#define APOTERM_RD_LCD_RDATA 0x3
/**** HD44780 ****/
-#define APOTERM_HD44780_DISP_SIZE (16*2)
+#define APOTERM_HD44780_DISP_COLS 16
+#define APOTERM_HD44780_DISP_LINES 2
+#define APOTERM_HD44780_DISP_SIZE (APOTERM_HD44780_DISP_COLS \
+ * APOTERM_HD44780_DISP_LINES)
/* RW bit */
#define APOTERM_HD44780_RD 0x1
typedef struct {
int poweron;
struct hd44780 {
+ /* Shifting not supported
+ CGRAM not supported
+ 4-bit interface not supported */
+
/* TO BE IMPLEMENTED IN FUTURE?
int CGROM[208+32];
int CGRAM[16];
int CGRAM_addr;
*/
int busyflag;
- int cursor_val;
int cursor_incr; /* Sets cursor move direction. This operation
is performed during data write and read. */
+ int display_lines; /* Real count of display lines -- not the "N" bit*/
int display_on;
- char DDRAM[APOTERM_HD44780_DISP_SIZE];
- int DDRAM_addr;
+#define APOTERM_HD44780_DDRAM_LINE1_START 0x0
+#define APOTERM_HD44780_DDRAM_LINE2_START 0x40
+#define APOTERM_HD44780_DDRAM_LINE_SIZE 0x27
+ uint8_t DDRAM[0x67]; /* Always this size -- not corresponding
+ to real display size */
+ unsigned int DDRAM_addr;
} lcd;
uint8_t led; /* LED reg */
uint8_t kbd; /* KBD reg */
int instance = 0; /* Shared among multiple APOHW devices */
#define DEFAULT_PORT 55555
-#define STR_BUFF 255
+#define STR_BUFF 256 // FIXME?
#define DEBUG_APOHW 1
#undef DEBUG_APOHW
{
apoterm_state_t *apoterm = &d->apoterm;
+ apoterm->lcd.busyflag = 0;
+ apoterm->lcd.DDRAM_addr = 0;
apoterm->lcd.cursor_incr = 1;
+ apoterm->lcd.display_lines = 1;
+}
+
+static void apoterm_hd44780_increment_DDRAM_addr(struct hd44780 *lcd)
+{
+ //printf("apoterm_hd44780_increment_DDRAM_addr invoked lcd->DDRAM_addr = 0x%x "
+ // "lcd->cursor_incr = %i\n", lcd->DDRAM_addr, lcd->cursor_incr);
+ /* Same for display_lines = 1 or 2 */
+ lcd->DDRAM_addr = ((lcd->DDRAM_addr + lcd->cursor_incr)
+ % APOTERM_HD44780_DDRAM_LINE_SIZE);
+}
+
+static int apoterm_hd44780_print(struct hd44780 *lcd, int line, char* buff)
+{
+ if (lcd->display_on != 1)
+ buff[0] = '\0';
+ return 0;
+
+ if (line == 1) {
+ memcpy(buff, &lcd->DDRAM[APOTERM_HD44780_DDRAM_LINE1_START],
+ APOTERM_HD44780_DISP_COLS);
+ buff[APOTERM_HD44780_DISP_COLS] = '\0';
+
+ return APOTERM_HD44780_DISP_COLS;
+ }
+
+ if (line == 2) {
+ memcpy(buff, &lcd->DDRAM[APOTERM_HD44780_DDRAM_LINE2_START],
+ APOTERM_HD44780_DISP_COLS);
+ buff[APOTERM_HD44780_DISP_COLS] = '\0';
+
+ return APOTERM_HD44780_DISP_COLS;
+ }
+
+ buff[0] = '\0';
+ return 0;
}
static int apoterm_hd44780(uint8_t data, int rw, int rs, struct hd44780 *lcd)
{
- printf("apoterm_hd44780 invoked. data = %i; rw = %i; rs = %i\n", data, rw, rs);
+ uint8_t ret;
+ //printf("apoterm_hd44780 invoked. data = %i; rw = %i; rs = %i\n", data, rw, rs);
if (rw == APOTERM_HD44780_WR) {
if (rs == APOTERM_HD44780_INSTREG) {
- if (data & APOTERM_HD44780_CLEAR_DISP_m) {
- lcd->cursor_val = 0;
- memset(lcd->DDRAM, 0, APOTERM_HD44780_DISP_SIZE);
+ printf("APOTERM_HD44780_WR INSTREG data = 0x%x\n", data);
- } else if (data & APOTERM_HD44780_RETURN_HOME_m) {
- lcd->cursor_val = 0;
+ /* Be aware of the sequence of checked conditions --
+ we must start from the mast with the "more significant" bits */
+ if (data & APOTERM_HD44780_SET_DDRAM_ADDR_m) {
+ lcd->DDRAM_addr = ((uint8_t)data & 0x7F);
- } else if (data & APOTERM_HD44780_ENTRY_MODE_SET_m) {
- if (data & (1 << 1)) /* Increment */
- lcd->cursor_incr = 1;
+ } else if (data & APOTERM_HD44780_SET_CGRAM_ADDR_m) {
+
+ } else if (data & APOTERM_HD44780_FUNCTION_SET_m) {
+ if (data & (1 << 4)) /* Sets interface data length */
+ {} // FIXME
+
+ if (data & (1 << 3)) /* Number of display lines */
+ lcd->display_lines = 2;
else
- lcd->cursor_incr = -1;
+ lcd->display_lines = 1;
- if (data & (1 << 0)) { /* Shifts the entire display ... */
- // FIXME
- }
+ if (data & (1 << 2)) /* Character font */
+ {} // FIXME
+
+ } else if (data & APOTERM_HD44780_CURSOR_DISPLAY_SHIFT_m) {
+ /* Cursor or Display Shift */
} else if (data & APOTERM_HD44780_DISPLAY_ON_OFF_m) {
- if (data & (1 << 2)) /* Display on */
+ if (data & (1 << 2)) { /* Display on */
lcd->display_on = 1;
- else
+ } else {
lcd->display_on = 0;
+ }
if (data & (1 << 1)) /* The cursor is displayed */
{} // FIXME
if (data & (1 << 0)) /* The character indicated by the cursor blinks */
{} // FIXME
- } else if (data & APOTERM_HD44780_CURSOR_DISPLAY_SHIFT_m) {
- /* Cursor or Display Shift */
+ } else if (data & APOTERM_HD44780_ENTRY_MODE_SET_m) {
+ if (data & (1 << 1)) /* Increment */
+ lcd->cursor_incr = 1;
+ else
+ lcd->cursor_incr = -1;
- } else if (data & APOTERM_HD44780_FUNCTION_SET_m) {
- /* Function set */
+ if (data & (1 << 0)) { /* Shifts the entire display ... */
+ // FIXME
+ }
- } else if (data & APOTERM_HD44780_SET_CGRAM_ADDR_m) {
+ } else if (data & APOTERM_HD44780_RETURN_HOME_m) {
+ lcd->DDRAM_addr = 0;
- } else if (data & APOTERM_HD44780_SET_DDRAM_ADDR_m) {
- lcd->DDRAM_addr = (data & 0x7F);
+ } else if (data & APOTERM_HD44780_CLEAR_DISP_m) {
+ lcd->DDRAM_addr = 0;
+ memset(lcd->DDRAM, 0, APOTERM_HD44780_DISP_SIZE);
}
+
}
if (rs == APOTERM_HD44780_DATREG) {
- lcd->cursor_val = (lcd->cursor_val + lcd->cursor_incr) % APOTERM_HD44780_DISP_SIZE;
- lcd->DDRAM[lcd->cursor_val] = data;
+ printf("APOTERM_HD44780_WR addr = 0x%x data = 0x%x\n", lcd->DDRAM_addr, (uint8_t)data);
+ lcd->DDRAM[lcd->DDRAM_addr] = (uint8_t)data;
+ apoterm_hd44780_increment_DDRAM_addr(lcd);
}
} else if (rw == APOTERM_HD44780_RD) {
if (rs == APOTERM_HD44780_DATREG) {
- return lcd->DDRAM[lcd->DDRAM_addr];
+ printf("APOTERM_HD44780_RD lcd->DDRAM_addr = 0x%x, data = 0x%x\n",
+ lcd->DDRAM_addr, (uint8_t)lcd->DDRAM[lcd->DDRAM_addr]);
+ ret = lcd->DDRAM[lcd->DDRAM_addr];
+ apoterm_hd44780_increment_DDRAM_addr(lcd);
+ return ret;
}
if (rs == APOTERM_HD44780_INSTREG) {
- return lcd->busyflag | lcd->cursor_val;
+ return lcd->busyflag | (lcd->DDRAM_addr & 0x7F);
}
}
apoio_state_t *apoio = &d->apoio;
char buff[STR_BUFF];
int i;
+ char lcd_buff[APOTERM_HD44780_DISP_COLS + 1];
snprintf(buff, STR_BUFF, "---------------------------------------------------\n");
socket_write(d, buff, strlen(buff));
}
socket_write(d, buff, strlen(buff));
- snprintf(buff, STR_BUFF, "LCD: %s\n",
- (apoterm->lcd.display_on == 1) ? apoterm->lcd.DDRAM : "");
+
+ apoterm_hd44780_print(&apoterm->lcd, 1, (char*)&lcd_buff);
+ snprintf(buff, STR_BUFF, "LCD1: %s\n", lcd_buff);
+ socket_write(d, buff, strlen(buff));
+
+ apoterm_hd44780_print(&apoterm->lcd, 2, (char*)&lcd_buff);
+ snprintf(buff, STR_BUFF, "LCD2: %s\n", lcd_buff);
socket_write(d, buff, strlen(buff));
}
}
apoterm_display_update(d);
- }
- /* (RD | CS0): H -> L */
- if (rd_en_old && !rd_en_new)
- {
+ } else if (rd_en_old && !rd_en_new) { /* (RD | CS0): H -> L */
switch (apoio->emul_bus_ctrl_new & APOTERM_ADDR_m) {
case APOTERM_RD_LCD_STAT:
- apoterm_hd44780(apoio->emul_bus_data_out,
+ apoio->emul_bus_data_in = apoterm_hd44780(0,
APOTERM_HD44780_RD,
APOTERM_HD44780_INSTREG,
&apoterm->lcd);
break;
case APOTERM_RD_LCD_RDATA:
- apoterm_hd44780(apoio->emul_bus_data_out,
+ apoio->emul_bus_data_in = apoterm_hd44780(0,
APOTERM_HD44780_RD,
APOTERM_HD44780_DATREG,
&apoterm->lcd);
DEBUG_PRINT("read addr = 0x%02x size = %u\n", (uint32_t)addr, size);
if (addr < APOIO_RAM_SIZE) {
- return d->apoio.ram[addr];
+ return (uint8_t)d->apoio.ram[addr];
} else if (addr == APOIO_EMUL_BUS_DATA_IN) {
- return d->apoio.emul_bus_data_in;
+ DEBUG_PRINT(" data = 0x%02x\n", (uint8_t)d->apoio.emul_bus_data_in);
+ return (uint8_t)d->apoio.emul_bus_data_in;
}
return 0;
if (d->apoio.emul_bus_ctrl_new != data) {
d->apoio.emul_bus_ctrl_old = d->apoio.emul_bus_ctrl_new;
d->apoio.emul_bus_ctrl_new = data;
+
+ upgrade_apoterm_state(d);
}
} else if (addr == APOIO_EMUL_BUS_DATA_OUT) {
d->apoio.emul_bus_data_out = data;
+ upgrade_apoterm_state(d);
} else if (addr == APOIO_LED_PIO) {
d->apoio.led_pio = (unsigned int) data;
printf(DEBUG_PREFIX "LED_PIO = 0x%X\n", d->apoio.led_pio);
}
- upgrade_apoterm_state(d);
}
static const MemoryRegionOps apoio_bar0_ops = {