trunk/src/emu/cpu/avr8/avr8.c
r18880 | r18881 | |
9 | 9 | the existing opcodes has been shown to wildly corrupt the video output in Craft, so one can assume that the |
10 | 10 | existing timing is 100% correct. |
11 | 11 | |
12 | | Unimplemented opcodes: CPSR, LD Z+, ST Z+, ST -Z/-Y/-X, ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, ICALL, |
13 | | EICALL, JMP, CALL, SBIW |
| 12 | Unimplemented opcodes: CPSR, LD Z+, ST -Z/-Y/-X, ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, ICALL, EICALL, |
| 13 | JMP, CALL |
14 | 14 | |
15 | 15 | - Changelist - |
16 | 16 | 30 Oct. 2012 |
r18880 | r18881 | |
95 | 95 | |
96 | 96 | enum |
97 | 97 | { |
98 | | WGM2_NORMAL = 0, |
99 | | WGM2_PWM_PC, |
100 | | WGM2_CTC_CMP, |
101 | | WGM2_FAST_PWM, |
102 | | WGM2_RESERVED0, |
103 | | WGM2_PWM_PC_CMP, |
104 | | WGM2_RESERVED1, |
105 | | WGM2_FAST_PWM_CMP |
| 98 | WGM02_NORMAL = 0, |
| 99 | WGM02_PWM_PC, |
| 100 | WGM02_CTC_CMP, |
| 101 | WGM02_FAST_PWM, |
| 102 | WGM02_RESERVED0, |
| 103 | WGM02_PWM_PC_CMP, |
| 104 | WGM02_RESERVED1, |
| 105 | WGM02_FAST_PWM_CMP |
106 | 106 | }; |
107 | 107 | |
108 | 108 | static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' }; |
109 | 109 | |
110 | | #define SREG_R(b) ((m_status & (1 << (b))) >> (b)) |
111 | | #define SREG_W(b,v) m_status = (m_status & ~(1 << (b))) | ((v) << (b)) |
| 110 | #define SREG_R(b) ((m_r[AVR8_REGIDX_SREG] & (1 << (b))) >> (b)) |
| 111 | #define SREG_W(b,v) m_r[AVR8_REGIDX_SREG] = (m_r[AVR8_REGIDX_SREG] & ~(1 << (b))) | ((v) << (b)) |
112 | 112 | #define NOT(x) (1 - (x)) |
113 | 113 | |
114 | 114 | // Opcode-Parsing Defines |
r18880 | r18881 | |
145 | 145 | #define AVR8_TCNT1H (m_r[AVR8_REGIDX_TCNT1H]) |
146 | 146 | #define AVR8_TCNT1L (m_r[AVR8_REGIDX_TCNT1L]) |
147 | 147 | |
| 148 | #define AVR8_TCCR0B (m_r[AVR8_REGIDX_TCCR0B]) |
| 149 | #define AVR8_TCCR0B_FOC0A_MASK 0x80 |
| 150 | #define AVR8_TCCR0B_FOC0A_SHIFT 7 |
| 151 | #define AVR8_TCCR0B_FOC0B_MASK 0x40 |
| 152 | #define AVR8_TCCR0B_FOC0B_SHIFT 6 |
| 153 | #define AVR8_TCCR0B_WGM0_2_MASK 0x08 |
| 154 | #define AVR8_TCCR0B_WGM0_2_SHIFT 3 |
| 155 | #define AVR8_TCCR0B_CS_MASK 0x07 |
| 156 | #define AVR8_TCCR0B_CS_SHIFT 0 |
| 157 | #define AVR8_TIMER0_CLOCK_SELECT (AVR8_TCCR0B & AVR8_TCCR0B_CS_MASK) |
| 158 | |
| 159 | #define AVR8_TCCR0A (m_r[AVR8_REGIDX_TCCR0A]) |
| 160 | #define AVR8_TCCR0A_COM0A_MASK 0xc0 |
| 161 | #define AVR8_TCCR0A_COM0A_SHIFT 6 |
| 162 | #define AVR8_TCCR0A_COM0B_MASK 0x30 |
| 163 | #define AVR8_TCCR0A_COM0B_SHIFT 4 |
| 164 | #define AVR8_TCCR0A_WGM0_10_MASK 0x03 |
| 165 | #define AVR8_TCCR0A_WGM0_10_SHIFT 0 |
| 166 | #define AVR8_TCCR0A_COM0A ((AVR8_TCCR0A & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT) |
| 167 | #define AVR8_TCCR0A_COM0B ((AVR8_TCCR0A & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT) |
| 168 | #define AVR8_TCCR0A_WGM0_10 (AVR8_TCCR0A & AVR8_TCCR0A_WGM0_10_MASK) |
| 169 | |
| 170 | #define AVR8_TIMSK0 (m_r[AVR8_REGIDX_TIMSK0]) |
| 171 | #define AVR8_TIMSK0_OCIE0B_MASK 0x04 |
| 172 | #define AVR8_TIMSK0_OCIE0A_MASK 0x02 |
| 173 | #define AVR8_TIMSK0_TOIE0_MASK 0x01 |
| 174 | #define AVR8_TIMSK0_OCIE0B ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0B_MASK) >> 2) |
| 175 | #define AVR8_TIMSK0_OCIE0A ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0A_MASK) >> 1) |
| 176 | #define AVR8_TIMSK0_TOIE0 (AVR8_TIMSK0 & AVR8_TIMSK0_TOIE0_MASK) |
| 177 | |
| 178 | #define AVR8_TIFR0 (m_r[AVR8_REGIDX_TIFR0]) |
| 179 | #define AVR8_TIFR0_OCF0B_MASK 0x04 |
| 180 | #define AVR8_TIFR0_OCF0B_SHIFT 2 |
| 181 | #define AVR8_TIFR0_OCF0A_MASK 0x02 |
| 182 | #define AVR8_TIFR0_OCF0A_SHIFT 1 |
| 183 | #define AVR8_TIFR0_TOV0_MASK 0x01 |
| 184 | #define AVR8_TIFR0_TOV0_SHIFT 0 |
| 185 | #define AVR8_TIFR0_MASK (AVR8_TIFR0_TOV0_MASK | AVR8_TIFR0_OCF0B_MASK | AVR8_TIFR0_OCF0A_MASK) |
| 186 | |
148 | 187 | #define AVR8_TCCR1B (m_r[AVR8_REGIDX_TCCR1B]) |
149 | 188 | #define AVR8_TCCR1B_ICNC1_MASK 0x80 |
150 | 189 | #define AVR8_TCCR1B_ICNC1_SHIFT 7 |
r18880 | r18881 | |
189 | 228 | #define AVR8_TIFR1_MASK (AVR8_TIFR1_ICF1_MASK | AVR8_TIFR1_TOV1_MASK | \ |
190 | 229 | AVR8_TIFR1_OCF1B_MASK | AVR8_TIFR1_OCF1A_MASK) |
191 | 230 | |
192 | | #define AVR8_TCCR2B (m_r[AVR8_REGIDX_TCCR1B]) |
| 231 | #define AVR8_TCCR2B (m_r[AVR8_REGIDX_TCCR2B]) |
193 | 232 | #define AVR8_TCCR2B_FOC2A_MASK 0x80 |
194 | 233 | #define AVR8_TCCR2B_FOC2A_SHIFT 7 |
195 | 234 | #define AVR8_TCCR2B_FOC2B_MASK 0x40 |
r18880 | r18881 | |
200 | 239 | #define AVR8_TCCR2B_CS_SHIFT 0 |
201 | 240 | #define AVR8_TIMER2_CLOCK_SELECT (AVR8_TCCR2B & AVR8_TCCR2B_CS_MASK) |
202 | 241 | |
203 | | #define AVR8_TCCR2A (m_r[AVR8_REGIDX_TCCR1A]) |
| 242 | #define AVR8_TCCR2A (m_r[AVR8_REGIDX_TCCR2A]) |
204 | 243 | #define AVR8_TCCR2A_COM2A_MASK 0xc0 |
205 | 244 | #define AVR8_TCCR2A_COM2A_SHIFT 6 |
206 | 245 | #define AVR8_TCCR2A_COM2B_MASK 0x30 |
r18880 | r18881 | |
209 | 248 | #define AVR8_TCCR2A_WGM2_10_SHIFT 0 |
210 | 249 | #define AVR8_TCCR2A_COM2A ((AVR8_TCCR2A & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT) |
211 | 250 | #define AVR8_TCCR2A_COM2B ((AVR8_TCCR2A & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT) |
212 | | #define AVR8_TCCR2A_WGM2_10 (AVR8_TCCR2A & AVR8_TCCR1A_WGM2_10_MASK) |
| 251 | #define AVR8_TCCR2A_WGM2_10 (AVR8_TCCR2A & AVR8_TCCR2A_WGM2_10_MASK) |
213 | 252 | |
214 | 253 | #define AVR8_TIMSK2 (m_r[AVR8_REGIDX_TIMSK2]) |
215 | 254 | #define AVR8_TIMSK2_OCIE2B_MASK 0x04 |
216 | 255 | #define AVR8_TIMSK2_OCIE2A_MASK 0x02 |
217 | 256 | #define AVR8_TIMSK2_TOIE2_MASK 0x01 |
218 | | #define AVR8_TIMSK2_OCIE2B ((AVR8_TIMSK2 & AVR8_TIMSK1_OCIE2B_MASK) >> 2) |
219 | | #define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK1_OCIE2A_MASK) >> 1) |
220 | | #define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK1_TOIE2_MASK) |
| 257 | #define AVR8_TIMSK2_OCIE2B ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2B_MASK) >> 2) |
| 258 | #define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2A_MASK) >> 1) |
| 259 | #define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK2_TOIE2_MASK) |
221 | 260 | |
222 | 261 | #define AVR8_TIFR2 (m_r[AVR8_REGIDX_TIFR2]) |
223 | 262 | #define AVR8_TIFR2_OCF2B_MASK 0x04 |
r18880 | r18881 | |
228 | 267 | #define AVR8_TIFR2_TOV2_SHIFT 0 |
229 | 268 | #define AVR8_TIFR2_MASK (AVR8_TIFR2_TOV2_MASK | AVR8_TIFR2_OCF2B_MASK | AVR8_TIFR2_OCF2A_MASK) |
230 | 269 | |
| 270 | #define AVR8_OCR0A m_r[AVR8_REGIDX_OCR0A] |
| 271 | #define AVR8_OCR0B m_r[AVR8_REGIDX_OCR0B] |
| 272 | #define AVR8_TCNT0 m_r[AVR8_REGIDX_TCNT0] |
| 273 | #define AVR8_WGM0 (((AVR8_TCCR0B & 0x08) >> 1) | (AVR8_TCCR0A & 0x03)) |
| 274 | |
231 | 275 | #define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL) |
232 | 276 | #define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL) |
233 | 277 | #define AVR8_ICR1 ((AVR8_ICR1H << 8) | AVR8_ICR1L) |
r18880 | r18881 | |
235 | 279 | #define AVR8_WGM1 (((AVR8_TCCR1B & 0x18) >> 1) | (AVR8_TCCR1A & 0x03)) |
236 | 280 | #define AVR8_TCNT1_DIR (state->m_tcnt1_direction) |
237 | 281 | |
| 282 | #define AVR8_OCR2A m_r[AVR8_REGIDX_OCR2A] |
238 | 283 | #define AVR8_OCR2B m_r[AVR8_REGIDX_OCR2B] |
239 | | #define AVR8_OCR2A m_r[AVR8_REGIDX_OCR2A] |
240 | 284 | #define AVR8_TCNT2 m_r[AVR8_REGIDX_TCNT2] |
241 | 285 | #define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03)) |
242 | 286 | |
243 | 287 | #define AVR8_GTCCR_PSRASY_MASK 0x02 |
244 | 288 | #define AVR8_GTCCR_PSRASY_SHIFT 1 |
245 | 289 | |
| 290 | #define AVR8_SPSR (m_r[AVR8_REGIDX_SPSR]) |
| 291 | #define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) |
| 292 | |
| 293 | #define AVR8_SPCR (m_r[AVR8_REGIDX_SPCR]) |
| 294 | #define AVR8_SPCR_SPIE ((AVR8_SPCR & AVR8_SPCR_SPIE_MASK) >> 7) |
| 295 | #define AVR8_SPCR_SPE ((AVR8_SPCR & AVR8_SPCR_SPE_MASK) >> 6) |
| 296 | #define AVR8_SPCR_DORD ((AVR8_SPCR & AVR8_SPCR_DORD_MASK) >> 5) |
| 297 | #define AVR8_SPCR_MSTR ((AVR8_SPCR & AVR8_SPCR_MSTR_MASK) >> 4) |
| 298 | #define AVR8_SPCR_CPOL ((AVR8_SPCR & AVR8_SPCR_CPOL_MASK) >> 3) |
| 299 | #define AVR8_SPCR_CPHA ((AVR8_SPCR & AVR8_SPCR_CPHA_MASK) >> 2) |
| 300 | #define AVR8_SPCR_SPR (AVR8_SPCR & AVR8_SPCR_SPR_MASK) |
| 301 | |
| 302 | #define AVR8_SPI_RATE ((AVR8_SPSR_SPR2X << 2) | AVR8_SPCR_SPR) |
| 303 | |
| 304 | #define AVR8_PORTB_MOSI 0x08 |
| 305 | |
246 | 306 | //************************************************************************** |
247 | 307 | // DEVICE INTERFACE |
248 | 308 | //************************************************************************** |
r18880 | r18881 | |
250 | 310 | const device_type ATMEGA88 = &device_creator<atmega88_device>; |
251 | 311 | const device_type ATMEGA644 = &device_creator<atmega644_device>; |
252 | 312 | |
| 313 | //************************************************************************** |
| 314 | // INTERNAL ADDRESS MAP |
| 315 | //************************************************************************** |
| 316 | |
| 317 | static ADDRESS_MAP_START( avr8_internal_map, AS_DATA, 8, avr8_device ) |
| 318 | AM_RANGE(0x0000, 0x00ff) AM_READWRITE( regs_r, regs_w ) |
| 319 | ADDRESS_MAP_END |
| 320 | |
253 | 321 | //------------------------------------------------- |
254 | | // atmega8_device - constructor |
| 322 | // atmega88_device - constructor |
255 | 323 | //------------------------------------------------- |
256 | 324 | |
257 | | avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 addr_mask) |
| 325 | atmega88_device::atmega88_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 326 | : avr8_device(mconfig, tag, owner, clock, ATMEGA88, 0x0fff, ADDRESS_MAP_NAME(avr8_internal_map)) |
| 327 | { |
| 328 | } |
| 329 | |
| 330 | //------------------------------------------------- |
| 331 | // atmega644_device - constructor |
| 332 | //------------------------------------------------- |
| 333 | |
| 334 | atmega644_device::atmega644_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 335 | : avr8_device(mconfig, tag, owner, clock, ATMEGA644, 0xffff, ADDRESS_MAP_NAME(avr8_internal_map)) |
| 336 | { |
| 337 | } |
| 338 | |
| 339 | //------------------------------------------------- |
| 340 | // avr8_device - constructor |
| 341 | //------------------------------------------------- |
| 342 | |
| 343 | avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 addr_mask, address_map_constructor internal_map) |
258 | 344 | : cpu_device(mconfig, type, "AVR8", tag, owner, clock), |
259 | 345 | m_program_config("program", ENDIANNESS_LITTLE, 8, 22), |
260 | | m_io_config("io", ENDIANNESS_LITTLE, 8, 16), |
| 346 | m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map), |
| 347 | m_io_config("io", ENDIANNESS_LITTLE, 8, 2), |
| 348 | m_eeprom(NULL), |
261 | 349 | m_pc(0), |
262 | | m_debugger_pc(0), |
263 | | m_status(0), |
| 350 | m_shifted_pc(0), |
264 | 351 | m_timer0_top(0), |
265 | 352 | m_timer0_increment(1), |
266 | 353 | m_timer0_prescale(0), |
r18880 | r18881 | |
273 | 360 | m_timer2_increment(1), |
274 | 361 | m_timer2_prescale(0), |
275 | 362 | m_timer2_prescale_count(0), |
| 363 | m_spi_active(false), |
| 364 | m_spi_prescale(0), |
| 365 | m_spi_prescale_count(0), |
276 | 366 | m_addr_mask(addr_mask), |
277 | 367 | m_interrupt_pending(false), |
278 | 368 | m_icount(0), |
r18880 | r18881 | |
341 | 431 | m_pc = 0; |
342 | 432 | |
343 | 433 | m_program = &space(AS_PROGRAM); |
| 434 | m_data = &space(AS_DATA); |
344 | 435 | m_io = &space(AS_IO); |
345 | 436 | |
346 | 437 | // register our state for the debugger |
347 | 438 | astring tempstr; |
348 | | state_add(STATE_GENPC, "GENPC", m_pc).noshow(); |
349 | | state_add(STATE_GENFLAGS, "GENFLAGS", m_status).callimport().callexport().formatstr("%8s").noshow(); |
| 439 | state_add(STATE_GENPC, "GENPC", m_shifted_pc).noshow(); |
| 440 | state_add(STATE_GENFLAGS, "GENFLAGS", m_r[AVR8_REGIDX_SREG]).callimport().callexport().formatstr("%8s").noshow(); |
350 | 441 | state_add(AVR8_SREG, "STATUS", m_r[AVR8_REGIDX_SREG]).mask(0xff); |
351 | | state_add(AVR8_PC, "PC", m_debugger_pc).mask(0xffff); |
| 442 | state_add(AVR8_PC, "PC", m_shifted_pc).mask(0xffff); |
352 | 443 | state_add(AVR8_R0, "R0", m_r[ 0]).mask(0xff); |
353 | 444 | state_add(AVR8_R1, "R1", m_r[ 1]).mask(0xff); |
354 | 445 | state_add(AVR8_R2, "R2", m_r[ 2]).mask(0xff); |
r18880 | r18881 | |
384 | 475 | |
385 | 476 | // register our state for saving |
386 | 477 | save_item(NAME(m_pc)); |
387 | | save_item(NAME(m_status)); |
388 | 478 | save_item(NAME(m_r)); |
389 | 479 | save_item(NAME(m_timer0_top)); |
390 | 480 | save_item(NAME(m_timer0_increment)); |
r18880 | r18881 | |
405 | 495 | |
406 | 496 | // set our instruction counter |
407 | 497 | m_icountptr = &m_icount; |
| 498 | |
| 499 | m_eeprom = machine().root_device().memregion(eeprom_region)->base(); |
408 | 500 | } |
409 | 501 | |
410 | 502 | //------------------------------------------------- |
r18880 | r18881 | |
413 | 505 | |
414 | 506 | void avr8_device::device_reset() |
415 | 507 | { |
416 | | m_status = 0; |
417 | | io_write8(AVR8_REGIDX_SPL, 0); |
418 | | io_write8(AVR8_REGIDX_SPH, 0); |
| 508 | m_r[AVR8_REGIDX_SPL] = 0; |
| 509 | m_r[AVR8_REGIDX_SPH] = 0; |
419 | 510 | |
420 | | for (int i = 0; i < 32; i++) |
| 511 | for (int i = 0; i < 256; i++) |
421 | 512 | { |
422 | 513 | m_r[i] = 0; |
423 | 514 | } |
424 | 515 | |
| 516 | m_spi_active = false; |
| 517 | m_spi_prescale = 0; |
| 518 | m_spi_prescale_count = 0; |
| 519 | |
425 | 520 | m_timer0_top = 0; |
426 | 521 | m_timer0_increment = 1; |
427 | 522 | m_timer0_prescale = 0; |
r18880 | r18881 | |
465 | 560 | { |
466 | 561 | return &m_program_config; |
467 | 562 | } |
| 563 | else if (spacenum == AS_DATA) |
| 564 | { |
| 565 | return &m_data_config; |
| 566 | } |
468 | 567 | else if (spacenum == AS_IO) |
469 | 568 | { |
470 | 569 | return &m_io_config; |
r18880 | r18881 | |
484 | 583 | { |
485 | 584 | case STATE_GENFLAGS: |
486 | 585 | string.printf("%c%c%c%c%c%c%c%c", |
487 | | (m_status & 0x80) ? 'I' : '-', |
488 | | (m_status & 0x40) ? 'T' : '-', |
489 | | (m_status & 0x20) ? 'H' : '-', |
490 | | (m_status & 0x10) ? 'S' : '-', |
491 | | (m_status & 0x08) ? 'V' : '-', |
492 | | (m_status & 0x04) ? 'N' : '-', |
493 | | (m_status & 0x02) ? 'Z' : '-', |
494 | | (m_status & 0x01) ? 'C' : '-'); |
| 586 | (m_r[AVR8_REGIDX_SREG] & 0x80) ? 'I' : '-', |
| 587 | (m_r[AVR8_REGIDX_SREG] & 0x40) ? 'T' : '-', |
| 588 | (m_r[AVR8_REGIDX_SREG] & 0x20) ? 'H' : '-', |
| 589 | (m_r[AVR8_REGIDX_SREG] & 0x10) ? 'S' : '-', |
| 590 | (m_r[AVR8_REGIDX_SREG] & 0x08) ? 'V' : '-', |
| 591 | (m_r[AVR8_REGIDX_SREG] & 0x04) ? 'N' : '-', |
| 592 | (m_r[AVR8_REGIDX_SREG] & 0x02) ? 'Z' : '-', |
| 593 | (m_r[AVR8_REGIDX_SREG] & 0x01) ? 'C' : '-'); |
495 | 594 | break; |
496 | 595 | } |
497 | 596 | } |
r18880 | r18881 | |
535 | 634 | // MEMORY ACCESSORS |
536 | 635 | //************************************************************************** |
537 | 636 | |
538 | | inline UINT8 avr8_device::program_read8(UINT32 address) |
539 | | { |
540 | | return m_program->read_byte(address); |
541 | | } |
542 | | |
543 | | inline UINT16 avr8_device::program_read16(UINT32 address) |
544 | | { |
545 | | return m_program->read_word(address << 1); |
546 | | } |
547 | | |
548 | | inline void avr8_device::program_write8(UINT32 address, UINT8 data) |
549 | | { |
550 | | m_program->write_byte(address, data); |
551 | | } |
552 | | |
553 | | inline void avr8_device::program_write16(UINT32 address, UINT16 data) |
554 | | { |
555 | | m_program->write_word(address, data); |
556 | | } |
557 | | |
558 | | inline UINT8 avr8_device::io_read8(UINT16 address) |
559 | | { |
560 | | if (address < 0x100) |
561 | | { |
562 | | // Allow unhandled internal registers to be handled by external driver |
563 | | UINT8 data; |
564 | | if (io_reg_read(address, &data)) |
565 | | { |
566 | | return data; |
567 | | } |
568 | | } |
569 | | return m_io->read_byte(address); |
570 | | } |
571 | | |
572 | | inline void avr8_device::io_write8(UINT16 address, UINT8 data) |
573 | | { |
574 | | if (address < 0x100) |
575 | | { |
576 | | // Allow unhandled internal registers to be handled by external driver |
577 | | if (io_reg_write(address, data)) |
578 | | { |
579 | | return; |
580 | | } |
581 | | } |
582 | | m_io->write_byte(address, data); |
583 | | } |
584 | | |
585 | 637 | inline void avr8_device::push(UINT8 val) |
586 | 638 | { |
587 | 639 | UINT16 sp = SPREG; |
588 | | io_write8(sp, val); |
| 640 | m_data->write_byte(sp, val); |
589 | 641 | sp--; |
590 | | io_write8(AVR8_REGIDX_SPL, sp & 0x00ff); |
591 | | io_write8(AVR8_REGIDX_SPH, (sp >> 8) & 0x00ff); |
| 642 | m_r[AVR8_REGIDX_SPL] = sp & 0x00ff; |
| 643 | m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff; |
592 | 644 | } |
593 | 645 | |
594 | 646 | inline UINT8 avr8_device::pop() |
595 | 647 | { |
596 | 648 | UINT16 sp = SPREG; |
597 | 649 | sp++; |
598 | | io_write8(AVR8_REGIDX_SPL, sp & 0x00ff); |
599 | | io_write8(AVR8_REGIDX_SPH, (sp >> 8) & 0x00ff); |
600 | | return io_read8(sp); |
| 650 | m_r[AVR8_REGIDX_SPL] = sp & 0x00ff; |
| 651 | m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff; |
| 652 | return m_data->read_byte(sp); |
601 | 653 | } |
602 | 654 | |
603 | 655 | //************************************************************************** |
r18880 | r18881 | |
615 | 667 | push((m_pc >> 8) & 0x00ff); |
616 | 668 | push(m_pc & 0x00ff); |
617 | 669 | m_pc = vector; |
| 670 | m_shifted_pc = vector << 1; |
618 | 671 | } |
619 | 672 | else |
620 | 673 | { |
r18880 | r18881 | |
636 | 689 | static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] = |
637 | 690 | { |
638 | 691 | { AVR8_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK }, |
| 692 | { AVR8_INT_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK }, |
| 693 | { AVR8_INT_T0COMPA, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0A_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0A_MASK }, |
| 694 | { AVR8_INT_T0OVF, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_TOIE0_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_TOV0_MASK }, |
639 | 695 | { AVR8_INT_T1CAPT, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_ICIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK }, |
640 | 696 | { AVR8_INT_T1COMPB, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1B_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK }, |
641 | 697 | { AVR8_INT_T1COMPA, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1A_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK }, |
r18880 | r18881 | |
666 | 722 | //************************************************************************** |
667 | 723 | void avr8_device::timer_tick(int cycles) |
668 | 724 | { |
669 | | if (m_timer0_prescale != 0) |
| 725 | for(int count = 0; count < cycles; count++) |
670 | 726 | { |
671 | | m_timer0_prescale_count += cycles; |
672 | | while(m_timer0_prescale_count >= m_timer0_prescale) |
| 727 | m_elapsed_cycles++; |
| 728 | |
| 729 | if (m_spi_active && m_spi_prescale > 0 && m_spi_prescale_countdown >= 0) |
673 | 730 | { |
674 | | timer0_tick(); |
675 | | m_timer0_prescale_count -= m_timer0_prescale; |
| 731 | m_spi_prescale_count++; |
| 732 | if (m_spi_prescale_count >= m_spi_prescale) |
| 733 | { |
| 734 | UINT8 out_bit = (m_r[AVR8_REGIDX_SPDR] & (1 << m_spi_prescale_countdown)) >> m_spi_prescale_countdown; |
| 735 | m_spi_prescale_countdown--; |
| 736 | m_io->write_byte(0x01, (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0)); |
| 737 | m_r[AVR8_REGIDX_PORTB] = (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0); |
| 738 | m_spi_prescale_count -= m_spi_prescale; |
| 739 | } |
676 | 740 | } |
677 | | } |
678 | 741 | |
679 | | if (m_timer1_prescale != 0) |
680 | | { |
681 | | m_timer1_prescale_count += cycles; |
682 | | while(m_timer1_prescale_count >= m_timer1_prescale) |
| 742 | if (m_timer0_prescale != 0) |
683 | 743 | { |
684 | | timer1_tick(); |
685 | | m_timer1_prescale_count -= m_timer1_prescale; |
| 744 | m_timer0_prescale_count++; |
| 745 | if (m_timer0_prescale_count >= m_timer0_prescale) |
| 746 | { |
| 747 | timer0_tick(); |
| 748 | m_timer0_prescale_count -= m_timer0_prescale; |
| 749 | } |
686 | 750 | } |
687 | | } |
688 | 751 | |
689 | | if (m_timer2_prescale != 0) |
690 | | { |
691 | | m_timer2_prescale_count += cycles; |
692 | | while(m_timer2_prescale_count >= (m_timer2_prescale)) |
| 752 | if (m_timer1_prescale != 0) |
693 | 753 | { |
694 | | timer2_tick(); |
695 | | m_timer2_prescale_count -= (m_timer2_prescale); |
| 754 | m_timer1_prescale_count++; |
| 755 | if (m_timer1_prescale_count >= m_timer1_prescale) |
| 756 | { |
| 757 | timer1_tick(); |
| 758 | m_timer1_prescale_count -= m_timer1_prescale; |
| 759 | } |
696 | 760 | } |
| 761 | |
| 762 | if (m_timer2_prescale != 0) |
| 763 | { |
| 764 | m_timer2_prescale_count++; |
| 765 | if (m_timer2_prescale_count == m_timer2_prescale) |
| 766 | { |
| 767 | timer2_tick(); |
| 768 | m_timer2_prescale_count -= m_timer2_prescale; |
| 769 | } |
| 770 | } |
697 | 771 | } |
698 | 772 | } |
699 | 773 | |
700 | 774 | // Timer 0 Handling |
701 | 775 | void avr8_device::timer0_tick() |
702 | 776 | { |
| 777 | /* |
| 778 | UINT16 count = m_r[AVR8_REGIDX_TCNT0]; |
| 779 | INT32 wgm0 = ((m_r[AVR8_REGIDX_TCCR0B] & AVR8_TCCR0B_WGM0_2_MASK) >> 1) | |
| 780 | (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_WGM0_10_MASK); |
| 781 | |
| 782 | // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer |
| 783 | //UINT8 compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT, |
| 784 | //(m_r[AVR8_REGIDX_TCCR0A] & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT }; |
| 785 | UINT8 ocr0[2] = { m_r[AVR8_REGIDX_OCR0A], m_r[AVR8_REGIDX_OCR0B] }; |
| 786 | UINT8 ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR0_OCF0B_SHIFT) }; |
| 787 | INT32 increment = m_timer0_increment; |
| 788 | |
| 789 | for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++) |
| 790 | { |
| 791 | switch(wgm0) |
| 792 | { |
| 793 | case WGM02_FAST_PWM: |
| 794 | if(count == ocr0[reg]) |
| 795 | { |
| 796 | if (reg == 0) |
| 797 | { |
| 798 | m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; |
| 799 | count = 0; |
| 800 | increment = 0; |
| 801 | } |
| 802 | |
| 803 | m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; |
| 804 | } |
| 805 | else if(count == 0) |
| 806 | { |
| 807 | if (reg == 0) |
| 808 | { |
| 809 | m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; |
| 810 | } |
| 811 | } |
| 812 | break; |
| 813 | |
| 814 | case WGM02_FAST_PWM_CMP: |
| 815 | if(count == ocr0[reg]) |
| 816 | { |
| 817 | if (reg == 0) |
| 818 | { |
| 819 | m_r[AVR8_REGIDX_TIFR0] |= AVR8_TIFR0_TOV0_MASK; |
| 820 | count = 0; |
| 821 | increment = 0; |
| 822 | } |
| 823 | |
| 824 | m_r[AVR8_REGIDX_TIFR0] |= ocf0[reg]; |
| 825 | } |
| 826 | else if(count == 0) |
| 827 | { |
| 828 | if (reg == 0) |
| 829 | { |
| 830 | m_r[AVR8_REGIDX_TIFR0] &= ~AVR8_TIFR0_TOV0_MASK; |
| 831 | } |
| 832 | } |
| 833 | break; |
| 834 | |
| 835 | default: |
| 836 | // TODO |
| 837 | break; |
| 838 | } |
| 839 | switch(compare_mode[reg]) |
| 840 | { |
| 841 | case 0: |
| 842 | //verboselog(m_pc, 0, "update_timer0_compare_mode: Normal port operation (OC0 disconnected)\n"); |
| 843 | break; |
| 844 | |
| 845 | case 1: |
| 846 | case 2: |
| 847 | // TODO |
| 848 | break; |
| 849 | |
| 850 | case 3: |
| 851 | break; |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | m_r[AVR8_REGIDX_TCNT0] = count + increment; |
| 856 | |
| 857 | update_interrupt(AVR8_INTIDX_OCF0A); |
| 858 | update_interrupt(AVR8_INTIDX_OCF0B); |
| 859 | update_interrupt(AVR8_INTIDX_TOV0); |
| 860 | */ |
| 861 | } |
| 862 | |
| 863 | void avr8_device::update_timer0_waveform_gen_mode() |
| 864 | { |
| 865 | m_timer0_top = 0; |
| 866 | switch(AVR8_WGM0) |
| 867 | { |
| 868 | case WGM02_NORMAL: |
| 869 | case WGM02_PWM_PC: |
| 870 | case WGM02_FAST_PWM: |
| 871 | m_timer0_top = 0x00ff; |
| 872 | break; |
| 873 | |
| 874 | case WGM02_CTC_CMP: |
| 875 | case WGM02_PWM_PC_CMP: |
| 876 | case WGM02_FAST_PWM_CMP: |
| 877 | m_timer0_top = AVR8_OCR0A; |
| 878 | break; |
| 879 | |
| 880 | default: |
| 881 | verboselog(m_pc, 0, "update_timer0_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM0); |
| 882 | break; |
| 883 | } |
| 884 | } |
| 885 | |
| 886 | void avr8_device::changed_tccr0a(UINT8 data) |
| 887 | { |
| 888 | UINT8 oldtccr = AVR8_TCCR0A; |
| 889 | UINT8 newtccr = data; |
| 890 | UINT8 changed = newtccr ^ oldtccr; |
| 891 | |
| 892 | AVR8_TCCR0A = data; |
| 893 | |
| 894 | if(changed & AVR8_TCCR0A_WGM0_10_MASK) |
| 895 | { |
| 896 | // TODO |
| 897 | update_timer0_waveform_gen_mode(); |
| 898 | } |
| 899 | } |
| 900 | |
| 901 | void avr8_device::timer0_force_output_compare(int reg) |
| 902 | { |
703 | 903 | // TODO |
| 904 | verboselog(m_pc, 0, "timer0_force_output_compare: TODO; should be forcing OC0%c\n", avr8_reg_name[reg]); |
704 | 905 | } |
705 | 906 | |
| 907 | void avr8_device::changed_tccr0b(UINT8 data) |
| 908 | { |
| 909 | UINT8 oldtccr = AVR8_TCCR0B; |
| 910 | UINT8 newtccr = data; |
| 911 | UINT8 changed = newtccr ^ oldtccr; |
| 912 | |
| 913 | AVR8_TCCR0B = data; |
| 914 | |
| 915 | if(changed & AVR8_TCCR0B_FOC0A_MASK) |
| 916 | { |
| 917 | // TODO |
| 918 | timer0_force_output_compare(AVR8_REG_A); |
| 919 | } |
| 920 | |
| 921 | if(changed & AVR8_TCCR0B_FOC0B_MASK) |
| 922 | { |
| 923 | // TODO |
| 924 | timer0_force_output_compare(AVR8_REG_B); |
| 925 | } |
| 926 | |
| 927 | if(changed & AVR8_TCCR0B_WGM0_2_MASK) |
| 928 | { |
| 929 | // TODO |
| 930 | update_timer0_waveform_gen_mode(); |
| 931 | } |
| 932 | |
| 933 | if(changed & AVR8_TCCR0B_CS_MASK) |
| 934 | { |
| 935 | update_timer0_clock_source(); |
| 936 | } |
| 937 | } |
| 938 | |
| 939 | void avr8_device::update_timer0_clock_source() |
| 940 | { |
| 941 | switch(AVR8_TIMER0_CLOCK_SELECT) |
| 942 | { |
| 943 | case 0: // Counter stopped |
| 944 | m_timer0_prescale = 0; |
| 945 | break; |
| 946 | case 1: // Clk/1; no prescaling |
| 947 | m_timer0_prescale = 1; |
| 948 | break; |
| 949 | case 2: // Clk/8 |
| 950 | m_timer0_prescale = 8; |
| 951 | break; |
| 952 | case 3: // Clk/64 |
| 953 | m_timer0_prescale = 64; |
| 954 | break; |
| 955 | case 4: // Clk/256 |
| 956 | m_timer0_prescale = 256; |
| 957 | break; |
| 958 | case 5: // Clk/1024 |
| 959 | m_timer0_prescale = 1024; |
| 960 | break; |
| 961 | case 6: // T0 trigger, falling edge |
| 962 | case 7: // T0 trigger, rising edge |
| 963 | m_timer0_prescale = 0; |
| 964 | verboselog(m_pc, 0, "update_timer0_clock_source: T0 Trigger mode not implemented yet\n"); |
| 965 | break; |
| 966 | } |
| 967 | |
| 968 | if (m_timer0_prescale_count > m_timer0_prescale) |
| 969 | { |
| 970 | m_timer0_prescale_count = m_timer0_prescale - 1; |
| 971 | } |
| 972 | } |
| 973 | |
| 974 | void avr8_device::update_ocr0(UINT8 newval, UINT8 reg) |
| 975 | { |
| 976 | m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR0A : AVR8_REGIDX_OCR0B] = newval; |
| 977 | } |
| 978 | |
706 | 979 | // Timer 1 Handling |
707 | 980 | |
708 | 981 | void avr8_device::timer1_tick() |
r18880 | r18881 | |
726 | 999 | { |
727 | 1000 | switch(wgm1) |
728 | 1001 | { |
| 1002 | case WGM1_CTC_OCR: |
| 1003 | if (count == 0xffff) |
| 1004 | { |
| 1005 | m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK; |
| 1006 | update_interrupt(AVR8_INTIDX_TOV1); |
| 1007 | count = 0; |
| 1008 | increment = 0; |
| 1009 | } |
| 1010 | |
| 1011 | if (count == ocr1[reg]) |
| 1012 | { |
| 1013 | m_r[AVR8_REGIDX_TIFR1] |= ocf1[reg]; |
| 1014 | update_interrupt(int1[reg]); |
| 1015 | } |
| 1016 | else if (count == 0) |
| 1017 | { |
| 1018 | if (reg == 0) |
| 1019 | { |
| 1020 | m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK; |
| 1021 | update_interrupt(AVR8_INTIDX_TOV1); |
| 1022 | } |
| 1023 | |
| 1024 | m_r[AVR8_REGIDX_TIFR1] &= ~ocf1[reg]; |
| 1025 | update_interrupt(int1[reg]); |
| 1026 | } |
| 1027 | break; |
| 1028 | |
729 | 1029 | case WGM1_FAST_PWM_OCR: |
730 | 1030 | if(count == ocr1[reg]) |
731 | 1031 | { |
r18880 | r18881 | |
754 | 1054 | break; |
755 | 1055 | |
756 | 1056 | default: |
757 | | // TODO |
| 1057 | verboselog(m_pc, 0, "update_timer1_compare_mode: Unknown waveform generation mode: %02x\n", wgm1); |
758 | 1058 | break; |
759 | 1059 | } |
760 | 1060 | /* |
r18880 | r18881 | |
780 | 1080 | m_r[AVR8_REGIDX_TCNT1L] = count & 0xff; |
781 | 1081 | } |
782 | 1082 | |
783 | | void avr8_device::change_timsk1(UINT8 data) |
784 | | { |
785 | | UINT8 oldtimsk = AVR8_TIMSK1; |
786 | | UINT8 newtimsk = data; |
787 | | UINT8 changed = newtimsk ^ oldtimsk; |
788 | | |
789 | | AVR8_TIMSK1 = newtimsk; |
790 | | |
791 | | if(changed & AVR8_TIMSK1_ICIE1_MASK) |
792 | | { |
793 | | // Check for Input Capture Interrupt interrupt condition |
794 | | update_interrupt(AVR8_INTIDX_ICF1); |
795 | | } |
796 | | |
797 | | if(changed & AVR8_TIMSK1_OCIE1B_MASK) |
798 | | { |
799 | | // Check for Output Compare B Interrupt interrupt condition |
800 | | update_interrupt(AVR8_INTIDX_OCF1B); |
801 | | } |
802 | | |
803 | | if(changed & AVR8_TIMSK1_OCIE1A_MASK) |
804 | | { |
805 | | // Check for Output Compare A Interrupt interrupt condition |
806 | | update_interrupt(AVR8_INTIDX_OCF1A); |
807 | | } |
808 | | |
809 | | if(changed & AVR8_TIMSK1_TOIE1_MASK) |
810 | | { |
811 | | // Check for Output Compare A Interrupt interrupt condition |
812 | | update_interrupt(AVR8_INTIDX_TOV1); |
813 | | } |
814 | | } |
815 | | |
816 | 1083 | void avr8_device::update_timer1_waveform_gen_mode() |
817 | 1084 | { |
818 | 1085 | // TODO |
819 | 1086 | m_timer1_top = 0; |
820 | | verboselog(m_pc, 0, "update_timer1_waveform_gen_mode: TODO; WGM1 is %d\n", AVR8_WGM1 ); |
821 | 1087 | switch(AVR8_WGM1) |
822 | 1088 | { |
823 | 1089 | case WGM1_NORMAL: |
r18880 | r18881 | |
942 | 1208 | |
943 | 1209 | if(changed & AVR8_TCCR1B_WGM1_32_MASK) |
944 | 1210 | { |
945 | | // TODO |
946 | 1211 | update_timer1_waveform_gen_mode(); |
947 | 1212 | } |
948 | 1213 | |
r18880 | r18881 | |
981 | 1246 | { |
982 | 1247 | switch(wgm2) |
983 | 1248 | { |
984 | | case WGM2_FAST_PWM_CMP: |
| 1249 | case WGM02_FAST_PWM: |
985 | 1250 | if(count == ocr2[reg]) |
986 | 1251 | { |
987 | 1252 | if (reg == 0) |
r18880 | r18881 | |
1002 | 1267 | } |
1003 | 1268 | break; |
1004 | 1269 | |
| 1270 | case WGM02_FAST_PWM_CMP: |
| 1271 | if(count == ocr2[reg]) |
| 1272 | { |
| 1273 | if (reg == 0) |
| 1274 | { |
| 1275 | m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK; |
| 1276 | count = 0; |
| 1277 | increment = 0; |
| 1278 | } |
| 1279 | |
| 1280 | m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg]; |
| 1281 | } |
| 1282 | else if(count == 0) |
| 1283 | { |
| 1284 | if (reg == 0) |
| 1285 | { |
| 1286 | m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK; |
| 1287 | } |
| 1288 | } |
| 1289 | break; |
| 1290 | |
1005 | 1291 | default: |
1006 | 1292 | // TODO |
1007 | 1293 | break; |
r18880 | r18881 | |
1036 | 1322 | m_timer2_top = 0; |
1037 | 1323 | switch(AVR8_WGM2) |
1038 | 1324 | { |
1039 | | case WGM2_NORMAL: |
1040 | | case WGM2_PWM_PC: |
1041 | | case WGM2_FAST_PWM: |
| 1325 | case WGM02_NORMAL: |
| 1326 | case WGM02_PWM_PC: |
| 1327 | case WGM02_FAST_PWM: |
1042 | 1328 | m_timer2_top = 0x00ff; |
1043 | 1329 | break; |
1044 | 1330 | |
1045 | | case WGM2_CTC_CMP: |
1046 | | case WGM2_PWM_PC_CMP: |
1047 | | case WGM2_FAST_PWM_CMP: |
| 1331 | case WGM02_CTC_CMP: |
| 1332 | case WGM02_PWM_PC_CMP: |
| 1333 | case WGM02_FAST_PWM_CMP: |
1048 | 1334 | m_timer2_top = AVR8_OCR2A; |
1049 | 1335 | break; |
1050 | 1336 | |
r18880 | r18881 | |
1060 | 1346 | UINT8 newtccr = data; |
1061 | 1347 | UINT8 changed = newtccr ^ oldtccr; |
1062 | 1348 | |
| 1349 | AVR8_TCCR2A = data; |
| 1350 | |
1063 | 1351 | if(changed & AVR8_TCCR2A_WGM2_10_MASK) |
1064 | 1352 | { |
1065 | 1353 | // TODO |
r18880 | r18881 | |
1115 | 1403 | UINT8 newtccr = data; |
1116 | 1404 | UINT8 changed = newtccr ^ oldtccr; |
1117 | 1405 | |
| 1406 | AVR8_TCCR2B = data; |
| 1407 | |
1118 | 1408 | if(changed & AVR8_TCCR2B_FOC2A_MASK) |
1119 | 1409 | { |
1120 | 1410 | // TODO |
r18880 | r18881 | |
1146 | 1436 | // Nothing needs to be done? All handled in timer callback |
1147 | 1437 | } |
1148 | 1438 | |
| 1439 | /****************/ |
| 1440 | /* SPI Handling */ |
| 1441 | /****************/ |
| 1442 | |
| 1443 | void avr8_device::enable_spi() |
| 1444 | { |
| 1445 | // TODO |
| 1446 | } |
| 1447 | |
| 1448 | void avr8_device::disable_spi() |
| 1449 | { |
| 1450 | // TODO |
| 1451 | } |
| 1452 | |
| 1453 | void avr8_device::spi_update_masterslave_select() |
| 1454 | { |
| 1455 | // TODO |
| 1456 | } |
| 1457 | |
| 1458 | void avr8_device::spi_update_clock_polarity() |
| 1459 | { |
| 1460 | // TODO |
| 1461 | } |
| 1462 | |
| 1463 | void avr8_device::spi_update_clock_phase() |
| 1464 | { |
| 1465 | // TODO |
| 1466 | } |
| 1467 | |
| 1468 | const UINT8 avr8_device::spi_clock_divisor[8] = { 4, 16, 64, 128, 2, 8, 32, 64 }; |
| 1469 | |
| 1470 | void avr8_device::spi_update_clock_rate() |
| 1471 | { |
| 1472 | m_spi_prescale = spi_clock_divisor[AVR8_SPI_RATE]; |
| 1473 | m_spi_prescale_count &= m_spi_prescale - 1; |
| 1474 | } |
| 1475 | |
| 1476 | void avr8_device::change_spcr(UINT8 data) |
| 1477 | { |
| 1478 | UINT8 oldspcr = AVR8_SPCR; |
| 1479 | UINT8 newspcr = data; |
| 1480 | UINT8 changed = newspcr ^ oldspcr; |
| 1481 | UINT8 high_to_low = ~newspcr & oldspcr; |
| 1482 | UINT8 low_to_high = newspcr & ~oldspcr; |
| 1483 | |
| 1484 | AVR8_SPCR = data; |
| 1485 | |
| 1486 | if(changed & AVR8_SPCR_SPIE_MASK) |
| 1487 | { |
| 1488 | // Check for SPI interrupt condition |
| 1489 | update_interrupt(AVR8_INTIDX_SPI); |
| 1490 | } |
| 1491 | |
| 1492 | if(low_to_high & AVR8_SPCR_SPE_MASK) |
| 1493 | { |
| 1494 | enable_spi(); |
| 1495 | } |
| 1496 | else if(high_to_low & AVR8_SPCR_SPE_MASK) |
| 1497 | { |
| 1498 | disable_spi(); |
| 1499 | } |
| 1500 | |
| 1501 | if(changed & AVR8_SPCR_MSTR_MASK) |
| 1502 | { |
| 1503 | spi_update_masterslave_select(); |
| 1504 | } |
| 1505 | |
| 1506 | if(changed & AVR8_SPCR_CPOL_MASK) |
| 1507 | { |
| 1508 | spi_update_clock_polarity(); |
| 1509 | } |
| 1510 | |
| 1511 | if(changed & AVR8_SPCR_CPHA_MASK) |
| 1512 | { |
| 1513 | spi_update_clock_phase(); |
| 1514 | } |
| 1515 | |
| 1516 | if(changed & AVR8_SPCR_SPR_MASK) |
| 1517 | { |
| 1518 | spi_update_clock_rate(); |
| 1519 | } |
| 1520 | } |
| 1521 | |
| 1522 | void avr8_device::change_spsr(UINT8 data) |
| 1523 | { |
| 1524 | UINT8 oldspsr = AVR8_SPSR; |
| 1525 | UINT8 newspsr = data; |
| 1526 | UINT8 changed = newspsr ^ oldspsr; |
| 1527 | |
| 1528 | AVR8_SPSR &= ~1; |
| 1529 | AVR8_SPSR |= data & 1; |
| 1530 | |
| 1531 | if(changed & AVR8_SPSR_SPR2X_MASK) |
| 1532 | { |
| 1533 | spi_update_clock_rate(); |
| 1534 | } |
| 1535 | } |
| 1536 | |
1149 | 1537 | /*****************************************************************************/ |
1150 | 1538 | |
1151 | | bool avr8_device::io_reg_write(UINT16 offset, UINT8 data) |
| 1539 | WRITE8_MEMBER( avr8_device::regs_w ) |
1152 | 1540 | { |
1153 | 1541 | switch( offset ) |
1154 | 1542 | { |
| 1543 | case AVR8_REGIDX_TCCR0B: |
| 1544 | verboselog(m_pc, 0, "AVR8: TCCR0B = %02x\n", data ); |
| 1545 | changed_tccr0b(data); |
| 1546 | break; |
| 1547 | |
| 1548 | case AVR8_REGIDX_TCCR0A: |
| 1549 | verboselog(m_pc, 0, "AVR8: TCCR0A = %02x\n", data ); |
| 1550 | changed_tccr0a(data); |
| 1551 | break; |
| 1552 | |
| 1553 | case AVR8_REGIDX_OCR0A: |
| 1554 | verboselog(m_pc, 0, "AVR8: OCR0A = %02x\n", data); |
| 1555 | update_ocr0(AVR8_OCR0A, AVR8_REG_A); |
| 1556 | break; |
| 1557 | |
| 1558 | case AVR8_REGIDX_OCR0B: |
| 1559 | verboselog(m_pc, 0, "AVR8: OCR0B = %02x\n", data ); |
| 1560 | update_ocr0(AVR8_OCR0B, AVR8_REG_B); |
| 1561 | break; |
| 1562 | |
| 1563 | case AVR8_REGIDX_TIMSK0: |
| 1564 | verboselog(m_pc, 0, "AVR8: TIMSK0 = %02x\n", data ); |
| 1565 | m_r[AVR8_REGIDX_TIMSK0] = data; |
| 1566 | update_interrupt(AVR8_INTIDX_OCF0A); |
| 1567 | update_interrupt(AVR8_INTIDX_OCF0B); |
| 1568 | update_interrupt(AVR8_INTIDX_TOV0); |
| 1569 | break; |
| 1570 | |
| 1571 | case AVR8_REGIDX_TIFR0: |
| 1572 | verboselog(m_pc, 0, "AVR8: TIFR0 = %02x\n", data ); |
| 1573 | m_r[AVR8_REGIDX_TIFR0] &= ~(data & AVR8_TIFR0_MASK); |
| 1574 | update_interrupt(AVR8_INTIDX_OCF0A); |
| 1575 | update_interrupt(AVR8_INTIDX_OCF0B); |
| 1576 | update_interrupt(AVR8_INTIDX_TOV0); |
| 1577 | break; |
| 1578 | |
| 1579 | case AVR8_REGIDX_TCNT0: |
| 1580 | AVR8_TCNT0 = data; |
| 1581 | break; |
| 1582 | |
| 1583 | case AVR8_REGIDX_TCCR1B: |
| 1584 | verboselog(m_pc, 0, "AVR8: TCCR1B = %02x\n", data ); |
| 1585 | changed_tccr1b(data); |
| 1586 | break; |
| 1587 | |
| 1588 | case AVR8_REGIDX_TCCR1A: |
| 1589 | verboselog(m_pc, 0, "AVR8: TCCR1A = %02x\n", data ); |
| 1590 | changed_tccr1a(data); |
| 1591 | break; |
| 1592 | |
1155 | 1593 | case AVR8_REGIDX_OCR1BH: |
1156 | 1594 | verboselog(m_pc, 0, "AVR8: OCR1BH = %02x\n", data ); |
1157 | 1595 | update_ocr1((AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B); |
1158 | | return true; |
| 1596 | break; |
1159 | 1597 | |
1160 | 1598 | case AVR8_REGIDX_OCR1BL: |
1161 | 1599 | verboselog(m_pc, 0, "AVR8: OCR1BL = %02x\n", data ); |
1162 | 1600 | update_ocr1((AVR8_OCR1B & 0xff00) | data, AVR8_REG_B); |
1163 | | return true; |
| 1601 | break; |
1164 | 1602 | |
1165 | 1603 | case AVR8_REGIDX_OCR1AH: |
1166 | 1604 | verboselog(m_pc, 0, "AVR8: OCR1AH = %02x\n", data ); |
1167 | 1605 | update_ocr1((AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A); |
1168 | | return true; |
| 1606 | break; |
1169 | 1607 | |
1170 | 1608 | case AVR8_REGIDX_OCR1AL: |
1171 | 1609 | verboselog(m_pc, 0, "AVR8: OCR1AL = %02x\n", data ); |
1172 | 1610 | update_ocr1((AVR8_OCR1A & 0xff00) | data, AVR8_REG_A); |
1173 | | return true; |
| 1611 | break; |
1174 | 1612 | |
1175 | | case AVR8_REGIDX_TCCR1B: |
1176 | | verboselog(m_pc, 0, "AVR8: TCCR1B = %02x\n", data ); |
1177 | | changed_tccr1b(data); |
1178 | | return true; |
1179 | | |
1180 | | case AVR8_REGIDX_TCCR1A: |
1181 | | verboselog(m_pc, 0, "AVR8: TCCR1A = %02x\n", data ); |
1182 | | changed_tccr1a(data); |
1183 | | return true; |
1184 | | |
1185 | 1613 | case AVR8_REGIDX_TIMSK1: |
1186 | 1614 | verboselog(m_pc, 0, "AVR8: TIMSK1 = %02x\n", data ); |
1187 | | change_timsk1(data); |
1188 | | return true; |
| 1615 | m_r[AVR8_REGIDX_TIMSK1] = data; |
| 1616 | update_interrupt(AVR8_INTIDX_ICF1); |
| 1617 | update_interrupt(AVR8_INTIDX_OCF1A); |
| 1618 | update_interrupt(AVR8_INTIDX_OCF1B); |
| 1619 | update_interrupt(AVR8_INTIDX_TOV1); |
| 1620 | break; |
1189 | 1621 | |
1190 | 1622 | case AVR8_REGIDX_TIFR1: |
1191 | 1623 | verboselog(m_pc, 0, "AVR8: TIFR1 = %02x\n", data ); |
r18880 | r18881 | |
1194 | 1626 | update_interrupt(AVR8_INTIDX_OCF1A); |
1195 | 1627 | update_interrupt(AVR8_INTIDX_OCF1B); |
1196 | 1628 | update_interrupt(AVR8_INTIDX_TOV1); |
1197 | | return true; |
| 1629 | break; |
1198 | 1630 | |
| 1631 | case AVR8_REGIDX_TCNT1H: |
| 1632 | AVR8_TCNT1H = data; |
| 1633 | break; |
| 1634 | |
| 1635 | case AVR8_REGIDX_TCNT1L: |
| 1636 | AVR8_TCNT1L = data; |
| 1637 | break; |
| 1638 | |
1199 | 1639 | case AVR8_REGIDX_TCCR2B: |
1200 | 1640 | verboselog(m_pc, 0, "AVR8: TCCR2B = %02x\n", data ); |
1201 | | changed_tccr2b(data); |
1202 | | return true; |
| 1641 | break; |
1203 | 1642 | |
1204 | 1643 | case AVR8_REGIDX_TCCR2A: |
1205 | 1644 | verboselog(m_pc, 0, "AVR8: TCCR2A = %02x\n", data ); |
1206 | 1645 | changed_tccr2a(data); |
1207 | | return true; |
| 1646 | break; |
1208 | 1647 | |
1209 | 1648 | case AVR8_REGIDX_OCR2A: |
1210 | 1649 | update_ocr2(data, AVR8_REG_A); |
1211 | | return true; |
| 1650 | break; |
1212 | 1651 | |
1213 | 1652 | case AVR8_REGIDX_OCR2B: |
1214 | 1653 | update_ocr2(data, AVR8_REG_B); |
1215 | | return true; |
| 1654 | break; |
1216 | 1655 | |
| 1656 | case AVR8_REGIDX_TIMSK2: |
| 1657 | verboselog(m_pc, 0, "AVR8: TIMSK2 = %02x\n", data ); |
| 1658 | m_r[AVR8_REGIDX_TIMSK2] = data; |
| 1659 | update_interrupt(AVR8_INTIDX_OCF2A); |
| 1660 | update_interrupt(AVR8_INTIDX_OCF2B); |
| 1661 | update_interrupt(AVR8_INTIDX_TOV2); |
| 1662 | break; |
| 1663 | |
| 1664 | case AVR8_REGIDX_TIFR2: |
| 1665 | verboselog(m_pc, 0, "AVR8: TIFR2 = %02x\n", data ); |
| 1666 | m_r[AVR8_REGIDX_TIFR2] &= ~(data & AVR8_TIFR2_MASK); |
| 1667 | update_interrupt(AVR8_INTIDX_OCF2A); |
| 1668 | update_interrupt(AVR8_INTIDX_OCF2B); |
| 1669 | update_interrupt(AVR8_INTIDX_TOV2); |
| 1670 | break; |
| 1671 | |
1217 | 1672 | case AVR8_REGIDX_TCNT2: |
1218 | 1673 | AVR8_TCNT2 = data; |
1219 | | return true; |
| 1674 | break; |
1220 | 1675 | |
1221 | 1676 | case AVR8_REGIDX_GTCCR: |
1222 | 1677 | if (data & AVR8_GTCCR_PSRASY_MASK) |
r18880 | r18881 | |
1224 | 1679 | data &= ~AVR8_GTCCR_PSRASY_MASK; |
1225 | 1680 | m_timer2_prescale_count = 0; |
1226 | 1681 | } |
1227 | | //verboselog(m_pc, 0, "AVR8: GTCCR = %02x\n", data ); |
1228 | | // TODO |
1229 | | return true; |
| 1682 | break; |
1230 | 1683 | |
1231 | 1684 | case AVR8_REGIDX_SPL: |
1232 | 1685 | case AVR8_REGIDX_SPH: |
| 1686 | case AVR8_REGIDX_DDRA: |
| 1687 | case AVR8_REGIDX_DDRB: |
| 1688 | case AVR8_REGIDX_DDRC: |
| 1689 | case AVR8_REGIDX_DDRD: |
| 1690 | case AVR8_REGIDX_EEARL: |
| 1691 | case AVR8_REGIDX_EEARH: |
| 1692 | case AVR8_REGIDX_SREG: |
1233 | 1693 | m_r[offset] = data; |
1234 | | return true; |
| 1694 | break; |
1235 | 1695 | |
| 1696 | case AVR8_REGIDX_EECR: |
| 1697 | if (data & AVR8_EECR_EERE) |
| 1698 | { |
| 1699 | UINT16 addr = (m_r[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8; |
| 1700 | addr |= m_r[AVR8_REGIDX_EEARL]; |
| 1701 | m_r[AVR8_REGIDX_EEDR] = m_eeprom[addr]; |
| 1702 | } |
| 1703 | break; |
| 1704 | |
1236 | 1705 | case AVR8_REGIDX_GPIOR0: |
1237 | | verboselog(m_pc, 0, "AVR8: GPIOR0 Write: %02x\n", data); |
| 1706 | verboselog(m_pc, 1, "AVR8: GPIOR0 Write: %02x\n", data); |
1238 | 1707 | m_r[offset] = data; |
1239 | | return true; |
| 1708 | break; |
1240 | 1709 | |
1241 | | case AVR8_REGIDX_SREG: |
1242 | | m_status = data; |
1243 | | return true; |
| 1710 | case AVR8_REGIDX_PORTA: |
| 1711 | m_io->write_byte(0x00, data); |
| 1712 | m_r[AVR8_REGIDX_PORTA] = data; |
| 1713 | break; |
1244 | 1714 | |
1245 | 1715 | case AVR8_REGIDX_PORTB: |
1246 | | if (m_portb_changed) |
1247 | | { |
1248 | | UINT8 changed = m_r[AVR8_REGIDX_PORTB] ^ data; |
1249 | | (*m_portb_changed)(*this, data, changed); |
1250 | | m_r[AVR8_REGIDX_PORTB] = data; |
1251 | | } |
| 1716 | m_io->write_byte(0x01, data); |
| 1717 | m_r[AVR8_REGIDX_PORTB] = data; |
1252 | 1718 | break; |
1253 | 1719 | |
1254 | 1720 | case AVR8_REGIDX_PORTC: |
1255 | | if (m_portc_changed) |
1256 | | { |
1257 | | UINT8 changed = m_r[AVR8_REGIDX_PORTC] ^ data; |
1258 | | (*m_portc_changed)(*this, data, changed); |
1259 | | m_r[AVR8_REGIDX_PORTC] = data; |
1260 | | } |
| 1721 | m_io->write_byte(0x02, data); |
| 1722 | m_r[AVR8_REGIDX_PORTC] = data; |
1261 | 1723 | break; |
1262 | 1724 | |
1263 | 1725 | case AVR8_REGIDX_PORTD: |
1264 | | if (m_portd_changed) |
1265 | | { |
1266 | | UINT8 changed = m_r[AVR8_REGIDX_PORTD] ^ data; |
1267 | | (*m_portd_changed)(*this, data, changed); |
1268 | | m_r[AVR8_REGIDX_PORTD] = data; |
1269 | | } |
1270 | | break; |
| 1726 | m_io->write_byte(0x03, data); |
| 1727 | m_r[AVR8_REGIDX_PORTD] = data; |
| 1728 | break; |
1271 | 1729 | |
| 1730 | case AVR8_REGIDX_SPSR: |
| 1731 | change_spsr(data); |
| 1732 | break; |
| 1733 | |
| 1734 | case AVR8_REGIDX_SPCR: |
| 1735 | change_spcr(data); |
| 1736 | break; |
| 1737 | |
| 1738 | case AVR8_REGIDX_SPDR: |
| 1739 | { |
| 1740 | m_r[AVR8_REGIDX_SPDR] = data; |
| 1741 | m_spi_active = true; |
| 1742 | m_spi_prescale_countdown = 7; |
| 1743 | m_spi_prescale_count = 0; |
| 1744 | break; |
| 1745 | } |
| 1746 | |
1272 | 1747 | default: |
1273 | | return false; |
| 1748 | verboselog(m_pc, 0, "AVR8: Unknown Register Write: %02x = %02x\n", (UINT8)offset, data); |
| 1749 | break; |
1274 | 1750 | } |
1275 | | return false; |
1276 | 1751 | } |
1277 | 1752 | |
1278 | | bool avr8_device::io_reg_read(UINT16 offset, UINT8 *data) |
| 1753 | READ8_MEMBER( avr8_device::regs_r ) |
1279 | 1754 | { |
| 1755 | //printf("offset %04x\n", offset); |
1280 | 1756 | switch( offset ) |
1281 | 1757 | { |
1282 | 1758 | case AVR8_REGIDX_SPL: |
r18880 | r18881 | |
1284 | 1760 | case AVR8_REGIDX_TCNT1L: |
1285 | 1761 | case AVR8_REGIDX_TCNT1H: |
1286 | 1762 | case AVR8_REGIDX_TCNT2: |
| 1763 | case AVR8_REGIDX_PORTA: |
1287 | 1764 | case AVR8_REGIDX_PORTB: |
1288 | 1765 | case AVR8_REGIDX_PORTC: |
1289 | 1766 | case AVR8_REGIDX_PORTD: |
1290 | | *data = m_r[offset]; |
1291 | | return true; |
1292 | | |
| 1767 | case AVR8_REGIDX_DDRA: |
| 1768 | case AVR8_REGIDX_DDRB: |
| 1769 | case AVR8_REGIDX_DDRC: |
| 1770 | case AVR8_REGIDX_DDRD: |
1293 | 1771 | case AVR8_REGIDX_GPIOR0: |
1294 | | *data = m_r[offset]; |
1295 | | verboselog(m_pc, 0, "AVR8: GPIOR0 Read: %02x\n", *data); |
1296 | | return true; |
1297 | | |
| 1772 | case AVR8_REGIDX_EEDR: |
1298 | 1773 | case AVR8_REGIDX_SREG: |
1299 | | *data = m_status; |
1300 | | return true; |
| 1774 | return m_r[offset]; |
1301 | 1775 | |
1302 | 1776 | default: |
1303 | | return false; |
| 1777 | verboselog(m_pc, 0, "AVR8: Unknown Register Read: %02x\n", (UINT8)offset); |
| 1778 | return 0; |
1304 | 1779 | } |
1305 | | |
1306 | | return false; |
1307 | 1780 | } |
1308 | 1781 | |
1309 | 1782 | |
r18880 | r18881 | |
1370 | 1843 | opcycles = 1; |
1371 | 1844 | |
1372 | 1845 | m_pc &= m_addr_mask; |
| 1846 | m_shifted_pc &= (m_addr_mask << 1) | 1; |
1373 | 1847 | |
1374 | | debugger_instruction_hook(this, m_debugger_pc); |
| 1848 | debugger_instruction_hook(this, m_shifted_pc); |
1375 | 1849 | |
1376 | | op = (UINT32)program_read16(m_pc); |
| 1850 | op = (UINT32)m_program->read_word(m_shifted_pc); |
1377 | 1851 | |
1378 | 1852 | switch(op & 0xf000) |
1379 | 1853 | { |
r18880 | r18881 | |
1622 | 2096 | switch(op & 0x0208) |
1623 | 2097 | { |
1624 | 2098 | case 0x0000: // LDD Rd,Z+q |
1625 | | m_r[RD5(op)] = io_read8(ZREG + QCONST6(op)); |
| 2099 | m_r[RD5(op)] = m_data->read_byte(ZREG + QCONST6(op)); |
1626 | 2100 | opcycles = 2; |
1627 | 2101 | break; |
1628 | 2102 | case 0x0008: // LDD Rd,Y+q |
1629 | | m_r[RD5(op)] = io_read8(YREG + QCONST6(op)); |
| 2103 | m_r[RD5(op)] = m_data->read_byte(YREG + QCONST6(op)); |
1630 | 2104 | opcycles = 2; |
1631 | 2105 | break; |
1632 | 2106 | case 0x0200: // STD Z+q,Rr |
1633 | | io_write8(ZREG + QCONST6(op), m_r[RD5(op)]); |
| 2107 | m_data->write_byte(ZREG + QCONST6(op), m_r[RD5(op)]); |
1634 | 2108 | opcycles = 2; |
1635 | 2109 | break; |
1636 | 2110 | case 0x0208: // STD Y+q,Rr |
1637 | | io_write8(YREG + QCONST6(op), m_r[RD5(op)]); |
| 2111 | m_data->write_byte(YREG + QCONST6(op), m_r[RD5(op)]); |
1638 | 2112 | opcycles = 2; |
1639 | 2113 | break; |
1640 | 2114 | } |
r18880 | r18881 | |
1649 | 2123 | case 0x0000: // LDS Rd,k |
1650 | 2124 | op <<= 16; |
1651 | 2125 | m_pc++; |
1652 | | op |= program_read16(m_pc); |
1653 | | m_r[RD5(op >> 16)] = io_read8(op & 0x0000ffff); |
| 2126 | m_shifted_pc += 2; |
| 2127 | op |= m_program->read_word(m_shifted_pc); |
| 2128 | m_r[RD5(op >> 16)] = m_data->read_byte(op & 0x0000ffff); |
1654 | 2129 | opcycles = 2; |
1655 | 2130 | break; |
1656 | 2131 | case 0x0001: // LD Rd,Z+ |
r18880 | r18881 | |
1659 | 2134 | case 0x0002: // LD Rd,-Z |
1660 | 2135 | pd = ZREG; |
1661 | 2136 | pd--; |
1662 | | m_r[RD5(op)] = io_read8(pd); |
| 2137 | m_r[RD5(op)] = m_data->read_byte(pd); |
1663 | 2138 | m_r[31] = (pd >> 8) & 0x00ff; |
1664 | 2139 | m_r[30] = pd & 0x00ff; |
1665 | 2140 | opcycles = 2; |
1666 | 2141 | break; |
1667 | 2142 | case 0x0004: // LPM Rd,Z |
1668 | | m_r[RD5(op)] = program_read8(ZREG); |
| 2143 | m_r[RD5(op)] = m_program->read_byte(ZREG); |
1669 | 2144 | opcycles = 3; |
1670 | 2145 | break; |
1671 | 2146 | case 0x0005: // LPM Rd,Z+ |
1672 | 2147 | pd = ZREG; |
1673 | | m_r[RD5(op)] = program_read8(pd); |
| 2148 | m_r[RD5(op)] = m_program->read_byte(pd); |
1674 | 2149 | pd++; |
1675 | 2150 | m_r[31] = (pd >> 8) & 0x00ff; |
1676 | 2151 | m_r[30] = pd & 0x00ff; |
r18880 | r18881 | |
1686 | 2161 | break; |
1687 | 2162 | case 0x0009: // LD Rd,Y+ |
1688 | 2163 | pd = YREG; |
1689 | | m_r[RD5(op)] = io_read8(pd); |
| 2164 | m_r[RD5(op)] = m_data->read_byte(pd); |
1690 | 2165 | pd++; |
1691 | 2166 | m_r[29] = (pd >> 8) & 0x00ff; |
1692 | 2167 | m_r[28] = pd & 0x00ff; |
r18880 | r18881 | |
1695 | 2170 | case 0x000a: // LD Rd,-Y |
1696 | 2171 | pd = YREG; |
1697 | 2172 | pd--; |
1698 | | m_r[RD5(op)] = io_read8(pd); |
| 2173 | m_r[RD5(op)] = m_data->read_byte(pd); |
1699 | 2174 | m_r[29] = (pd >> 8) & 0x00ff; |
1700 | 2175 | m_r[28] = pd & 0x00ff; |
1701 | 2176 | opcycles = 2; |
1702 | 2177 | break; |
1703 | 2178 | case 0x000c: // LD Rd,X |
1704 | | m_r[RD5(op)] = io_read8(XREG); |
| 2179 | m_r[RD5(op)] = m_data->read_byte(XREG); |
1705 | 2180 | opcycles = 2; |
1706 | 2181 | break; |
1707 | 2182 | case 0x000d: // LD Rd,X+ |
1708 | 2183 | pd = XREG; |
1709 | | m_r[RD5(op)] = io_read8(pd); |
| 2184 | m_r[RD5(op)] = m_data->read_byte(pd); |
1710 | 2185 | pd++; |
1711 | 2186 | m_r[27] = (pd >> 8) & 0x00ff; |
1712 | 2187 | m_r[26] = pd & 0x00ff; |
r18880 | r18881 | |
1715 | 2190 | case 0x000e: // LD Rd,-X |
1716 | 2191 | pd = XREG; |
1717 | 2192 | pd--; |
1718 | | m_r[RD5(op)] = io_read8(pd); |
| 2193 | m_r[RD5(op)] = m_data->read_byte(pd); |
1719 | 2194 | m_r[27] = (pd >> 8) & 0x00ff; |
1720 | 2195 | m_r[26] = pd & 0x00ff; |
1721 | 2196 | opcycles = 2; |
r18880 | r18881 | |
1737 | 2212 | case 0x0000: // STS k,Rr |
1738 | 2213 | op <<= 16; |
1739 | 2214 | m_pc++; |
1740 | | op |= program_read16(m_pc); |
1741 | | io_write8(op & 0x0000ffff, m_r[RD5(op >> 16)]); |
| 2215 | m_shifted_pc += 2; |
| 2216 | op |= m_program->read_word(m_shifted_pc); |
| 2217 | m_data->write_byte(op & 0x0000ffff, m_r[RD5(op >> 16)]); |
1742 | 2218 | opcycles = 2; |
1743 | 2219 | break; |
1744 | 2220 | case 0x0001: // ST Z+,Rd |
1745 | | //output += sprintf( output, "ST Z+, R%d", RD5(op) ); |
1746 | | unimplemented_opcode(op); |
| 2221 | pd = ZREG; |
| 2222 | m_data->write_byte(pd, m_r[RD5(op)]); |
| 2223 | pd++; |
| 2224 | m_r[31] = (pd >> 8) & 0x00ff; |
| 2225 | m_r[30] = pd & 0x00ff; |
| 2226 | opcycles = 2; |
1747 | 2227 | break; |
1748 | 2228 | case 0x0002: // ST -Z,Rd |
1749 | 2229 | //output += sprintf( output, "ST -Z , R%d", RD5(op) ); |
r18880 | r18881 | |
1751 | 2231 | break; |
1752 | 2232 | case 0x0009: // ST Y+,Rd |
1753 | 2233 | pd = YREG; |
1754 | | io_write8(pd, m_r[RD5(op)]); |
| 2234 | m_data->write_byte(pd, m_r[RD5(op)]); |
1755 | 2235 | pd++; |
1756 | 2236 | m_r[29] = (pd >> 8) & 0x00ff; |
1757 | 2237 | m_r[28] = pd & 0x00ff; |
r18880 | r18881 | |
1762 | 2242 | unimplemented_opcode(op); |
1763 | 2243 | break; |
1764 | 2244 | case 0x000c: // ST X,Rd |
1765 | | io_write8(XREG, m_r[RD5(op)]); |
| 2245 | m_data->write_byte(XREG, m_r[RD5(op)]); |
1766 | 2246 | break; |
1767 | 2247 | case 0x000d: // ST X+,Rd |
1768 | 2248 | pd = XREG; |
1769 | | io_write8(pd, m_r[RD5(op)]); |
| 2249 | m_data->write_byte(pd, m_r[RD5(op)]); |
1770 | 2250 | pd++; |
1771 | 2251 | m_r[27] = (pd >> 8) & 0x00ff; |
1772 | 2252 | m_r[26] = pd & 0x00ff; |
r18880 | r18881 | |
1909 | 2389 | case 0x000d: // JMP k |
1910 | 2390 | offs = KCONST22(op) << 16; |
1911 | 2391 | m_pc++; |
1912 | | offs |= program_read16(m_pc); |
| 2392 | m_shifted_pc += 2; |
| 2393 | offs |= m_program->read_word(m_shifted_pc); |
1913 | 2394 | m_pc = offs; |
1914 | 2395 | m_pc--; |
1915 | 2396 | opcycles = 3; |
r18880 | r18881 | |
1920 | 2401 | push((m_pc + 1) & 0x00ff); |
1921 | 2402 | offs = KCONST22(op) << 16; |
1922 | 2403 | m_pc++; |
1923 | | offs |= program_read16(m_pc); |
| 2404 | m_shifted_pc += 2; |
| 2405 | offs |= m_program->read_word(m_shifted_pc); |
1924 | 2406 | m_pc = offs; |
1925 | 2407 | m_pc--; |
1926 | 2408 | opcycles = 4; |
r18880 | r18881 | |
2028 | 2510 | unimplemented_opcode(op); |
2029 | 2511 | break; |
2030 | 2512 | case 0x00c0: // LPM |
2031 | | m_r[0] = program_read8(ZREG); |
| 2513 | m_r[0] = m_program->read_byte(ZREG); |
2032 | 2514 | opcycles = 3; |
2033 | 2515 | break; |
2034 | 2516 | case 0x00d0: // ELPM |
r18880 | r18881 | |
2111 | 2593 | opcycles = 2; |
2112 | 2594 | break; |
2113 | 2595 | case 0x0700: // SBIW Rd+1:Rd,K |
2114 | | //output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) ); |
2115 | | unimplemented_opcode(op); |
| 2596 | rd = m_r[24 + (DCONST(op) << 1)]; |
| 2597 | rr = m_r[25 + (DCONST(op) << 1)]; |
| 2598 | pd = rd; |
| 2599 | pd |= rr << 8; |
| 2600 | pd -= KCONST6(op); |
| 2601 | SREG_W(AVR8_SREG_V, BIT(pd,15) & NOT(BIT(rr,7))); |
| 2602 | SREG_W(AVR8_SREG_N, BIT(pd,15)); |
| 2603 | SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V)); |
| 2604 | SREG_W(AVR8_SREG_Z, (pd == 0) ? 1 : 0); |
| 2605 | SREG_W(AVR8_SREG_C, NOT(BIT(pd,15)) & BIT(rr,7)); |
| 2606 | m_r[24 + (DCONST(op) << 1)] = pd & 0x00ff; |
| 2607 | m_r[25 + (DCONST(op) << 1)] = (pd >> 8) & 0x00ff; |
| 2608 | opcycles = 2; |
2116 | 2609 | break; |
2117 | 2610 | case 0x0800: // CBI A,b |
2118 | 2611 | //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) ); |
2119 | | io_write8(32 + ACONST5(op), io_read8(32 + ACONST5(op)) &~ (1 << RR3(op))); |
| 2612 | m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) &~ (1 << RR3(op))); |
2120 | 2613 | opcycles = 2; |
2121 | 2614 | break; |
2122 | 2615 | case 0x0900: // SBIC A,b |
2123 | | if(NOT(BIT(io_read8(32 + ACONST5(op)), RR3(op)))) |
| 2616 | if(NOT(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op)))) |
2124 | 2617 | { |
2125 | | op = (UINT32)program_read16(m_pc + 1); |
| 2618 | op = (UINT32)m_program->read_word(m_shifted_pc + 2); |
2126 | 2619 | opcycles = is_long_opcode(op) ? 3 : 2; |
2127 | 2620 | m_pc += is_long_opcode(op) ? 2 : 1; |
2128 | 2621 | } |
2129 | 2622 | break; |
2130 | 2623 | case 0x0a00: // SBI A,b |
2131 | | io_write8(32 + ACONST5(op), io_read8(32 + ACONST5(op)) | (1 << RR3(op))); |
| 2624 | m_data->write_byte(32 + ACONST5(op), m_data->read_byte(32 + ACONST5(op)) | (1 << RR3(op))); |
2132 | 2625 | opcycles = 2; |
2133 | 2626 | break; |
2134 | 2627 | case 0x0b00: // SBIS A,b |
2135 | | if(BIT(io_read8(32 + ACONST5(op)), RR3(op))) |
| 2628 | if(BIT(m_data->read_byte(32 + ACONST5(op)), RR3(op))) |
2136 | 2629 | { |
2137 | | op = (UINT32)program_read16(m_pc + 1); |
| 2630 | op = (UINT32)m_program->read_word(m_shifted_pc + 2); |
2138 | 2631 | opcycles = is_long_opcode(op) ? 3 : 2; |
2139 | 2632 | m_pc += is_long_opcode(op) ? 2 : 1; |
2140 | 2633 | } |
r18880 | r18881 | |
2155 | 2648 | case 0xb000: |
2156 | 2649 | if(op & 0x0800) // OUT A,Rr |
2157 | 2650 | { |
2158 | | io_write8(32 + ACONST6(op), m_r[RD5(op)]); |
| 2651 | m_data->write_byte(32 + ACONST6(op), m_r[RD5(op)]); |
2159 | 2652 | } |
2160 | 2653 | else // IN Rd,A |
2161 | 2654 | { |
2162 | | m_r[RD5(op)] = io_read8(0x20 + ACONST6(op)); |
| 2655 | m_r[RD5(op)] = m_data->read_byte(0x20 + ACONST6(op)); |
2163 | 2656 | } |
2164 | 2657 | break; |
2165 | 2658 | case 0xc000: // RJMP k |
r18880 | r18881 | |
2226 | 2719 | { |
2227 | 2720 | if(BIT(m_r[RD5(op)], RR3(op))) |
2228 | 2721 | { |
2229 | | op = (UINT32)program_read16(m_pc++); |
2230 | | m_pc += is_long_opcode(op) ? 1 : 0; |
| 2722 | op = (UINT32)m_program->read_word(m_shifted_pc + 2); |
| 2723 | m_pc += is_long_opcode(op) ? 2 : 1; |
2231 | 2724 | opcycles = is_long_opcode(op) ? 3 : 2; |
2232 | 2725 | } |
2233 | 2726 | } |
r18880 | r18881 | |
2235 | 2728 | { |
2236 | 2729 | if(NOT(BIT(m_r[RD5(op)], RR3(op)))) |
2237 | 2730 | { |
2238 | | op = (UINT32)program_read16(m_pc++); |
2239 | | m_pc += is_long_opcode(op) ? 1 : 0; |
| 2731 | op = (UINT32)m_program->read_word(m_shifted_pc + 2); |
| 2732 | m_pc += is_long_opcode(op) ? 2 : 1; |
2240 | 2733 | opcycles = is_long_opcode(op) ? 3 : 2; |
2241 | 2734 | } |
2242 | 2735 | } |
r18880 | r18881 | |
2247 | 2740 | |
2248 | 2741 | m_pc++; |
2249 | 2742 | |
2250 | | m_debugger_pc = m_pc << 1; |
| 2743 | m_shifted_pc = m_pc << 1; |
2251 | 2744 | |
2252 | 2745 | m_icount -= opcycles; |
2253 | 2746 | |
2254 | | m_elapsed_cycles += opcycles; |
2255 | | |
2256 | 2747 | timer_tick(opcycles); |
2257 | 2748 | } |
2258 | 2749 | } |
trunk/src/mess/drivers/craft.c
r18880 | r18881 | |
41 | 41 | #define PIXELS_PER_FRAME (CYCLES_PER_FRAME) |
42 | 42 | |
43 | 43 | /****************************************************\ |
44 | | * I/O defines * |
45 | | \****************************************************/ |
46 | | |
47 | | #define AVR8_PORTD (state->m_regs[AVR8_REGIDX_PORTD]) |
48 | | #define AVR8_DDRD (state->m_regs[AVR8_REGIDX_DDRD]) |
49 | | #define AVR8_PORTC (state->m_regs[AVR8_REGIDX_PORTC]) |
50 | | #define AVR8_DDRC (state->m_regs[AVR8_REGIDX_DDRC]) |
51 | | #define AVR8_PORTB (state->m_regs[AVR8_REGIDX_PORTB]) |
52 | | #define AVR8_DDRB (state->m_regs[AVR8_REGIDX_DDRB]) |
53 | | |
54 | | #define AVR8_SPSR (state->m_regs[AVR8_REGIDX_SPSR]) |
55 | | #define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK) |
56 | | |
57 | | #define AVR8_SPCR (state->m_regs[AVR8_REGIDX_SPCR]) |
58 | | #define AVR8_SPCR_SPIE ((AVR8_SPCR & AVR8_SPCR_SPIE_MASK) >> 7) |
59 | | #define AVR8_SPCR_SPE ((AVR8_SPCR & AVR8_SPCR_SPE_MASK) >> 6) |
60 | | #define AVR8_SPCR_DORD ((AVR8_SPCR & AVR8_SPCR_DORD_MASK) >> 5) |
61 | | #define AVR8_SPCR_MSTR ((AVR8_SPCR & AVR8_SPCR_MSTR_MASK) >> 4) |
62 | | #define AVR8_SPCR_CPOL ((AVR8_SPCR & AVR8_SPCR_CPOL_MASK) >> 3) |
63 | | #define AVR8_SPCR_CPHA ((AVR8_SPCR & AVR8_SPCR_CPHA_MASK) >> 2) |
64 | | #define AVR8_SPCR_SPR (AVR8_SPCR & AVR8_SPCR_SPR_MASK) |
65 | | |
66 | | |
67 | | /****************************************************\ |
68 | 44 | * I/O devices * |
69 | 45 | \****************************************************/ |
70 | 46 | |
r18880 | r18881 | |
77 | 53 | { |
78 | 54 | } |
79 | 55 | |
| 56 | void video_update(); |
| 57 | |
80 | 58 | virtual void machine_start(); |
81 | 59 | |
82 | | dac_device* dac; |
| 60 | dac_device* m_dac; |
83 | 61 | |
84 | | UINT8 m_regs[0x100]; |
85 | | UINT8* m_eeprom; |
86 | 62 | UINT32 m_last_cycles; |
87 | | |
88 | | bool m_spi_pending; |
89 | | UINT64 m_spi_start_cycle; |
90 | | |
91 | 63 | UINT64 m_frame_start_cycle; |
92 | 64 | |
| 65 | UINT8 m_port_b; |
| 66 | UINT8 m_port_c; |
| 67 | UINT8 m_port_d; |
| 68 | |
| 69 | UINT8 m_latched_color; |
93 | 70 | UINT8 m_pixels[PIXELS_PER_FRAME]; |
94 | 71 | |
95 | 72 | required_device<avr8_device> m_maincpu; |
96 | 73 | |
97 | | DECLARE_READ8_MEMBER(avr8_read); |
98 | | DECLARE_WRITE8_MEMBER(avr8_write); |
| 74 | DECLARE_READ8_MEMBER(port_r); |
| 75 | DECLARE_WRITE8_MEMBER(port_w); |
99 | 76 | DECLARE_DRIVER_INIT(craft); |
100 | 77 | virtual void machine_reset(); |
101 | 78 | UINT32 screen_update_craft(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
102 | | TIMER_CALLBACK_MEMBER(avr8_timer0_tick); |
103 | | TIMER_CALLBACK_MEMBER(avr8_timer1_tick); |
104 | | TIMER_CALLBACK_MEMBER(avr8_timer2_tick); |
105 | 79 | }; |
106 | 80 | |
107 | 81 | void craft_state::machine_start() |
108 | 82 | { |
109 | 83 | } |
110 | 84 | |
111 | | READ8_MEMBER(craft_state::avr8_read) |
| 85 | READ8_MEMBER(craft_state::port_r) |
112 | 86 | { |
113 | 87 | switch( offset ) |
114 | 88 | { |
115 | | case AVR8_REGIDX_EEDR: |
116 | | return m_regs[offset]; |
117 | | |
118 | | default: |
119 | | verboselog(machine(), 0, "AVR8: Unrecognized register read: %02x\n", offset ); |
| 89 | case 0x00: // Port A |
| 90 | case 0x01: // Port B |
| 91 | case 0x02: // Port C |
| 92 | case 0x03: // Port D |
| 93 | // Unhandled |
| 94 | return 0x00; |
120 | 95 | } |
121 | 96 | |
122 | 97 | return 0; |
123 | 98 | } |
124 | 99 | |
125 | | static UINT8 avr8_get_ddr(running_machine &machine, int reg) |
| 100 | WRITE8_MEMBER(craft_state::port_w) |
126 | 101 | { |
127 | | craft_state *state = machine.driver_data<craft_state>(); |
128 | | |
129 | | switch(reg) |
130 | | { |
131 | | case AVR8_REG_B: |
132 | | return AVR8_DDRB; |
133 | | |
134 | | case AVR8_REG_C: |
135 | | return AVR8_DDRC; |
136 | | |
137 | | case AVR8_REG_D: |
138 | | return AVR8_DDRD; |
139 | | |
140 | | default: |
141 | | verboselog(machine, 0, "avr8_get_ddr: Unsupported register retrieval: %c\n", avr8_reg_name[reg]); |
| 102 | switch( offset ) |
| 103 | { |
| 104 | case 0x00: // Port A |
| 105 | // Unhandled |
142 | 106 | break; |
143 | | } |
144 | 107 | |
145 | | return 0; |
146 | | } |
147 | | |
148 | | static void avr8_change_ddr(running_machine &machine, int reg, UINT8 data) |
149 | | { |
150 | | //craft_state *state = machine.driver_data<craft_state>(); |
151 | | |
152 | | UINT8 oldddr = avr8_get_ddr(machine, reg); |
153 | | UINT8 newddr = data; |
154 | | UINT8 changed = newddr ^ oldddr; |
155 | | // TODO: When AVR8 is converted to emu/machine, this should be factored out to 8 single-bit callbacks per port |
156 | | if(changed) |
157 | | { |
158 | | // TODO |
159 | | verboselog(machine, 0, "avr8_change_ddr: DDR%c lines %02x changed\n", avr8_reg_name[reg], changed); |
160 | | } |
161 | | } |
162 | | |
163 | | static void avr8_video_update(running_machine &machine) |
164 | | { |
165 | | craft_state *state = machine.driver_data<craft_state>(); |
166 | | |
167 | | UINT64 cycles = state->m_maincpu->get_elapsed_cycles(); |
168 | | UINT32 frame_cycles = (UINT32)(cycles - state->m_frame_start_cycle); |
169 | | |
170 | | if (state->m_last_cycles < frame_cycles) |
171 | | { |
172 | | for (UINT32 pixidx = state->m_last_cycles; pixidx < frame_cycles; pixidx++) |
| 108 | case 0x01: // Port B |
173 | 109 | { |
174 | | UINT8 value = AVR8_PORTC & 0x3f; |
175 | | if (state->m_spi_pending) |
| 110 | UINT8 old_port_b = m_port_b; |
| 111 | UINT8 pins = data; |
| 112 | UINT8 changed = pins ^ old_port_b; |
| 113 | if(pins & changed & 0x02) |
176 | 114 | { |
177 | | if (pixidx >= state->m_spi_start_cycle && pixidx < (state->m_spi_start_cycle + 16)) |
178 | | { |
179 | | UINT8 bitidx = 7 - ((pixidx - state->m_spi_start_cycle) >> 1); |
180 | | value = ((state->m_regs[AVR8_REGIDX_SPDR] & (1 << bitidx)) ? value : 0x3f); |
181 | | if (pixidx == (state->m_spi_start_cycle + 15)) |
182 | | { |
183 | | state->m_spi_pending = false; |
184 | | state->m_regs[AVR8_REGIDX_SPDR] = 0; |
185 | | } |
186 | | } |
| 115 | m_frame_start_cycle = m_maincpu->get_elapsed_cycles(); |
| 116 | video_update(); |
187 | 117 | } |
188 | | state->m_pixels[pixidx] = value; |
| 118 | if(changed & 0x08) |
| 119 | { |
| 120 | video_update(); |
| 121 | m_latched_color = (pins & 0x08) ? (m_port_c & 0x3f) : 0x3f; |
| 122 | } |
| 123 | m_port_b = data; |
| 124 | break; |
189 | 125 | } |
190 | | } |
191 | | else |
192 | | { |
193 | | memset(state->m_pixels + state->m_last_cycles, 0, sizeof(state->m_pixels) - state->m_last_cycles); |
194 | | memset(state->m_pixels, 0, frame_cycles); |
195 | | } |
196 | 126 | |
197 | | state->m_last_cycles = frame_cycles; |
198 | | } |
| 127 | case 0x02: // Port C |
| 128 | video_update(); |
| 129 | m_port_c = data; |
| 130 | m_latched_color = m_port_c; |
| 131 | break; |
199 | 132 | |
200 | | static void portb_write(avr8_device &device, UINT8 pins, UINT8 changed) |
201 | | { |
202 | | craft_state *state = device.machine().driver_data<craft_state>(); |
203 | | if(pins & changed & 0x02) |
204 | | { |
205 | | state->m_frame_start_cycle = device.get_elapsed_cycles(); |
206 | | } |
| 133 | case 0x03: // Port D |
| 134 | { |
| 135 | m_port_d = data; |
| 136 | UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2); |
| 137 | m_dac->write_unsigned8(audio_sample << 1); |
| 138 | break; |
| 139 | } |
| 140 | } |
207 | 141 | } |
208 | 142 | |
209 | | static void portc_write(avr8_device &device, UINT8 pins, UINT8 changed) |
| 143 | void craft_state::video_update() |
210 | 144 | { |
211 | | craft_state *state = device.machine().driver_data<craft_state>(); |
212 | | avr8_video_update(device.machine()); |
213 | | AVR8_PORTC = pins; |
214 | | } |
| 145 | UINT64 cycles = m_maincpu->get_elapsed_cycles(); |
| 146 | UINT32 frame_cycles = (UINT32)(cycles - m_frame_start_cycle); |
215 | 147 | |
216 | | static void portd_write(avr8_device &device, UINT8 pins, UINT8 changed) |
217 | | { |
218 | | craft_state *state = device.machine().driver_data<craft_state>(); |
219 | | UINT8 audio_sample = (pins & 0x02) | ((pins & 0xf4) >> 2); |
220 | | state->dac->write_unsigned8(audio_sample << 1); |
221 | | } |
222 | | |
223 | | /****************/ |
224 | | /* SPI Handling */ |
225 | | /****************/ |
226 | | |
227 | | static void avr8_enable_spi(running_machine &machine) |
228 | | { |
229 | | // TODO |
230 | | verboselog(machine, 0, "avr8_enable_spi: TODO\n"); |
231 | | } |
232 | | |
233 | | static void avr8_disable_spi(running_machine &machine) |
234 | | { |
235 | | // TODO |
236 | | verboselog(machine, 0, "avr8_disable_spi: TODO\n"); |
237 | | } |
238 | | |
239 | | static void avr8_spi_update_masterslave_select(running_machine &machine) |
240 | | { |
241 | | // TODO |
242 | | //craft_state *state = machine.driver_data<craft_state>(); |
243 | | //verboselog(machine, 0, "avr8_spi_update_masterslave_select: TODO; AVR is %s\n", AVR8_SPCR_MSTR ? "Master" : "Slave"); |
244 | | } |
245 | | |
246 | | static void avr8_spi_update_clock_polarity(running_machine &machine) |
247 | | { |
248 | | // TODO |
249 | | //craft_state *state = machine.driver_data<craft_state>(); |
250 | | //verboselog(machine, 0, "avr8_spi_update_clock_polarity: TODO; SCK is Active-%s\n", AVR8_SPCR_CPOL ? "Low" : "High"); |
251 | | } |
252 | | |
253 | | static void avr8_spi_update_clock_phase(running_machine &machine) |
254 | | { |
255 | | // TODO |
256 | | //craft_state *state = machine.driver_data<craft_state>(); |
257 | | //verboselog(machine, 0, "avr8_spi_update_clock_phase: TODO; Sampling edge is %s\n", AVR8_SPCR_CPHA ? "Trailing" : "Leading"); |
258 | | } |
259 | | |
260 | | static const UINT8 avr8_spi_clock_divisor[8] = { 4, 16, 64, 128, 2, 8, 32, 64 }; |
261 | | |
262 | | static void avr8_spi_update_clock_rate(running_machine &machine) |
263 | | { |
264 | | // TODO |
265 | | //craft_state *state = machine.driver_data<craft_state>(); |
266 | | //verboselog(machine, 0, "avr8_spi_update_clock_rate: TODO; New clock rate should be f/%d\n", avr8_spi_clock_divisor[AVR8_SPCR_SPR] / (AVR8_SPSR_SPR2X ? 2 : 1)); |
267 | | } |
268 | | |
269 | | static void avr8_change_spcr(running_machine &machine, UINT8 data) |
270 | | { |
271 | | craft_state *state = machine.driver_data<craft_state>(); |
272 | | |
273 | | UINT8 oldspcr = AVR8_SPCR; |
274 | | UINT8 newspcr = data; |
275 | | UINT8 changed = newspcr ^ oldspcr; |
276 | | UINT8 high_to_low = ~newspcr & oldspcr; |
277 | | UINT8 low_to_high = newspcr & ~oldspcr; |
278 | | |
279 | | AVR8_SPCR = data; |
280 | | |
281 | | if(changed & AVR8_SPCR_SPIE_MASK) |
| 148 | if (m_last_cycles < frame_cycles) |
282 | 149 | { |
283 | | // Check for SPI interrupt condition |
284 | | state->m_maincpu->update_interrupt(AVR8_INTIDX_SPI); |
| 150 | for (UINT32 pixidx = m_last_cycles; pixidx < frame_cycles && pixidx < PIXELS_PER_FRAME; pixidx++) |
| 151 | { |
| 152 | m_pixels[pixidx] = m_latched_color; |
| 153 | } |
285 | 154 | } |
286 | | |
287 | | if(low_to_high & AVR8_SPCR_SPE_MASK) |
| 155 | else |
288 | 156 | { |
289 | | avr8_enable_spi(machine); |
290 | | } |
291 | | else if(high_to_low & AVR8_SPCR_SPE_MASK) |
292 | | { |
293 | | avr8_disable_spi(machine); |
294 | | } |
295 | | |
296 | | if(changed & AVR8_SPCR_MSTR_MASK) |
297 | | { |
298 | | avr8_spi_update_masterslave_select(machine); |
299 | | } |
300 | | |
301 | | if(changed & AVR8_SPCR_CPOL_MASK) |
302 | | { |
303 | | avr8_spi_update_clock_polarity(machine); |
304 | | } |
305 | | |
306 | | if(changed & AVR8_SPCR_CPHA_MASK) |
307 | | { |
308 | | avr8_spi_update_clock_phase(machine); |
309 | | } |
310 | | |
311 | | if(changed & AVR8_SPCR_SPR_MASK) |
312 | | { |
313 | | avr8_spi_update_clock_rate(machine); |
314 | | } |
315 | | } |
316 | | |
317 | | static void avr8_change_spsr(running_machine &machine, UINT8 data) |
318 | | { |
319 | | craft_state *state = machine.driver_data<craft_state>(); |
320 | | |
321 | | UINT8 oldspsr = AVR8_SPSR; |
322 | | UINT8 newspsr = data; |
323 | | UINT8 changed = newspsr ^ oldspsr; |
324 | | //UINT8 high_to_low = ~newspsr & oldspsr; |
325 | | //UINT8 low_to_high = newspsr & ~oldspsr; |
326 | | |
327 | | AVR8_SPSR &= ~1; |
328 | | AVR8_SPSR |= data & 1; |
329 | | |
330 | | if(changed & AVR8_SPSR_SPR2X_MASK) |
331 | | { |
332 | | avr8_spi_update_clock_rate(machine); |
333 | | } |
334 | | } |
335 | | |
336 | | WRITE8_MEMBER(craft_state::avr8_write) |
337 | | { |
338 | | switch( offset ) |
339 | | { |
340 | | case AVR8_REGIDX_SPSR: |
341 | | avr8_change_spsr(machine(), data); |
342 | | break; |
343 | | |
344 | | case AVR8_REGIDX_SPCR: |
345 | | avr8_change_spcr(machine(), data); |
346 | | break; |
347 | | |
348 | | case AVR8_REGIDX_SPDR: |
| 157 | UINT32 end_clear = sizeof(m_pixels) - m_last_cycles; |
| 158 | UINT32 start_clear = frame_cycles; |
| 159 | end_clear = (end_clear > PIXELS_PER_FRAME) ? (PIXELS_PER_FRAME - m_last_cycles) : end_clear; |
| 160 | start_clear = (start_clear > PIXELS_PER_FRAME) ? PIXELS_PER_FRAME : start_clear; |
| 161 | if (m_last_cycles < PIXELS_PER_FRAME) |
349 | 162 | { |
350 | | avr8_video_update(machine()); |
351 | | m_regs[offset] = data; |
352 | | m_spi_pending = true; |
353 | | m_spi_start_cycle = m_maincpu->get_elapsed_cycles() - m_frame_start_cycle; |
354 | | break; |
| 163 | memset(m_pixels + m_last_cycles, 0, end_clear); |
355 | 164 | } |
| 165 | if (start_clear < PIXELS_PER_FRAME) |
| 166 | { |
| 167 | memset(m_pixels, 0, start_clear); |
| 168 | } |
| 169 | } |
356 | 170 | |
357 | | case AVR8_REGIDX_EECR: |
358 | | if (data & AVR8_EECR_EERE) |
359 | | { |
360 | | UINT16 addr = (m_regs[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8; |
361 | | addr |= m_regs[AVR8_REGIDX_EEARL]; |
362 | | m_regs[AVR8_REGIDX_EEDR] = m_eeprom[addr]; |
363 | | } |
364 | | break; |
365 | | |
366 | | case AVR8_REGIDX_EEARL: |
367 | | case AVR8_REGIDX_EEARH: |
368 | | m_regs[offset] = data; |
369 | | break; |
370 | | |
371 | | case AVR8_REGIDX_DDRD: |
372 | | avr8_change_ddr(machine(), AVR8_REG_D, data); |
373 | | break; |
374 | | |
375 | | case AVR8_REGIDX_DDRC: |
376 | | avr8_change_ddr(machine(), AVR8_REG_C, data); |
377 | | break; |
378 | | |
379 | | case AVR8_REGIDX_DDRB: |
380 | | avr8_change_ddr(machine(), AVR8_REG_B, data); |
381 | | break; |
382 | | |
383 | | default: |
384 | | verboselog(machine(), 0, "AVR8: Unrecognized register write: %02x = %02x\n", offset, data ); |
385 | | } |
| 171 | m_last_cycles = frame_cycles; |
386 | 172 | } |
387 | 173 | |
388 | 174 | /****************************************************\ |
r18880 | r18881 | |
393 | 179 | AM_RANGE(0x0000, 0x1fff) AM_ROM |
394 | 180 | ADDRESS_MAP_END |
395 | 181 | |
396 | | static ADDRESS_MAP_START( craft_io_map, AS_IO, 8, craft_state ) |
397 | | AM_RANGE(0x0000, 0x00ff) AM_READWRITE(avr8_read, avr8_write) |
| 182 | static ADDRESS_MAP_START( craft_data_map, AS_DATA, 8, craft_state ) |
398 | 183 | AM_RANGE(0x0100, 0x04ff) AM_RAM |
399 | 184 | ADDRESS_MAP_END |
400 | 185 | |
| 186 | static ADDRESS_MAP_START( craft_io_map, AS_IO, 8, craft_state ) |
| 187 | AM_RANGE(0x00, 0x03) AM_READWRITE( port_r, port_w ) |
| 188 | ADDRESS_MAP_END |
| 189 | |
401 | 190 | /****************************************************\ |
402 | 191 | * Input ports * |
403 | 192 | \****************************************************/ |
r18880 | r18881 | |
438 | 227 | |
439 | 228 | void craft_state::machine_reset() |
440 | 229 | { |
441 | | craft_state *state = machine().driver_data<craft_state>(); |
| 230 | m_dac = machine().device<dac_device>("dac"); |
442 | 231 | |
443 | | state->dac = machine().device<dac_device>("dac"); |
| 232 | m_dac->write_unsigned8(0x00); |
444 | 233 | |
445 | | state->dac->write_unsigned8(0x00); |
446 | | |
447 | | state->m_eeprom = memregion("eeprom")->base(); |
448 | | |
449 | | state->m_frame_start_cycle = 0; |
450 | | state->m_last_cycles = 0; |
451 | | |
452 | | state->m_spi_pending = false; |
453 | | |
454 | | state->m_spi_start_cycle = 0; |
| 234 | m_frame_start_cycle = 0; |
| 235 | m_last_cycles = 0; |
455 | 236 | } |
456 | 237 | |
457 | 238 | const avr8_config atmega88_config = |
458 | 239 | { |
459 | | &portb_write, // Video timing signals |
460 | | &portc_write, // Video color signals |
461 | | &portd_write // Audio DAC |
| 240 | "eeprom" |
462 | 241 | }; |
463 | 242 | |
464 | 243 | static MACHINE_CONFIG_START( craft, craft_state ) |
r18880 | r18881 | |
467 | 246 | MCFG_CPU_ADD("maincpu", ATMEGA88, MASTER_CLOCK) |
468 | 247 | MCFG_CPU_AVR8_CONFIG(atmega88_config) |
469 | 248 | MCFG_CPU_PROGRAM_MAP(craft_prg_map) |
| 249 | MCFG_CPU_DATA_MAP(craft_data_map) |
470 | 250 | MCFG_CPU_IO_MAP(craft_io_map) |
471 | 251 | |
472 | 252 | /* video hardware */ |
r18880 | r18881 | |
492 | 272 | ROM_END |
493 | 273 | |
494 | 274 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */ |
495 | | CONS(2008, craft, 0, 0, craft, craft, craft_state, craft, "Linus Akesson", "Craft", GAME_IMPERFECT_GRAPHICS) |
| 275 | CONS(2008, craft, 0, 0, craft, craft, craft_state, craft, "Linus Akesson", "Craft", GAME_NOT_WORKING) |