From dab360416efd7db06d9c7c63bda94db27f9516a1 Mon Sep 17 00:00:00 2001 From: vintagepc <53943260+vintagepc@users.noreply.github.com> Date: Mon, 3 Aug 2020 19:14:54 -0400 Subject: [PATCH] Clock out SPI data according to SPCR/SPSR --- simavr/sim/avr_spi.c | 14 ++++++++++---- simavr/sim/avr_spi.h | 7 +++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/simavr/sim/avr_spi.c b/simavr/sim/avr_spi.c index e97d824..da96f29 100644 --- a/simavr/sim/avr_spi.c +++ b/simavr/sim/avr_spi.c @@ -2,6 +2,7 @@ avr_spi.c Copyright 2008, 2009 Michel Pollet + Modified 2020 by VintagePC to support clock divisors This file is part of simavr. @@ -25,7 +26,7 @@ static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_spi_t * p = (avr_spi_t *)param; - + if (avr_regbit_get(avr, p->spe)) { // in master mode, any byte is sent as it comes.. if (avr_regbit_get(avr, p->mstr)) { @@ -55,7 +56,13 @@ static void avr_spi_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, voi avr_regbit_clear(avr, p->spi.raised); avr_core_watch_write(avr, addr, v); - avr_cycle_timer_register_usec(avr, 100, avr_spi_raise, p); // should be speed dependent + uint16_t uiClkShift = _avr_spi_clkdiv[avr->data[p->r_spcr]&0b11]; + // If master && 2X, double rate (half divisor) + if (avr_regbit_get(avr, p->mstr) && avr_regbit_get(avr, p->spr[2])) + uiClkShift>>=1; + + // We can wait directly in clockshifts, it is a divisor, so /4 means 4 avr cycles to clock out one bit. + avr_cycle_timer_register(avr, uiClkShift<<3, avr_spi_raise, p); // *8 since 8 clocks to a byte. } } @@ -72,7 +79,7 @@ static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * par p->input_data_register = value; avr_raise_interrupt(avr, &p->spi); - // if in slave mode, + // if in slave mode, // 'output' the byte only when we received one... if (!avr_regbit_get(avr, p->mstr)) { avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]); @@ -108,4 +115,3 @@ void avr_spi_init(avr_t * avr, avr_spi_t * p) avr_register_io_write(avr, p->r_spdr, avr_spi_write, p); avr_register_io_read(avr, p->r_spdr, avr_spi_read, p); } - diff --git a/simavr/sim/avr_spi.h b/simavr/sim/avr_spi.h index 23ff78f..933d405 100644 --- a/simavr/sim/avr_spi.h +++ b/simavr/sim/avr_spi.h @@ -2,6 +2,7 @@ avr_spi.h Copyright 2008, 2009 Michel Pollet + Modified 2020 by VintagePC to support clock divisors This file is part of simavr. @@ -45,11 +46,11 @@ typedef struct avr_spi_t { avr_io_addr_t r_spdr; // data register avr_io_addr_t r_spcr; // control register avr_io_addr_t r_spsr; // status register - + avr_regbit_t spe; // spi enable avr_regbit_t mstr; // master/slave avr_regbit_t spr[4]; // clock divider - + avr_int_vector_t spi; // spi interrupt uint8_t input_data_register; @@ -103,4 +104,6 @@ void avr_spi_init(avr_t * avr, avr_spi_t * port); }; #endif +static const uint8_t _avr_spi_clkdiv[4] = {4,16,64,128}; + #endif /*__AVR_SPI_H__*/ -- 2.39.5