From a2739c054c27f6bf62498a7a2fc5f77917928350 Mon Sep 17 00:00:00 2001 From: Keith Bourdon <33245078+celerizer@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:03:29 -0500 Subject: [PATCH] start working on lcd commands --- devices/lcd.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 4 deletions(-) diff --git a/devices/lcd.c b/devices/lcd.c index a92ce8c..6521c49 100644 --- a/devices/lcd.c +++ b/devices/lcd.c @@ -1,14 +1,56 @@ #include "../dma.h" #include "lcd.h" +#include "../types.h" static const char *name = "128x64 LCD device"; static const h8_device_id type = H8_DEVICE_LCD; +typedef union +{ + H8_BITFIELD_4 + ( + /** Hardcoded chip ID */ + h8_u8 id : 4, + + /** Whether the device is busy with a reset. Unimplemented */ + h8_u8 res : 1, + + /** Whether the device is on */ + h8_u8 on : 1, + + /** Whether the device is busy with a command. Unimplemented */ + h8_u8 bsy : 1 + ) flags; + h8_u8 raw; +} h8_lcd_sr_t; + typedef struct { h8_u8 vram[128 * 64]; h8_bool selected; h8_bool mode; + h8_u8 command; + h8_bool second_byte; + + h8_u8 x, y; + + /** @todo What is this? */ + h8_bool icon_enable; + + /** If true, displays all pixels on regardless of VRAM contents */ + h8_bool all_on; + + h8_bool inverse_display; + + h8_bool power_save; + + /** If true, the display will sleep when power save is enabled. + * If false, the display will standby. */ + h8_bool power_save_mode_sleep; + + h8_bool x_flip, y_flip; + + h8_lcd_sr_t status; } h8_lcd_t; #define H8_LCD_MODE_CMD 0 @@ -32,16 +74,136 @@ void h8_lcd_read(h8_device_t *device, h8_byte_t *dst) { h8_lcd_t *m_lcd = device->device; - /** @todo */ - dst->u = m_lcd->vram[0]; + if (m_lcd->mode) + dst->u = m_lcd->status.raw; + else + /** @todo */ + dst->u = 0; } void h8_lcd_write(h8_device_t *device, h8_byte_t *dst, const h8_byte_t value) { h8_lcd_t *m_lcd = device->device; - /** @todo */ - m_lcd->vram[0] = value.u; + if (!m_lcd->second_byte) + { + m_lcd->command = value.u; + switch (m_lcd->command) + { + /** Set Column Address bit0-3 */ + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + m_lcd->x = (m_lcd->x & B01110000) | value.u; + break; + /** Set Column Address bit4-6 */ + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + m_lcd->x = (m_lcd->x & B00001111) | ((value.u & B00000111) << 4); + break; + case 0xA2: + m_lcd->icon_enable = FALSE; + break; + case 0xA3: + m_lcd->icon_enable = TRUE; + break; + case 0xA4: + m_lcd->status.flags.on = FALSE; + break; + case 0xA5: + m_lcd->status.flags.on = TRUE; + break; + case 0xA6: + m_lcd->inverse_display = FALSE; + break; + case 0xA7: + m_lcd->inverse_display = TRUE; + break; + case 0xA8: + m_lcd->power_save_mode_sleep = FALSE; + break; + case 0xA9: + m_lcd->power_save_mode_sleep = TRUE; + break; + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + m_lcd->y = (value.u & B00001111) * 8; + break; + case 0xC0: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + m_lcd->y_flip = FALSE; + break; + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + m_lcd->y_flip = TRUE; + break; + case 0xE1: + m_lcd->power_save = FALSE; + break; + /** Software Reset */ + case 0xE2: + /** @todo set defaults */ + break; + default: + break; + } + } + else + { + switch (m_lcd->command) + { + default: + break; + } + m_lcd->second_byte = FALSE; + } + + *dst = value; } void h8_lcd_init(h8_device_t *device) @@ -50,6 +212,9 @@ void h8_lcd_init(h8_device_t *device) { h8_lcd_t *m_lcd = h8_dma_alloc(sizeof(h8_lcd_t), TRUE); + m_lcd->status.flags.on = TRUE; + m_lcd->status.flags.id = 0x08; + device->device = m_lcd; device->read = h8_lcd_read; device->write = h8_lcd_write;