src/mess/video/hd66421.c
| r13281 | r13282 | |
| 9 | 9 | #include "emu.h" |
| 10 | 10 | #include "hd66421.h" |
| 11 | 11 | |
| 12 | //************************************************************************** |
| 13 | // MACROS / CONSTANTS |
| 14 | //************************************************************************** |
| 15 | |
| 12 | 16 | #define LOG_LEVEL 1 |
| 13 | 17 | #define _logerror(level,x) do { if (LOG_LEVEL > level) logerror x; } while (0) |
| 14 | 18 | |
| 15 | | //#define BRIGHTNESS_DOES_NOT_WORK |
| 16 | | |
| 17 | 19 | #define HD66421_RAM_SIZE (HD66421_WIDTH * HD66421_HEIGHT / 4) // 2-bits per pixel |
| 18 | 20 | |
| 19 | 21 | // R0 - control register 1 |
| r13281 | r13282 | |
| 56 | 58 | #define LCD_REG_CONTRAST 0x10 // contrast control register |
| 57 | 59 | #define LCD_REG_PLANE 0x11 // plane selection register |
| 58 | 60 | |
| 59 | | typedef struct |
| 61 | //************************************************************************** |
| 62 | // GLOBAL VARIABLES |
| 63 | //************************************************************************** |
| 64 | |
| 65 | // devices |
| 66 | const device_type HD66421 = &device_creator<hd66421_device>; |
| 67 | |
| 68 | |
| 69 | // default address map |
| 70 | static ADDRESS_MAP_START( hd66421, AS_0, 8 ) |
| 71 | AM_RANGE(0x0000, HD66421_RAM_SIZE) AM_RAM |
| 72 | ADDRESS_MAP_END |
| 73 | |
| 74 | //------------------------------------------------- |
| 75 | // memory_space_config - return a description of |
| 76 | // any address spaces owned by this device |
| 77 | //------------------------------------------------- |
| 78 | |
| 79 | const address_space_config *hd66421_device::memory_space_config(address_spacenum spacenum) const |
| 60 | 80 | { |
| 61 | | UINT8 cmd, reg[32]; |
| 62 | | UINT8 *ram; |
| 63 | | int x, y; |
| 64 | | } HD66421; |
| 81 | return (spacenum == AS_0) ? &m_space_config : NULL; |
| 82 | } |
| 65 | 83 | |
| 66 | | static HD66421 lcd; |
| 67 | 84 | |
| 68 | | UINT8 hd66421_reg_idx_r(void) |
| 85 | //************************************************************************** |
| 86 | // INLINE HELPERS |
| 87 | //************************************************************************** |
| 88 | |
| 89 | //------------------------------------------------- |
| 90 | // readbyte - read a byte at the given address |
| 91 | //------------------------------------------------- |
| 92 | |
| 93 | inline UINT8 hd66421_device::readbyte(offs_t address) |
| 69 | 94 | { |
| 70 | | _logerror( 2, ("hd66421_reg_idx_r\n")); |
| 71 | | return lcd.cmd; |
| 95 | return space()->read_byte(address); |
| 72 | 96 | } |
| 73 | 97 | |
| 74 | | void hd66421_reg_idx_w(UINT8 data) |
| 98 | |
| 99 | //------------------------------------------------- |
| 100 | // writebyte - write a byte at the given address |
| 101 | //------------------------------------------------- |
| 102 | |
| 103 | inline void hd66421_device::writebyte(offs_t address, UINT8 data) |
| 75 | 104 | { |
| 76 | | _logerror( 2, ("hd66421_reg_idx_w (%02X)\n", data)); |
| 77 | | lcd.cmd = data; |
| 105 | space()->write_byte(address, data); |
| 78 | 106 | } |
| 79 | 107 | |
| 80 | | UINT8 hd66421_reg_dat_r(void) |
| 108 | |
| 109 | //************************************************************************** |
| 110 | // LIVE DEVICE |
| 111 | //************************************************************************** |
| 112 | |
| 113 | //------------------------------------------------- |
| 114 | // hd66421_device - constructor |
| 115 | //------------------------------------------------- |
| 116 | |
| 117 | hd66421_device::hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 118 | : device_t(mconfig, HD66421, "Hitachi HD66421 LCD Controller", tag, owner, clock), |
| 119 | device_memory_interface(mconfig, *this), |
| 120 | m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, NULL, *ADDRESS_MAP_NAME(hd66421)), |
| 121 | m_cmd(0), |
| 122 | m_x(0), |
| 123 | m_y(0) |
| 81 | 124 | { |
| 82 | | _logerror( 2, ("hd66421_reg_dat_r\n")); |
| 83 | | return lcd.reg[lcd.cmd]; |
| 125 | for (int i = 0; i < 32; i++) |
| 126 | { |
| 127 | m_reg[i] = 0; |
| 128 | } |
| 84 | 129 | } |
| 85 | 130 | |
| 86 | | void hd66421_reg_dat_w(UINT8 data) |
| 131 | |
| 132 | //------------------------------------------------- |
| 133 | // device_start - device-specific startup |
| 134 | //------------------------------------------------- |
| 135 | |
| 136 | void hd66421_device::device_start() |
| 137 | { |
| 138 | // register for state saving |
| 139 | save_item(NAME(m_cmd)); |
| 140 | save_item(NAME(m_reg)); |
| 141 | save_item(NAME(m_x)); |
| 142 | save_item(NAME(m_y)); |
| 143 | } |
| 144 | |
| 145 | READ8_MEMBER( hd66421_device::reg_idx_r ) |
| 87 | 146 | { |
| 88 | | _logerror( 2, ("hd66421_reg_dat_w (%02X)\n", data)); |
| 89 | | lcd.reg[lcd.cmd] = data; |
| 90 | | switch (lcd.cmd) |
| 147 | _logerror( 2, ("reg_idx_r\n")); |
| 148 | return m_cmd; |
| 149 | } |
| 150 | |
| 151 | WRITE8_MEMBER( hd66421_device::reg_idx_w ) |
| 152 | { |
| 153 | _logerror( 2, ("reg_idx_w (%02X)\n", data)); |
| 154 | m_cmd = data; |
| 155 | } |
| 156 | |
| 157 | READ8_MEMBER( hd66421_device::reg_dat_r ) |
| 158 | { |
| 159 | _logerror( 2, ("reg_dat_r\n")); |
| 160 | return m_reg[m_cmd]; |
| 161 | } |
| 162 | |
| 163 | WRITE8_MEMBER( hd66421_device::reg_dat_w ) |
| 164 | { |
| 165 | _logerror( 2, ("reg_dat_w (%02X)\n", data)); |
| 166 | m_reg[m_cmd] = data; |
| 167 | |
| 168 | switch (m_cmd) |
| 91 | 169 | { |
| 92 | 170 | case LCD_REG_ADDR_X : |
| 93 | | { |
| 94 | | lcd.x = data; |
| 95 | | } |
| 96 | | break; |
| 171 | m_x = data; |
| 172 | break; |
| 173 | |
| 97 | 174 | case LCD_REG_ADDR_Y : |
| 98 | | { |
| 99 | | lcd.y = data; |
| 100 | | } |
| 101 | | break; |
| 175 | m_y = data; |
| 176 | break; |
| 177 | |
| 102 | 178 | case LCD_REG_RAM : |
| 103 | 179 | { |
| 104 | 180 | UINT8 r1; |
| 105 | | *(lcd.ram + lcd.y * (HD66421_WIDTH / 4) + lcd.x) = data; |
| 106 | | r1 = lcd.reg[LCD_REG_CONTROL_2]; |
| 181 | writebyte(m_y * (HD66421_WIDTH / 4) + m_x, data); |
| 182 | r1 = m_reg[LCD_REG_CONTROL_2]; |
| 107 | 183 | if (r1 & 0x02) |
| 108 | | { |
| 109 | | lcd.x++; |
| 110 | | } |
| 184 | m_x++; |
| 111 | 185 | else |
| 186 | m_y++; |
| 187 | |
| 188 | if (m_x >= (HD66421_WIDTH / 4)) |
| 112 | 189 | { |
| 113 | | lcd.y++; |
| 190 | m_x = 0; |
| 191 | m_y++; |
| 114 | 192 | } |
| 115 | | if (lcd.x >= (HD66421_WIDTH / 4)) |
| 116 | | { |
| 117 | | lcd.x = 0; |
| 118 | | lcd.y++; |
| 119 | | } |
| 120 | | if (lcd.y >= HD66421_HEIGHT) |
| 121 | | { |
| 122 | | lcd.y = 0; |
| 123 | | } |
| 193 | |
| 194 | if (m_y >= HD66421_HEIGHT) |
| 195 | m_y = 0; |
| 124 | 196 | } |
| 125 | 197 | break; |
| 126 | 198 | } |
| 127 | 199 | } |
| 128 | 200 | |
| 129 | | INLINE void hd66421_plot_pixel(bitmap_t *bitmap, int x, int y, UINT32 color) |
| 201 | void hd66421_device::plot_pixel(bitmap_t *bitmap, int x, int y, UINT32 color) |
| 130 | 202 | { |
| 131 | | *BITMAP_ADDR16( bitmap, y, x) = (UINT16)color; |
| 203 | *BITMAP_ADDR16(bitmap, y, x) = (UINT16)color; |
| 132 | 204 | } |
| 133 | 205 | |
| 134 | | PALETTE_INIT( hd66421 ) |
| 206 | void hd66421_device::update_screen(bitmap_t *bitmap, const rectangle *cliprect) |
| 135 | 207 | { |
| 136 | | int i; |
| 137 | | _logerror( 0, ("palette_init_hd66421\n")); |
| 138 | | // init palette |
| 139 | | for (i=0;i<4;i++) |
| 140 | | { |
| 141 | | palette_set_color( machine, i, RGB_WHITE); |
| 142 | | #ifndef BRIGHTNESS_DOES_NOT_WORK |
| 143 | | palette_set_pen_contrast( machine, i, 1.0 * i / (4 - 1)); |
| 144 | | #endif |
| 145 | | } |
| 146 | | } |
| 208 | pen_t pen[4]; |
| 147 | 209 | |
| 148 | | static void hd66421_state_save(running_machine &machine) |
| 149 | | { |
| 150 | | const char *name = "hd66421"; |
| 151 | | state_save_register_item(machine, name, NULL, 0, lcd.cmd); |
| 152 | | state_save_register_item_array(machine, name, NULL, 0, lcd.reg); |
| 153 | | state_save_register_item(machine, name, NULL, 0, lcd.x); |
| 154 | | state_save_register_item(machine, name, NULL, 0, lcd.y); |
| 155 | | state_save_register_item_pointer(machine, name, NULL, 0, lcd.ram, HD66421_RAM_SIZE); |
| 156 | | } |
| 210 | _logerror( 1, ("video_update_hd66421\n")); |
| 157 | 211 | |
| 158 | | VIDEO_START( hd66421 ) |
| 159 | | { |
| 160 | | _logerror( 0, ("video_start_hd66421\n")); |
| 161 | | memset( &lcd, 0, sizeof( lcd)); |
| 162 | | lcd.ram = auto_alloc_array(machine, UINT8, HD66421_RAM_SIZE); |
| 163 | | hd66421_state_save(machine); |
| 164 | | } |
| 165 | | |
| 166 | | SCREEN_UPDATE( hd66421 ) |
| 167 | | { |
| 168 | | pen_t pen[4]; |
| 169 | | int i; |
| 170 | | _logerror( 1, ("video_update_hd66421\n")); |
| 171 | 212 | // update palette |
| 172 | | for (i=0;i<4;i++) |
| 213 | for (int i = 0; i < 4; i++) |
| 173 | 214 | { |
| 174 | 215 | double bright; |
| 175 | 216 | int temp; |
| 176 | | temp = 31 - (lcd.reg[LCD_REG_COLOR_1+i] - lcd.reg[LCD_REG_CONTRAST] + 0x03); |
| 217 | temp = 31 - (m_reg[LCD_REG_COLOR_1 + i] - m_reg[LCD_REG_CONTRAST] + 0x03); |
| 177 | 218 | if (temp < 0) temp = 0; |
| 178 | 219 | if (temp > 31) temp = 31; |
| 179 | 220 | bright = 1.0 * temp / 31; |
| 180 | 221 | pen[i] = i; |
| 181 | | #ifdef BRIGHTNESS_DOES_NOT_WORK |
| 182 | | palette_set_color(screen->machine(), pen[i], 255 * bright, 255 * bright, 255 * bright); |
| 222 | #ifdef HD66421_BRIGHTNESS_DOES_NOT_WORK |
| 223 | palette_set_color(machine(), pen[i], 255 * bright, 255 * bright, 255 * bright); |
| 183 | 224 | #else |
| 184 | | palette_set_pen_contrast(screen->machine(), pen[i], bright); |
| 225 | palette_set_pen_contrast(machine(), pen[i], bright); |
| 185 | 226 | #endif |
| 186 | 227 | } |
| 228 | |
| 187 | 229 | // draw bitmap (bottom to top) |
| 188 | | if (lcd.reg[0] & LCD_R0_DISP) |
| 230 | if (m_reg[0] & LCD_R0_DISP) |
| 189 | 231 | { |
| 190 | 232 | int x, y; |
| 191 | 233 | x = 0; |
| 192 | 234 | y = HD66421_HEIGHT - 1; |
| 193 | | for (i=0;i<HD66421_RAM_SIZE;i++) |
| 235 | |
| 236 | for (int i = 0; i < HD66421_RAM_SIZE; i++) |
| 194 | 237 | { |
| 195 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 6) & 3]); |
| 196 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 4) & 3]); |
| 197 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 2) & 3]); |
| 198 | | hd66421_plot_pixel( bitmap, x++, y, pen[(lcd.ram[i] >> 0) & 3]); |
| 238 | plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 6) & 3]); |
| 239 | plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 4) & 3]); |
| 240 | plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 2) & 3]); |
| 241 | plot_pixel(bitmap, x++, y, pen[(readbyte(i) >> 0) & 3]); |
| 199 | 242 | if (x >= HD66421_WIDTH) |
| 200 | 243 | { |
| 201 | 244 | x = 0; |
| r13281 | r13282 | |
| 210 | 253 | rect.max_x = HD66421_WIDTH - 1; |
| 211 | 254 | rect.min_y = 0; |
| 212 | 255 | rect.max_y = HD66421_HEIGHT - 1; |
| 213 | | bitmap_fill( bitmap, &rect, get_white_pen(screen->machine())); |
| 256 | bitmap_fill(bitmap, &rect, get_white_pen(machine())); |
| 214 | 257 | } |
| 215 | | // flags |
| 216 | | return 0; |
| 217 | 258 | } |
src/mess/video/hd66421.h
| r13281 | r13282 | |
| 1 | | /* |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Hitachi HD66421 LCD Controller |
| 2 | 4 | |
| 3 | | Hitachi HD66421 LCD Controller/Driver |
| 5 | (c) 2001-2007 Tim Schuerewegen |
| 4 | 6 | |
| 5 | | (c) 2001-2007 Tim Schuerewegen |
| 7 | ***************************************************************************/ |
| 6 | 8 | |
| 7 | | */ |
| 9 | #pragma once |
| 8 | 10 | |
| 9 | | #ifndef HD66421_H_ |
| 10 | | #define HD66421_H_ |
| 11 | #ifndef __HD66421_H__ |
| 12 | #define __HD66421_H__ |
| 11 | 13 | |
| 12 | 14 | |
| 15 | ///************************************************************************* |
| 16 | // MACROS / CONSTANTS |
| 17 | ///************************************************************************* |
| 18 | |
| 19 | //#define HD66421_BRIGHTNESS_DOES_NOT_WORK |
| 20 | |
| 13 | 21 | #define HD66421_WIDTH 160 |
| 14 | 22 | #define HD66421_HEIGHT 100 |
| 15 | 23 | |
| 16 | 24 | |
| 17 | 25 | /*----------- defined in video/hd66421.c -----------*/ |
| 18 | 26 | |
| 19 | | UINT8 hd66421_reg_idx_r(void); |
| 20 | | void hd66421_reg_idx_w(UINT8 data); |
| 27 | ///************************************************************************* |
| 28 | // INTERFACE CONFIGURATION MACROS |
| 29 | ///************************************************************************* |
| 21 | 30 | |
| 22 | | UINT8 hd66421_reg_dat_r(void); |
| 23 | | void hd66421_reg_dat_w(UINT8 data); |
| 31 | #define MCFG_HD66421_ADD(_tag) \ |
| 32 | MCFG_DEVICE_ADD(_tag, HD66421, 0) \ |
| 24 | 33 | |
| 25 | | PALETTE_INIT( hd66421 ); |
| 26 | 34 | |
| 27 | | VIDEO_START( hd66421 ); |
| 28 | | SCREEN_UPDATE( hd66421 ); |
| 35 | ///************************************************************************* |
| 36 | // TYPE DEFINITIONS |
| 37 | ///************************************************************************* |
| 29 | 38 | |
| 39 | // ======================> hd66421_device |
| 30 | 40 | |
| 31 | | #endif /* HD66421_H_ */ |
| 41 | class hd66421_device : public device_t, |
| 42 | public device_memory_interface |
| 43 | { |
| 44 | public: |
| 45 | // construction/destruction |
| 46 | hd66421_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 47 | |
| 48 | DECLARE_READ8_MEMBER( reg_idx_r ); |
| 49 | DECLARE_WRITE8_MEMBER( reg_idx_w ); |
| 50 | DECLARE_READ8_MEMBER( reg_dat_r ); |
| 51 | DECLARE_WRITE8_MEMBER( reg_dat_w ); |
| 52 | |
| 53 | void update_screen(bitmap_t *bitmap, const rectangle *cliprect); |
| 54 | |
| 55 | protected: |
| 56 | // device-level overrides |
| 57 | virtual void device_start(); |
| 58 | |
| 59 | // device_config_memory_interface overrides |
| 60 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; |
| 61 | |
| 62 | // address space configurations |
| 63 | const address_space_config m_space_config; |
| 64 | |
| 65 | inline UINT8 readbyte(offs_t address); |
| 66 | inline void writebyte(offs_t address, UINT8 data); |
| 67 | |
| 68 | void plot_pixel(bitmap_t *bitmap, int x, int y, UINT32 color); |
| 69 | |
| 70 | private: |
| 71 | UINT8 m_cmd, m_reg[32]; |
| 72 | int m_x, m_y; |
| 73 | }; |
| 74 | |
| 75 | |
| 76 | // device type definition |
| 77 | extern const device_type HD66421; |
| 78 | |
| 79 | |
| 80 | #endif |