trunk/src/mess/drivers/tispeak.c
| r242502 | r242503 | |
| 20 | 20 | tispeak_state(const machine_config &mconfig, device_type type, const char *tag) |
| 21 | 21 | : driver_device(mconfig, type, tag), |
| 22 | 22 | m_maincpu(*this, "maincpu"), |
| 23 | m_tms5100(*this, "tms5100"), |
| 24 | m_tms6100(*this, "tms6100"), |
| 25 | m_filoff_timer(*this, "filoff"), |
| 23 | 26 | m_button_matrix(*this, "IN") |
| 24 | 27 | { } |
| 25 | 28 | |
| 26 | 29 | required_device<tms0270_cpu_device> m_maincpu; |
| 30 | required_device<tms5100_device> m_tms5100; |
| 31 | required_device<tms6100_device> m_tms6100; |
| 32 | required_device<timer_device> m_filoff_timer; |
| 27 | 33 | required_ioport_array<9> m_button_matrix; |
| 28 | 34 | |
| 29 | 35 | UINT16 m_r; |
| 30 | 36 | UINT16 m_o; |
| 37 | int m_filament_on; |
| 38 | int m_power_on; |
| 31 | 39 | |
| 32 | | UINT16 m_leds_state[9]; |
| 33 | | void leds_update(); |
| 40 | UINT16 m_digit_state[9]; |
| 41 | void display_update(); |
| 42 | TIMER_DEVICE_CALLBACK_MEMBER(delayed_filament_off); |
| 34 | 43 | |
| 35 | 44 | DECLARE_READ8_MEMBER(snspell_read_k); |
| 36 | 45 | DECLARE_WRITE16_MEMBER(snmath_write_o); |
| 37 | 46 | DECLARE_WRITE16_MEMBER(snspell_write_o); |
| 38 | 47 | DECLARE_WRITE16_MEMBER(snspell_write_r); |
| 48 | |
| 49 | DECLARE_INPUT_CHANGED_MEMBER(power_button); |
| 39 | 50 | DECLARE_WRITE_LINE_MEMBER(auto_power_off); |
| 51 | void power_off(); |
| 40 | 52 | |
| 53 | virtual void machine_reset(); |
| 41 | 54 | virtual void machine_start(); |
| 42 | 55 | }; |
| 43 | 56 | |
| r242502 | r242503 | |
| 45 | 58 | |
| 46 | 59 | /*************************************************************************** |
| 47 | 60 | |
| 48 | | LEDs |
| 61 | VFD Display |
| 49 | 62 | |
| 50 | 63 | ***************************************************************************/ |
| 51 | 64 | |
| 65 | // The device strobes the filament-enable very fast, it is unnoticeable to the user. |
| 66 | // To prevent flickering here, we need to simulate a decay. |
| 52 | 67 | |
| 53 | | void tispeak_state::leds_update() |
| 68 | // decay time in milliseconds |
| 69 | #define FILOFF_DECAY_TIME 20 |
| 70 | |
| 71 | TIMER_DEVICE_CALLBACK_MEMBER(tispeak_state::delayed_filament_off) |
| 54 | 72 | { |
| 55 | | // update leds state |
| 73 | // turn off display |
| 74 | m_filament_on = 0; |
| 75 | display_update(); |
| 76 | } |
| 77 | |
| 78 | void tispeak_state::display_update() |
| 79 | { |
| 80 | // filament on/off |
| 81 | if (m_r & 0x8000) |
| 82 | { |
| 83 | m_filament_on = 1; |
| 84 | m_filoff_timer->reset(); |
| 85 | } |
| 86 | else if (m_filament_on && m_filoff_timer->time_left() == attotime::never) |
| 87 | { |
| 88 | // schedule delayed filament-off |
| 89 | m_filoff_timer->adjust(attotime::from_msec(FILOFF_DECAY_TIME)); |
| 90 | } |
| 91 | |
| 92 | // update digit state |
| 56 | 93 | for (int i = 0; i < 9; i++) |
| 57 | 94 | if (m_r >> i & 1) |
| 58 | | m_leds_state[i] = m_o & 0x3fff; |
| 95 | m_digit_state[i] = m_o; |
| 59 | 96 | |
| 60 | | // if filament (R15) is on, send to output |
| 61 | | // if (m_r & 0x8000) // blank.. |
| 97 | // send to output |
| 62 | 98 | for (int i = 0; i < 9; i++) |
| 63 | | output_set_digit_value(i, m_leds_state[i]); |
| 99 | { |
| 100 | // standard led14seg |
| 101 | output_set_digit_value(i, m_filament_on ? m_digit_state[i] & 0x3fff : 0); |
| 102 | |
| 103 | // DP(display point) and AP(apostrophe) segments as lamps |
| 104 | output_set_lamp_value(i*10 + 0, m_digit_state[i] >> 14 & m_filament_on); |
| 105 | output_set_lamp_value(i*10 + 1, m_digit_state[i] >> 15 & m_filament_on); |
| 106 | } |
| 64 | 107 | } |
| 65 | 108 | |
| 66 | 109 | |
| r242502 | r242503 | |
| 88 | 131 | |
| 89 | 132 | WRITE16_MEMBER(tispeak_state::snspell_write_r) |
| 90 | 133 | { |
| 134 | // R0-R7: input mux and select digit (+R8 if the device has 9 digits) |
| 135 | // R15: filament on |
| 136 | // other bits: MCU internal use |
| 91 | 137 | m_r = data; |
| 92 | | leds_update(); |
| 138 | display_update(); |
| 93 | 139 | } |
| 94 | 140 | |
| 95 | 141 | WRITE16_MEMBER(tispeak_state::snspell_write_o) |
| r242502 | r242503 | |
| 98 | 144 | // E,D,C,G,B,A,I,M,L,K,N,J,[AP],H,F,[DP] (sidenote: TI KLMN = MAME MLNK) |
| 99 | 145 | m_o = BITSWAP16(data,12,15,10,7,8,9,11,6,13,3,14,0,1,2,4,5); |
| 100 | 146 | |
| 101 | | leds_update(); |
| 147 | display_update(); |
| 102 | 148 | } |
| 103 | 149 | |
| 104 | 150 | |
| 151 | void tispeak_state::power_off() |
| 152 | { |
| 153 | m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| 154 | m_tms5100->reset(); |
| 155 | m_tms6100->reset(); |
| 156 | |
| 157 | m_power_on = 0; |
| 158 | } |
| 159 | |
| 105 | 160 | WRITE_LINE_MEMBER(tispeak_state::auto_power_off) |
| 106 | 161 | { |
| 107 | | //if (state) printf("X"); |
| 162 | // power-off request from the MCU, usually after a couple of minutes of idling |
| 163 | if (state) |
| 164 | power_off(); |
| 108 | 165 | } |
| 109 | 166 | |
| 110 | 167 | |
| r242502 | r242503 | |
| 116 | 173 | // [DP],D,C,H,F,B,I,M,L,K,N,J,[AP],E,G,A (sidenote: TI KLMN = MAME MLNK) |
| 117 | 174 | m_o = BITSWAP16(data,12,0,10,7,8,9,11,6,3,14,4,13,1,2,5,15); |
| 118 | 175 | |
| 119 | | leds_update(); |
| 176 | display_update(); |
| 120 | 177 | } |
| 121 | 178 | |
| 122 | 179 | |
| r242502 | r242503 | |
| 127 | 184 | |
| 128 | 185 | ***************************************************************************/ |
| 129 | 186 | |
| 187 | INPUT_CHANGED_MEMBER(tispeak_state::power_button) |
| 188 | { |
| 189 | // note: even though power buttons are on the matrix, they are not MCU-controlled |
| 190 | int on = (int)(FPTR)param; |
| 191 | |
| 192 | if (on) |
| 193 | { |
| 194 | m_power_on = 1; |
| 195 | m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); |
| 196 | } |
| 197 | else if (m_power_on) |
| 198 | power_off(); |
| 199 | } |
| 200 | |
| 130 | 201 | static INPUT_PORTS_START( snspell ) |
| 131 | 202 | PORT_START("IN.0") // R0 |
| 132 | 203 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') |
| r242502 | r242503 | |
| 174 | 245 | PORT_BIT( 0x1f, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 175 | 246 | |
| 176 | 247 | PORT_START("IN.7") // R7 |
| 177 | | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Off") |
| 248 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Off") PORT_CHANGED_MEMBER(DEVICE_SELF, tispeak_state, power_button, (void *)0) |
| 178 | 249 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_NAME("Go") |
| 179 | 250 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_NAME("Replay") |
| 180 | 251 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_NAME("Repeat") |
| r242502 | r242503 | |
| 185 | 256 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_NAME("Secret Code") |
| 186 | 257 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_NAME("Letter") |
| 187 | 258 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_NAME("Say It") |
| 188 | | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Spell/On") |
| 259 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Spell/On") PORT_CHANGED_MEMBER(DEVICE_SELF, tispeak_state, power_button, (void *)1) |
| 189 | 260 | INPUT_PORTS_END |
| 190 | 261 | |
| 191 | 262 | |
| r242502 | r242503 | |
| 215 | 286 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 216 | 287 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter") |
| 217 | 288 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_NAME("Go") |
| 218 | | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Off") |
| 289 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Off") PORT_CHANGED_MEMBER(DEVICE_SELF, tispeak_state, power_button, (void *)0) |
| 219 | 290 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| 220 | 291 | |
| 221 | 292 | PORT_START("IN.4") // R4 |
| r242502 | r242503 | |
| 237 | 308 | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_NAME("Write It") |
| 238 | 309 | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_NAME("Greater/Less") |
| 239 | 310 | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_NAME("Word Problems") |
| 240 | | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Solve It/On") |
| 311 | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CODE(KEYCODE_PGUP) PORT_NAME("Solve It/On") PORT_CHANGED_MEMBER(DEVICE_SELF, tispeak_state, power_button, (void *)1) |
| 241 | 312 | |
| 242 | 313 | PORT_START("IN.7") |
| 243 | 314 | PORT_BIT( 0x1f, IP_ACTIVE_HIGH, IPT_UNUSED ) |
| r242502 | r242503 | |
| 254 | 325 | |
| 255 | 326 | ***************************************************************************/ |
| 256 | 327 | |
| 328 | void tispeak_state::machine_reset() |
| 329 | { |
| 330 | m_filament_on = 0; |
| 331 | m_power_on = 1; |
| 332 | } |
| 333 | |
| 257 | 334 | void tispeak_state::machine_start() |
| 258 | 335 | { |
| 259 | | memset(m_leds_state, 0, sizeof(m_leds_state)); |
| 336 | // zerofill |
| 337 | memset(m_digit_state, 0, sizeof(m_digit_state)); |
| 260 | 338 | m_r = 0; |
| 261 | 339 | m_o = 0; |
| 340 | m_filament_on = 0; |
| 341 | m_power_on = 0; |
| 262 | 342 | |
| 263 | | save_item(NAME(m_leds_state)); |
| 343 | // register for savestates |
| 344 | save_item(NAME(m_digit_state)); |
| 264 | 345 | save_item(NAME(m_r)); |
| 265 | 346 | save_item(NAME(m_o)); |
| 347 | save_item(NAME(m_filament_on)); |
| 348 | save_item(NAME(m_power_on)); |
| 266 | 349 | } |
| 267 | 350 | |
| 268 | 351 | |
| r242502 | r242503 | |
| 279 | 362 | MCFG_TMS0270_WRITE_CTL_CB(DEVWRITE8("tms5100", tms5100_device, ctl_w)) |
| 280 | 363 | MCFG_TMS0270_WRITE_PDC_CB(DEVWRITELINE("tms5100", tms5100_device, pdc_w)) |
| 281 | 364 | |
| 282 | | MCFG_DEFAULT_LAYOUT(layout_tispeak) |
| 365 | MCFG_TIMER_DRIVER_ADD("filoff", tispeak_state, delayed_filament_off) |
| 366 | MCFG_DEFAULT_LAYOUT(layout_tispeak) // max 9 digits |
| 283 | 367 | |
| 284 | 368 | /* no video! */ |
| 285 | 369 | |