src/mess/video/hd44780.c
| r0 | r9039 | |
| 1 | /***************************************************************************
|
| 2 | |
| 3 | Hitachi HD44780 LCD controller
|
| 4 | |
| 5 | TODO:
|
| 6 | - 4-bit mode
|
| 7 | - 5x10 chars
|
| 8 | - dump internal CGROM
|
| 9 | |
| 10 | ***************************************************************************/
|
| 11 | |
| 12 | #include "emu.h"
|
| 13 | #include "video/hd44780.h"
|
| 14 | |
| 15 | |
| 16 | //**************************************************************************
|
| 17 | // device configuration
|
| 18 | //**************************************************************************
|
| 19 | |
| 20 | //-------------------------------------------------
|
| 21 | // hd44780_device_config - constructor
|
| 22 | //-------------------------------------------------
|
| 23 | |
| 24 | hd44780_device_config::hd44780_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock ):
|
| 25 | device_config( mconfig, static_alloc_device_config, "HD44780", tag, owner, clock)
|
| 26 | {
|
| 27 | }
|
| 28 | |
| 29 | |
| 30 | //-------------------------------------------------
|
| 31 | // static_alloc_device_config - allocate a new
|
| 32 | // configuration object
|
| 33 | //-------------------------------------------------
|
| 34 | |
| 35 | device_config *hd44780_device_config::static_alloc_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock )
|
| 36 | {
|
| 37 | return global_alloc( hd44780_device_config( mconfig, tag, owner, clock ) );
|
| 38 | }
|
| 39 | |
| 40 | |
| 41 | //-------------------------------------------------
|
| 42 | // alloc_device - allocate a new device object
|
| 43 | //-------------------------------------------------
|
| 44 | |
| 45 | device_t *hd44780_device_config::alloc_device( running_machine &machine ) const
|
| 46 | {
|
| 47 | return auto_alloc( &machine, hd44780_device( machine, *this ) );
|
| 48 | }
|
| 49 | |
| 50 | //-------------------------------------------------
|
| 51 | // device_config_complete - perform any
|
| 52 | // operations now that the configuration is
|
| 53 | // complete
|
| 54 | //-------------------------------------------------
|
| 55 | |
| 56 | void hd44780_device_config::device_config_complete()
|
| 57 | {
|
| 58 | // inherit a copy of the static data
|
| 59 | const hd44780_interface *intf = reinterpret_cast<const hd44780_interface *>(static_config());
|
| 60 | |
| 61 | if (intf != NULL)
|
| 62 | *static_cast<hd44780_interface *>(this) = *intf;
|
| 63 | |
| 64 | // or initialize to defaults if none provided
|
| 65 | else
|
| 66 | {
|
| 67 | height = width = 0;
|
| 68 | custom_layout = NULL;
|
| 69 | }
|
| 70 | }
|
| 71 | |
| 72 | //-------------------------------------------------
|
| 73 | // device_validity_check - perform validity checks
|
| 74 | // on this device
|
| 75 | //-------------------------------------------------
|
| 76 | |
| 77 | bool hd44780_device_config::device_validity_check( const game_driver &driver ) const
|
| 78 | {
|
| 79 | bool error = false;
|
| 80 | |
| 81 | // display with more than 2 lines requires a layout
|
| 82 | if ((custom_layout == NULL && height > 2) || height == 0 || width == 0)
|
| 83 | {
|
| 84 | mame_printf_error("%s: %s device '%s' has invalid parameter\n", driver.source_file, driver.name, tag());
|
| 85 | error = true;
|
| 86 | }
|
| 87 | |
| 88 | return error;
|
| 89 | }
|
| 90 | |
| 91 | //**************************************************************************
|
| 92 | // live device
|
| 93 | //**************************************************************************
|
| 94 | |
| 95 | //-------------------------------------------------
|
| 96 | // hd44780_device - constructor
|
| 97 | //-------------------------------------------------
|
| 98 | |
| 99 | hd44780_device::hd44780_device( running_machine &_machine, const hd44780_device_config &config ) :
|
| 100 | device_t( _machine, config ),
|
| 101 | m_config( config )
|
| 102 | {
|
| 103 | }
|
| 104 | |
| 105 | |
| 106 | //-------------------------------------------------
|
| 107 | // device_start - device-specific startup
|
| 108 | //-------------------------------------------------
|
| 109 | |
| 110 | void hd44780_device::device_start()
|
| 111 | {
|
| 112 | busy_timer = timer_alloc(&m_machine, bf_clear, this);
|
| 113 | |
| 114 | timer_pulse(&m_machine, ATTOTIME_IN_MSEC(500), this, 0, blink_timer);
|
| 115 | |
| 116 | chargen = memory_region(&m_machine, "chargen");
|
| 117 | |
| 118 | state_save_register_device_item( this, 0, ac);
|
| 119 | state_save_register_device_item( this, 0, ac_mode);
|
| 120 | state_save_register_device_item( this, 0, data_bus_flag);
|
| 121 | state_save_register_device_item( this, 0, cursor_pos);
|
| 122 | state_save_register_device_item( this, 0, display_on);
|
| 123 | state_save_register_device_item( this, 0, cursor_on);
|
| 124 | state_save_register_device_item( this, 0, shift_on);
|
| 125 | state_save_register_device_item( this, 0, blink_on);
|
| 126 | state_save_register_device_item( this, 0, direction);
|
| 127 | state_save_register_device_item( this, 0, data_len);
|
| 128 | state_save_register_device_item( this, 0, n_line);
|
| 129 | state_save_register_device_item( this, 0, char_size);
|
| 130 | state_save_register_device_item( this, 0, disp_shift);
|
| 131 | state_save_register_device_item( this, 0, blink);
|
| 132 | state_save_register_device_item_array( this, 0, ddram);
|
| 133 | state_save_register_device_item_array( this, 0, cgram);
|
| 134 | }
|
| 135 | |
| 136 | |
| 137 | //-------------------------------------------------
|
| 138 | // device_reset - device-specific reset
|
| 139 | //-------------------------------------------------
|
| 140 | |
| 141 | void hd44780_device::device_reset()
|
| 142 | {
|
| 143 | busy_flag = 0;
|
| 144 | |
| 145 | memset(ddram, 0, ARRAY_LENGTH(ddram));
|
| 146 | memset(cgram, 0, ARRAY_LENGTH(cgram));
|
| 147 | ac = 0;
|
| 148 | ac_mode = 0;
|
| 149 | data_bus_flag = 0;
|
| 150 | cursor_pos = 0;
|
| 151 | display_on = 0;
|
| 152 | cursor_on = 0;
|
| 153 | shift_on = 0;
|
| 154 | blink_on = 0;
|
| 155 | direction = 1;
|
| 156 | data_len = 1;
|
| 157 | n_line = 0;
|
| 158 | char_size = 0;
|
| 159 | disp_shift = 0;
|
| 160 | blink = 0;
|
| 161 | |
| 162 | set_busy_flag(1520);
|
| 163 | }
|
| 164 | |
| 165 | |
| 166 | //**************************************************************************
|
| 167 | // device interface
|
| 168 | //**************************************************************************
|
| 169 | |
| 170 | int hd44780_device::video_update(bitmap_t *bitmap, const rectangle *cliprect)
|
| 171 | {
|
| 172 | assert(m_config.height*9 <= bitmap->height && m_config.width*6 <= bitmap->width);
|
| 173 | |
| 174 | bitmap_fill(bitmap, cliprect, 0);
|
| 175 | |
| 176 | if (display_on)
|
| 177 | for (int l=0; l<m_config.height; l++)
|
| 178 | for (int i=0; i<m_config.width; i++)
|
| 179 | {
|
| 180 | UINT8 line_base = l * 0x40;
|
| 181 | UINT8 line_size = (n_line) ? 40 : 80;
|
| 182 | INT8 char_pos = line_base + i;
|
| 183 | |
| 184 | // if specified uses the custom layout
|
| 185 | if (m_config.custom_layout != NULL)
|
| 186 | char_pos = m_config.custom_layout[l*m_config.width + i];
|
| 187 | else
|
| 188 | {
|
| 189 | char_pos += disp_shift;
|
| 190 | |
| 191 | while (char_pos < 0 || (char_pos - line_base) >= line_size)
|
| 192 | {
|
| 193 | if (char_pos < 0)
|
| 194 | char_pos += line_size;
|
| 195 | else if (char_pos - line_base >= line_size)
|
| 196 | char_pos -= line_size;
|
| 197 | }
|
| 198 | }
|
| 199 | |
| 200 | for (int y=0; y<8; y++)
|
| 201 | for (int x=0; x<5; x++)
|
| 202 | if (ddram[char_pos] <= 0x10)
|
| 203 | {
|
| 204 | //draw CGRAM characters
|
| 205 | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(cgram[(ddram[char_pos]&0x07)*8+y], 4-x);
|
| 206 | }
|
| 207 | else
|
| 208 | {
|
| 209 | //draw CGROM characters
|
| 210 | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(chargen[(ddram[char_pos]-0x20)*8+y], 4-x);
|
| 211 | }
|
| 212 | |
| 213 | // if is the correct position draw cursor and blink
|
| 214 | if (char_pos == cursor_pos)
|
| 215 | {
|
| 216 | //draw the cursor
|
| 217 | if (cursor_on)
|
| 218 | for (int x=0; x<5; x++)
|
| 219 | *BITMAP_ADDR16(bitmap, l*9 + 7, i * 6 + x) = 1;
|
| 220 | |
| 221 | if (!blink && blink_on)
|
| 222 | for (int y=0; y<7; y++)
|
| 223 | for (int x=0; x<5; x++)
|
| 224 | *BITMAP_ADDR16(bitmap, l*9 + y, i * 6 + x) = 1;
|
| 225 | }
|
| 226 | }
|
| 227 | |
| 228 | return 0;
|
| 229 | |
| 230 | }
|
| 231 | |
| 232 | void hd44780_device::control_write(offs_t offset, UINT8 data)
|
| 233 | {
|
| 234 | if (BIT(data, 7))
|
| 235 | {
|
| 236 | ac_mode = 0;
|
| 237 | ac = data & 0x7f;
|
| 238 | if (data != 0x81)
|
| 239 | cursor_pos = ac;
|
| 240 | set_busy_flag(37);
|
| 241 | }
|
| 242 | else if (BIT(data, 6))
|
| 243 | {
|
| 244 | ac_mode = 1;
|
| 245 | ac = data & 0x3f;
|
| 246 | set_busy_flag(37);
|
| 247 | }
|
| 248 | else if (BIT(data, 5))
|
| 249 | {
|
| 250 | data_len = BIT(data, 4);
|
| 251 | n_line = BIT(data, 3);
|
| 252 | char_size = BIT(data, 2);
|
| 253 | set_busy_flag(37);
|
| 254 | }
|
| 255 | else if (BIT(data, 4))
|
| 256 | {
|
| 257 | UINT8 direct = (BIT(data, 2)) ? +1 : -1;
|
| 258 | |
| 259 | if (BIT(data, 3))
|
| 260 | disp_shift += direct;
|
| 261 | else
|
| 262 | {
|
| 263 | ac += direct;
|
| 264 | cursor_pos += direct;
|
| 265 | }
|
| 266 | |
| 267 | set_busy_flag(37);
|
| 268 | }
|
| 269 | else if (BIT(data, 3))
|
| 270 | {
|
| 271 | display_on = BIT(data, 2);
|
| 272 | cursor_on = BIT(data, 1);
|
| 273 | blink_on = BIT(data, 0);
|
| 274 | |
| 275 | set_busy_flag(37);
|
| 276 | }
|
| 277 | else if (BIT(data, 2))
|
| 278 | {
|
| 279 | direction = (BIT(data, 1)) ? +1 : -1;
|
| 280 | |
| 281 | shift_on = BIT(data, 0);
|
| 282 | |
| 283 | set_busy_flag(37);
|
| 284 | }
|
| 285 | else if (BIT(data, 1))
|
| 286 | {
|
| 287 | ac = 0;
|
| 288 | cursor_pos = 0;
|
| 289 | ac_mode = 0;
|
| 290 | direction = 1;
|
| 291 | disp_shift = 0;
|
| 292 | set_busy_flag(1520);
|
| 293 | }
|
| 294 | else if (BIT(data, 0))
|
| 295 | {
|
| 296 | ac = 0;
|
| 297 | cursor_pos = 0;
|
| 298 | ac_mode = 0;
|
| 299 | direction = 1;
|
| 300 | disp_shift = 0;
|
| 301 | memset(ddram, 0x20, ARRAY_LENGTH(ddram));
|
| 302 | memset(cgram, 0x20, ARRAY_LENGTH(cgram));
|
| 303 | set_busy_flag(1520);
|
| 304 | }
|
| 305 | }
|
| 306 | |
| 307 | UINT8 hd44780_device::control_read(offs_t offset)
|
| 308 | {
|
| 309 | return busy_flag<<7 || ac&0x7f;
|
| 310 | }
|
| 311 | |
| 312 | void hd44780_device::data_write(offs_t offset, UINT8 data)
|
| 313 | {
|
| 314 | if (ac_mode == 0)
|
| 315 | ddram[ac] = data;
|
| 316 | else
|
| 317 | cgram[ac] = data;
|
| 318 | |
| 319 | data_bus_flag = 1;
|
| 320 | |
| 321 | set_busy_flag(41);
|
| 322 | }
|
| 323 | |
| 324 | UINT8 hd44780_device::data_read(offs_t offset)
|
| 325 | {
|
| 326 | UINT8 data;
|
| 327 | |
| 328 | if (ac_mode == 0)
|
| 329 | data = ddram[ac];
|
| 330 | else
|
| 331 | data = cgram[ac];
|
| 332 | |
| 333 | data_bus_flag = 2;
|
| 334 | |
| 335 | set_busy_flag(41);
|
| 336 | |
| 337 | return data;
|
| 338 | }
|
| 339 | |
| 340 | |
| 341 | //**************************************************************************
|
| 342 | // internal helpers
|
| 343 | //**************************************************************************
|
| 344 | |
| 345 | void hd44780_device::set_busy_flag(UINT16 usec)
|
| 346 | {
|
| 347 | busy_flag = 1;
|
| 348 | |
| 349 | timer_adjust_oneshot( busy_timer, ATTOTIME_IN_USEC( usec ), 0 );
|
| 350 | }
|
| 351 | |
| 352 | TIMER_CALLBACK( hd44780_device::bf_clear )
|
| 353 | {
|
| 354 | hd44780_device *hd44780 = reinterpret_cast<hd44780_device *>(ptr);
|
| 355 | |
| 356 | if (hd44780->data_bus_flag)
|
| 357 | {
|
| 358 | int new_ac = hd44780->ac + hd44780->direction;
|
| 359 | |
| 360 | hd44780->ac = (new_ac < 0) ? 0 : ((new_ac > 0x7f) ? 0x7f : new_ac);
|
| 361 | |
| 362 | if (hd44780->ac_mode == 0)
|
| 363 | {
|
| 364 | hd44780->cursor_pos = hd44780->ac;
|
| 365 | |
| 366 | // display is shifted only after a write
|
| 367 | if (hd44780->shift_on && hd44780->data_bus_flag == 1)
|
| 368 | hd44780->disp_shift += hd44780->direction;
|
| 369 | }
|
| 370 | |
| 371 | hd44780->data_bus_flag = 0;
|
| 372 | }
|
| 373 | |
| 374 | hd44780->busy_flag = 0;
|
| 375 | }
|
| 376 | |
| 377 | TIMER_CALLBACK( hd44780_device::blink_timer )
|
| 378 | {
|
| 379 | hd44780_device *hd44780 = reinterpret_cast<hd44780_device *>(ptr);
|
| 380 | |
| 381 | hd44780->blink = ~hd44780->blink;
|
| 382 | }
|
| 383 | |
| 384 | //**************************************************************************
|
| 385 | // READ/WRITE HANDLERS
|
| 386 | //**************************************************************************
|
| 387 | |
| 388 | WRITE8_DEVICE_HANDLER( hd44780_control_w )
|
| 389 | {
|
| 390 | downcast<hd44780_device *>( device )->control_write( offset, data );
|
| 391 | }
|
| 392 | |
| 393 | WRITE8_DEVICE_HANDLER( hd44780_data_w )
|
| 394 | {
|
| 395 | downcast<hd44780_device *>( device )->data_write( offset, data );
|
| 396 | }
|
| 397 | |
| 398 | READ8_DEVICE_HANDLER( hd44780_control_r )
|
| 399 | {
|
| 400 | return downcast<hd44780_device *>( device )->control_read( offset );
|
| 401 | }
|
| 402 | |
| 403 | READ8_DEVICE_HANDLER( hd44780_data_r )
|
| 404 | {
|
| 405 | return downcast<hd44780_device *>( device )->data_read( offset );
|
| 406 | }
|
| 407 | |
| 408 | const device_type HD44780 = hd44780_device_config::static_alloc_device_config;
|
src/mess/video/hd44780.h
| r0 | r9039 | |
| 1 | /***************************************************************************
|
| 2 | |
| 3 | Hitachi HD44780 LCD controller
|
| 4 | |
| 5 | ***************************************************************************/
|
| 6 | |
| 7 | #pragma once
|
| 8 | |
| 9 | #ifndef __HD44780_H__
|
| 10 | #define __HD44780_H__
|
| 11 | |
| 12 | |
| 13 | #define MDRV_HD44780_ADD( _tag , _config) \
|
| 14 | MDRV_DEVICE_ADD( _tag, HD44780, 0 ) \
|
| 15 | MDRV_DEVICE_CONFIG(_config)
|
| 16 | |
| 17 | //**************************************************************************
|
| 18 | // TYPE DEFINITIONS
|
| 19 | //**************************************************************************
|
| 20 | |
| 21 | // ======================> hd44780_interface
|
| 22 | |
| 23 | struct hd44780_interface
|
| 24 | {
|
| 25 | UINT8 height; // number of lines
|
| 26 | UINT8 width; // chars for line
|
| 27 | UINT8 *custom_layout; // custom display layout (NULL for default)
|
| 28 | };
|
| 29 | |
| 30 | |
| 31 | // ======================> hd44780_device_config
|
| 32 | |
| 33 | class hd44780_device_config :
|
| 34 | public device_config,
|
| 35 | public hd44780_interface
|
| 36 | {
|
| 37 | friend class hd44780_device;
|
| 38 | |
| 39 | // construction/destruction
|
| 40 | hd44780_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock );
|
| 41 | |
| 42 | public:
|
| 43 | // allocators
|
| 44 | static device_config *static_alloc_device_config( const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock );
|
| 45 | virtual device_t *alloc_device( running_machine &machine ) const;
|
| 46 | |
| 47 | protected:
|
| 48 | // device_config overrides
|
| 49 | virtual void device_config_complete();
|
| 50 | virtual bool device_validity_check( const game_driver &driver ) const;
|
| 51 | };
|
| 52 | |
| 53 | |
| 54 | // ======================> hd44780_device
|
| 55 | |
| 56 | class hd44780_device :
|
| 57 | public device_t
|
| 58 | {
|
| 59 | friend class hd44780_device_config;
|
| 60 | |
| 61 | // construction/destruction
|
| 62 | hd44780_device( running_machine &_machine, const hd44780_device_config &config );
|
| 63 | |
| 64 | public:
|
| 65 | // device interface
|
| 66 | void control_write(offs_t offset, UINT8 data);
|
| 67 | UINT8 control_read(offs_t offset);
|
| 68 | void data_write(offs_t offset, UINT8 data);
|
| 69 | UINT8 data_read(offs_t offset);
|
| 70 | |
| 71 | int video_update(bitmap_t *bitmap, const rectangle *cliprect);
|
| 72 | |
| 73 | protected:
|
| 74 | // device-level overrides
|
| 75 | virtual void device_start();
|
| 76 | virtual void device_reset();
|
| 77 | |
| 78 | // internal helper
|
| 79 | static TIMER_CALLBACK( bf_clear );
|
| 80 | static TIMER_CALLBACK( blink_timer );
|
| 81 | |
| 82 | void set_busy_flag(UINT16 usec);
|
| 83 | |
| 84 | // internal state
|
| 85 | const hd44780_device_config &m_config;
|
| 86 | |
| 87 | emu_timer *busy_timer;
|
| 88 | UINT8 *chargen;
|
| 89 | UINT8 busy_flag;
|
| 90 | |
| 91 | UINT8 ddram[0x80]; //internal display data RAM
|
| 92 | UINT8 cgram[0x40]; //internal chargen RAM
|
| 93 | |
| 94 | INT8 ac; //address counter
|
| 95 | UINT8 ac_mode; //0=DDRAM 1=CGRAM
|
| 96 | UINT8 data_bus_flag;//0=none 1=write 2=read
|
| 97 | |
| 98 | INT8 cursor_pos; //cursor position
|
| 99 | UINT8 display_on; //display on/off
|
| 100 | UINT8 cursor_on; //cursor on/off
|
| 101 | UINT8 blink_on; //blink on/off
|
| 102 | UINT8 shift_on; //shift on/off
|
| 103 | INT8 disp_shift; //display shift
|
| 104 | |
| 105 | INT8 direction; //auto increment/decrement
|
| 106 | UINT8 data_len; //interface data length 4 or 8 bit
|
| 107 | UINT8 n_line; //number of lines
|
| 108 | UINT8 char_size; //char size 5x8 or 5x10
|
| 109 | |
| 110 | UINT8 blink;
|
| 111 | };
|
| 112 | |
| 113 | // device type definition
|
| 114 | extern const device_type HD44780;
|
| 115 | |
| 116 | |
| 117 | //**************************************************************************
|
| 118 | // READ/WRITE HANDLERS
|
| 119 | //**************************************************************************
|
| 120 | |
| 121 | WRITE8_DEVICE_HANDLER( hd44780_control_w );
|
| 122 | WRITE8_DEVICE_HANDLER( hd44780_data_w );
|
| 123 | READ8_DEVICE_HANDLER( hd44780_control_r );
|
| 124 | READ8_DEVICE_HANDLER( hd44780_data_r );
|
| 125 | |
| 126 | #endif
|
src/mess/drivers/psion.c
| r9038 | r9039 | |
| 25 | 25 | #include "cpu/m6800/m6800.h" |
| 26 | 26 | #include "sound/beep.h" |
| 27 | 27 | #include "devices/cartslot.h" |
| 28 | #include "video/hd44780.h" |
| 28 | 29 | |
| 29 | 30 | struct datapack |
| 30 | 31 | { |
| r9038 | r9039 | |
| 60 | 61 | struct datapack pack2; |
| 61 | 62 | } psion; |
| 62 | 63 | |
| 63 | | /************************************************* |
| 64 | | |
| 65 | | Hitachi HD44780 LCD controller implemantation |
| 66 | | |
| 67 | | *************************************************/ |
| 68 | | |
| 69 | | static struct _hd44780 |
| 70 | | { |
| 71 | | UINT8 busy_flag; |
| 72 | | |
| 73 | | //HD44780 has only 80 bytes of DDRAM, customized HD66780 has 128 bytes |
| 74 | | UINT8 ddram[128]; //internal display data RAM, |
| 75 | | UINT8 cgram[64]; //internal chargen RAM |
| 76 | | |
| 77 | | UINT8 ac; //address counter |
| 78 | | UINT8 ddram_a; //DDRAM address |
| 79 | | UINT8 cgram_a; //CGRAM address |
| 80 | | UINT8 ac_mode; //0=DDRAM 1=CGRAM |
| 81 | | |
| 82 | | UINT8 cursor_pos; //cursor position |
| 83 | | UINT8 display_on; //display on/off |
| 84 | | UINT8 cursor_on; //cursor on/off |
| 85 | | UINT8 blink_on; //blink on/off |
| 86 | | |
| 87 | | UINT8 direction; //auto increment/decrement |
| 88 | | UINT8 data_len; //interface data length 4 or 8 bit |
| 89 | | UINT8 n_line; //number of lines |
| 90 | | UINT8 char_size; //char size 5x8 or 5x10 |
| 91 | | |
| 92 | | UINT8 disp_shift; //display shift |
| 93 | | |
| 94 | | UINT8 blink; |
| 95 | | } hd44780; |
| 96 | | |
| 97 | | static TIMER_CALLBACK( bf_clear ) |
| 98 | | { |
| 99 | | hd44780.busy_flag = 0; |
| 100 | | } |
| 101 | | |
| 102 | | void set_busy_flag(running_machine *machine, UINT16 usec) |
| 103 | | { |
| 104 | | hd44780.busy_flag = 1; |
| 105 | | timer_set(machine, ATTOTIME_IN_USEC(usec), NULL, 0, bf_clear); |
| 106 | | } |
| 107 | | |
| 108 | | void hd44780_reset(running_machine *machine) |
| 109 | | { |
| 110 | | memset(&hd44780, 0x00, sizeof(_hd44780)); |
| 111 | | hd44780.direction = 1; |
| 112 | | hd44780.data_len = 1; |
| 113 | | set_busy_flag(machine, 1520); |
| 114 | | } |
| 115 | | |
| 116 | | void hd44780_control_w(running_machine *machine, UINT8 data) |
| 117 | | { |
| 118 | | if (BIT(data, 7)) |
| 119 | | { |
| 120 | | hd44780.ac_mode = 0; |
| 121 | | hd44780.ac = data & 0x7f; |
| 122 | | hd44780.ddram_a = data & 0x7f; |
| 123 | | if (data != 0x81) |
| 124 | | hd44780.cursor_pos = hd44780.ddram_a; |
| 125 | | set_busy_flag(machine, 37); |
| 126 | | } |
| 127 | | else if (BIT(data, 6)) |
| 128 | | { |
| 129 | | hd44780.ac_mode = 1; |
| 130 | | hd44780.ac = data & 0x3f; |
| 131 | | hd44780.cgram_a = data & 0x3f; |
| 132 | | set_busy_flag(machine, 37); |
| 133 | | } |
| 134 | | else if (BIT(data, 5)) |
| 135 | | { |
| 136 | | hd44780.data_len = BIT(data, 4); |
| 137 | | hd44780.n_line = BIT(data, 3); |
| 138 | | hd44780.char_size = BIT(data, 2); |
| 139 | | set_busy_flag(machine, 37); |
| 140 | | } |
| 141 | | else if (BIT(data, 4)) |
| 142 | | { |
| 143 | | UINT8 direction = (BIT(data, 2)) ? +1 : -1; |
| 144 | | |
| 145 | | if (BIT(data, 3)) |
| 146 | | hd44780.disp_shift += direction; |
| 147 | | else |
| 148 | | { |
| 149 | | hd44780.ac += direction; |
| 150 | | |
| 151 | | if (hd44780.ac_mode == 0) |
| 152 | | { |
| 153 | | hd44780.ddram_a += hd44780.direction; |
| 154 | | hd44780.cursor_pos += hd44780.direction; |
| 155 | | } |
| 156 | | else |
| 157 | | hd44780.cgram_a += hd44780.direction; |
| 158 | | } |
| 159 | | set_busy_flag(machine, 37); |
| 160 | | } |
| 161 | | else if (BIT(data, 3)) |
| 162 | | { |
| 163 | | hd44780.display_on = BIT(data, 2); |
| 164 | | hd44780.cursor_on = BIT(data, 1); |
| 165 | | hd44780.blink_on = BIT(data, 0); |
| 166 | | |
| 167 | | set_busy_flag(machine, 37); |
| 168 | | } |
| 169 | | else if (BIT(data, 2)) |
| 170 | | { |
| 171 | | hd44780.direction = (BIT(data, 1)) ? +1 : -1; |
| 172 | | if (BIT(data, 0)) |
| 173 | | hd44780.disp_shift += hd44780.direction; |
| 174 | | |
| 175 | | set_busy_flag(machine, 37); |
| 176 | | } |
| 177 | | else if (BIT(data, 1)) |
| 178 | | { |
| 179 | | hd44780.ac = 0; |
| 180 | | hd44780.ddram_a = 0; |
| 181 | | hd44780.cgram_a = 0; |
| 182 | | hd44780.cursor_pos = 0; |
| 183 | | hd44780.ac_mode = 0; |
| 184 | | hd44780.direction = 1; |
| 185 | | set_busy_flag(machine, 1520); |
| 186 | | } |
| 187 | | else if (BIT(data, 0)) |
| 188 | | { |
| 189 | | hd44780.ac = 0; |
| 190 | | hd44780.ddram_a = 0; |
| 191 | | hd44780.cgram_a = 0; |
| 192 | | hd44780.cursor_pos = 0; |
| 193 | | hd44780.ac_mode = 0; |
| 194 | | hd44780.direction = 1; |
| 195 | | memset(hd44780.ddram, 0x20, ARRAY_LENGTH(hd44780.ddram)); |
| 196 | | memset(hd44780.cgram, 0x20, ARRAY_LENGTH(hd44780.cgram)); |
| 197 | | set_busy_flag(machine, 1520); |
| 198 | | } |
| 199 | | } |
| 200 | | |
| 201 | | UINT8 hd44780_control_r(running_machine *machine) |
| 202 | | { |
| 203 | | return hd44780.busy_flag<<7 || hd44780.ac&0x7f; |
| 204 | | } |
| 205 | | |
| 206 | | void hd44780_data_w(running_machine *machine, UINT8 data) |
| 207 | | { |
| 208 | | if (hd44780.ac_mode == 0) |
| 209 | | { |
| 210 | | hd44780.ddram[hd44780.ac] = data; |
| 211 | | hd44780.ddram_a += hd44780.direction; |
| 212 | | hd44780.cursor_pos += hd44780.direction; |
| 213 | | } |
| 214 | | else |
| 215 | | { |
| 216 | | hd44780.cgram[hd44780.ac] = data; |
| 217 | | hd44780.cgram_a += hd44780.direction; |
| 218 | | } |
| 219 | | |
| 220 | | hd44780.ac += hd44780.direction; |
| 221 | | } |
| 222 | | |
| 223 | | UINT8 hd44780_data_r(running_machine *machine) |
| 224 | | { |
| 225 | | UINT8 data; |
| 226 | | |
| 227 | | if (hd44780.ac_mode == 0) |
| 228 | | { |
| 229 | | data = hd44780.ddram[hd44780.ac]; |
| 230 | | hd44780.ddram_a += hd44780.direction; |
| 231 | | hd44780.cursor_pos += hd44780.direction; |
| 232 | | } |
| 233 | | else |
| 234 | | { |
| 235 | | data = hd44780.cgram[hd44780.ac]; |
| 236 | | hd44780.cgram_a += hd44780.direction; |
| 237 | | } |
| 238 | | |
| 239 | | hd44780.ac += hd44780.direction; |
| 240 | | |
| 241 | | return data; |
| 242 | | } |
| 243 | | |
| 244 | 64 | /*********************************************** |
| 245 | 65 | |
| 246 | 66 | basic machine |
| r9038 | r9039 | |
| 253 | 73 | cputag_set_input_line(machine, "maincpu", INPUT_LINE_NMI, PULSE_LINE); |
| 254 | 74 | } |
| 255 | 75 | |
| 256 | | static TIMER_CALLBACK( blink_timer ) |
| 257 | | { |
| 258 | | hd44780.blink = ~hd44780.blink; |
| 259 | | } |
| 260 | | |
| 261 | 76 | UINT8 kb_read(running_machine *machine) |
| 262 | 77 | { |
| 263 | 78 | static const char *const bitnames[] = {"K1", "K2", "K3", "K4", "K5", "K6", "K7"}; |
| r9038 | r9039 | |
| 482 | 297 | |
| 483 | 298 | WRITE8_HANDLER( io_w ) |
| 484 | 299 | { |
| 300 | hd44780_device * hd44780 = space->machine->device<hd44780_device>("hd44780"); |
| 301 | |
| 485 | 302 | switch (offset & 0x0ffc0) |
| 486 | 303 | { |
| 487 | 304 | case 0x80: |
| 488 | 305 | if (offset & 1) |
| 489 | | hd44780_data_w(space->machine, data); |
| 306 | hd44780->data_write(offset, data); |
| 490 | 307 | else |
| 491 | | hd44780_control_w(space->machine, data); |
| 308 | hd44780->control_write(offset, data); |
| 492 | 309 | break; |
| 493 | 310 | default: |
| 494 | 311 | io_rw(space, offset); |
| r9038 | r9039 | |
| 497 | 314 | |
| 498 | 315 | READ8_HANDLER( io_r ) |
| 499 | 316 | { |
| 317 | hd44780_device * hd44780 = space->machine->device<hd44780_device>("hd44780"); |
| 318 | |
| 500 | 319 | switch (offset & 0xffc0) |
| 501 | 320 | { |
| 502 | 321 | case 0x80: |
| 503 | 322 | if (offset& 1) |
| 504 | | return hd44780_data_r(space->machine); |
| 323 | return hd44780->data_read(offset); |
| 505 | 324 | else |
| 506 | | return hd44780_control_r(space->machine); |
| 325 | return hd44780->control_read(offset); |
| 507 | 326 | default: |
| 508 | 327 | io_rw(space, offset); |
| 509 | 328 | } |
| r9038 | r9039 | |
| 731 | 550 | psion.paged_ram = auto_alloc_array(machine, UINT8, psion.ram_bank_count * 0x4000); |
| 732 | 551 | |
| 733 | 552 | timer_pulse(machine, ATTOTIME_IN_SEC(1), NULL, 0, nmi_timer); |
| 734 | | timer_pulse(machine, ATTOTIME_IN_MSEC(500), NULL, 0, blink_timer); |
| 735 | | |
| 736 | | state_save_register_global_array(machine, hd44780.ddram); |
| 737 | | state_save_register_global_array(machine, hd44780.cgram); |
| 738 | 553 | } |
| 739 | 554 | |
| 740 | 555 | static MACHINE_RESET(psion) |
| r9038 | r9039 | |
| 744 | 559 | psion.ram_bank=0; |
| 745 | 560 | psion.rom_bank=0; |
| 746 | 561 | |
| 747 | | hd44780_reset(machine); |
| 748 | | |
| 749 | 562 | if (psion.rom_bank_count || psion.ram_bank_count) |
| 750 | 563 | update_bank(machine); |
| 751 | 564 | } |
| r9038 | r9039 | |
| 756 | 569 | |
| 757 | 570 | static VIDEO_UPDATE( psion_2lines ) |
| 758 | 571 | { |
| 759 | | char lcd_map[2][16]; |
| 760 | | UINT8 cur_x = 0; |
| 761 | | UINT8 cur_y = 0; |
| 762 | | UINT8 display_layout[2] = {0x00, 0x40}; |
| 572 | hd44780_device * hd44780 = screen->machine->device<hd44780_device>("hd44780"); |
| 763 | 573 | |
| 764 | | memset(lcd_map, 0, 2*16); |
| 765 | | |
| 766 | | for (int i=0; i<2; i++) |
| 767 | | { |
| 768 | | if (hd44780.cursor_pos >= display_layout[i] && hd44780.cursor_pos < display_layout[i]+16) |
| 769 | | { |
| 770 | | cur_y = i+1; |
| 771 | | cur_x = hd44780.cursor_pos - display_layout[i]; |
| 772 | | } |
| 773 | | |
| 774 | | memcpy(&lcd_map[i], hd44780.ddram + display_layout[i], 16); |
| 775 | | } |
| 776 | | |
| 777 | | bitmap_fill(bitmap, NULL, 0); |
| 778 | | |
| 779 | | if (hd44780.display_on) |
| 780 | | { |
| 781 | | for (int l=0; l<2; l++) |
| 782 | | for (int i=0; i<16; i++) |
| 783 | | for (int y=0; y<8; y++) |
| 784 | | for (int x=0; x<5; x++) |
| 785 | | if (lcd_map[l][i] <= 0x10) |
| 786 | | { |
| 787 | | //draw CGRAM characters |
| 788 | | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(hd44780.cgram[(lcd_map[l][i]&0x07)*8+y], 4-x); |
| 789 | | } |
| 790 | | else |
| 791 | | { |
| 792 | | //draw CGROM characters |
| 793 | | UINT8 * gc_base = memory_region(screen->machine, "chargen"); |
| 794 | | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(gc_base[(lcd_map[l][i]-0x20)*8+y], 4-x); |
| 795 | | } |
| 796 | | |
| 797 | | //draw the cursor |
| 798 | | if (hd44780.cursor_on) |
| 799 | | for (int i=0; i<5; i++) |
| 800 | | *BITMAP_ADDR16(bitmap, cur_y * 9-2, cur_x*6 + i) = 1; |
| 801 | | |
| 802 | | if (!hd44780.blink && hd44780.blink_on) |
| 803 | | for (int l=0; l<7; l++) |
| 804 | | for (int i=0; i<5; i++) |
| 805 | | *BITMAP_ADDR16(bitmap, (cur_y-1) * 9 + l, cur_x*6 + i) = 1; |
| 806 | | } |
| 807 | | |
| 808 | | #if(0) |
| 809 | | popmessage("cur: %u, pos %u, shift %u", hd44780.cursor_on, hd44780.ddram_a, hd44780.disp_shift); |
| 810 | | #endif |
| 811 | | return 0; |
| 574 | return hd44780->video_update( bitmap, cliprect ); |
| 812 | 575 | } |
| 813 | 576 | |
| 814 | 577 | static VIDEO_UPDATE( psion_4lines ) |
| 815 | 578 | { |
| 816 | | UINT8 lcd_map[4][20]; |
| 817 | | UINT8 cur_x = 0; |
| 818 | | UINT8 cur_y = 0; |
| 819 | | UINT8 line_pos = 0; |
| 820 | | UINT8 display_layout[4][3]= |
| 821 | | { |
| 822 | | {0x00, 0x08, 0x18}, |
| 823 | | {0x40, 0x48, 0x58}, |
| 824 | | {0x04, 0x10, 0x20}, |
| 825 | | {0x44, 0x50, 0x60} |
| 826 | | }; |
| 579 | hd44780_device * hd44780 = screen->machine->device<hd44780_device>("hd44780"); |
| 827 | 580 | |
| 828 | | memset(lcd_map, 0, 4*20); |
| 829 | | |
| 830 | | for (int i=0; i<4; i++) |
| 831 | | { |
| 832 | | line_pos = 0; |
| 833 | | |
| 834 | | for (int j=0; j<3; j++) |
| 835 | | { |
| 836 | | if (hd44780.cursor_pos >= display_layout[i][j] && hd44780.cursor_pos < display_layout[i][j] + ((j==0)?4:8)) |
| 837 | | { |
| 838 | | cur_y = i+1; |
| 839 | | cur_x = line_pos + hd44780.cursor_pos - display_layout[i][j]; |
| 840 | | } |
| 841 | | |
| 842 | | memcpy(&lcd_map[i][line_pos], hd44780.ddram + display_layout[i][j], ((j==0)?4:8)); |
| 843 | | |
| 844 | | line_pos += (j==0)?4:8; |
| 845 | | } |
| 846 | | } |
| 847 | | |
| 848 | | bitmap_fill(bitmap, NULL, 0); |
| 849 | | |
| 850 | | if (hd44780.display_on) |
| 851 | | { |
| 852 | | for (int l=0; l<4; l++) |
| 853 | | for (int i=0; i<20; i++) |
| 854 | | for (int y=0; y<8; y++) |
| 855 | | for (int x=0; x<5; x++) |
| 856 | | if (lcd_map[l][i] <= 0x10) |
| 857 | | { |
| 858 | | //draw CGRAM characters |
| 859 | | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(hd44780.cgram[(lcd_map[l][i]&0x07)*8+y], 4-x); |
| 860 | | } |
| 861 | | else |
| 862 | | { |
| 863 | | //draw CGROM characters |
| 864 | | UINT8 * gc_base = memory_region(screen->machine, "chargen"); |
| 865 | | *BITMAP_ADDR16(bitmap, l*9 + y, i*6 + x) = BIT(gc_base[(lcd_map[l][i]-0x20)*8+y], 4-x); |
| 866 | | } |
| 867 | | |
| 868 | | //draw the cursor |
| 869 | | if (hd44780.cursor_on) |
| 870 | | for (int i=0; i<5; i++) |
| 871 | | *BITMAP_ADDR16(bitmap, cur_y * 9-2, cur_x*6 + i) = 1; |
| 872 | | |
| 873 | | if (!hd44780.blink && hd44780.blink_on) |
| 874 | | for (int l=0; l<7; l++) |
| 875 | | for (int i=0; i<5; i++) |
| 876 | | *BITMAP_ADDR16(bitmap, (cur_y-1) * 9 + l, cur_x*6 + i) = 1; |
| 877 | | } |
| 878 | | |
| 879 | | #if(0) |
| 880 | | popmessage("cur: %u, pos %u, shift %u", hd44780.cursor_on, hd44780.cursor_pos, hd44780.disp_shift); |
| 881 | | #endif |
| 882 | | return 0; |
| 581 | return hd44780->video_update( bitmap, cliprect ); |
| 883 | 582 | } |
| 884 | 583 | |
| 885 | 584 | static PALETTE_INIT( psion ) |
| r9038 | r9039 | |
| 920 | 619 | MDRV_CARTSLOT_UNLOAD(psion_pack2) |
| 921 | 620 | MACHINE_CONFIG_END |
| 922 | 621 | |
| 622 | static const hd44780_interface psion_2line_display = |
| 623 | { |
| 624 | 2, // number of lines |
| 625 | 16, // chars for line |
| 626 | NULL // custom display layout |
| 627 | }; |
| 628 | |
| 923 | 629 | /* basic configuration for 2 lines display */ |
| 924 | 630 | static MACHINE_CONFIG_START( psion_2lines, driver_device ) |
| 925 | 631 | /* basic machine hardware */ |
| r9038 | r9039 | |
| 940 | 646 | MDRV_PALETTE_INIT(psion) |
| 941 | 647 | MDRV_GFXDECODE(psion) |
| 942 | 648 | |
| 649 | MDRV_HD44780_ADD("hd44780", psion_2line_display) |
| 650 | |
| 943 | 651 | MDRV_VIDEO_START(psion) |
| 944 | 652 | MDRV_VIDEO_UPDATE(psion_2lines) |
| 945 | 653 | |
| r9038 | r9039 | |
| 953 | 661 | MDRV_FRAGMENT_ADD( psion_slot ) |
| 954 | 662 | MACHINE_CONFIG_END |
| 955 | 663 | |
| 664 | UINT8 psion_4line_layout[] = |
| 665 | { |
| 666 | 0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, |
| 667 | 0x40, 0x41, 0x42, 0x43, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, |
| 668 | 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, |
| 669 | 0x44, 0x45, 0x46, 0x47, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67 |
| 670 | }; |
| 671 | |
| 672 | static const hd44780_interface psion_4line_display = |
| 673 | { |
| 674 | 4, // number of lines |
| 675 | 20, // chars for line |
| 676 | psion_4line_layout // custom display layout |
| 677 | }; |
| 678 | |
| 956 | 679 | /* basic configuration for 4 lines display */ |
| 957 | 680 | static MACHINE_CONFIG_START( psion_4lines, driver_device ) |
| 958 | 681 | /* basic machine hardware */ |
| r9038 | r9039 | |
| 973 | 696 | MDRV_PALETTE_INIT(psion) |
| 974 | 697 | MDRV_GFXDECODE(psion) |
| 975 | 698 | |
| 699 | MDRV_HD44780_ADD("hd44780", psion_4line_display) |
| 700 | |
| 976 | 701 | MDRV_VIDEO_START(psion) |
| 977 | 702 | MDRV_VIDEO_UPDATE(psion_4lines) |
| 978 | 703 | |