Skip to content

Commit dab3604

Browse files
committed
Clock out SPI data according to SPCR/SPSR
1 parent 73ae11a commit dab3604

File tree

2 files changed

+15
-6
lines changed

2 files changed

+15
-6
lines changed

simavr/sim/avr_spi.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
avr_spi.c
33
44
Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5+
Modified 2020 by VintagePC <https://github.com/vintagepc> to support clock divisors
56
67
This file is part of simavr.
78
@@ -25,7 +26,7 @@
2526
static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
2627
{
2728
avr_spi_t * p = (avr_spi_t *)param;
28-
29+
2930
if (avr_regbit_get(avr, p->spe)) {
3031
// in master mode, any byte is sent as it comes..
3132
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
5556
avr_regbit_clear(avr, p->spi.raised);
5657

5758
avr_core_watch_write(avr, addr, v);
58-
avr_cycle_timer_register_usec(avr, 100, avr_spi_raise, p); // should be speed dependent
59+
uint16_t uiClkShift = _avr_spi_clkdiv[avr->data[p->r_spcr]&0b11];
60+
// If master && 2X, double rate (half divisor)
61+
if (avr_regbit_get(avr, p->mstr) && avr_regbit_get(avr, p->spr[2]))
62+
uiClkShift>>=1;
63+
64+
// We can wait directly in clockshifts, it is a divisor, so /4 means 4 avr cycles to clock out one bit.
65+
avr_cycle_timer_register(avr, uiClkShift<<3, avr_spi_raise, p); // *8 since 8 clocks to a byte.
5966
}
6067
}
6168

@@ -72,7 +79,7 @@ static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * par
7279
p->input_data_register = value;
7380
avr_raise_interrupt(avr, &p->spi);
7481

75-
// if in slave mode,
82+
// if in slave mode,
7683
// 'output' the byte only when we received one...
7784
if (!avr_regbit_get(avr, p->mstr)) {
7885
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)
108115
avr_register_io_write(avr, p->r_spdr, avr_spi_write, p);
109116
avr_register_io_read(avr, p->r_spdr, avr_spi_read, p);
110117
}
111-

simavr/sim/avr_spi.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
avr_spi.h
33
44
Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5+
Modified 2020 by VintagePC <https://github.com/vintagepc> to support clock divisors
56
67
This file is part of simavr.
78
@@ -45,11 +46,11 @@ typedef struct avr_spi_t {
4546
avr_io_addr_t r_spdr; // data register
4647
avr_io_addr_t r_spcr; // control register
4748
avr_io_addr_t r_spsr; // status register
48-
49+
4950
avr_regbit_t spe; // spi enable
5051
avr_regbit_t mstr; // master/slave
5152
avr_regbit_t spr[4]; // clock divider
52-
53+
5354
avr_int_vector_t spi; // spi interrupt
5455

5556
uint8_t input_data_register;
@@ -103,4 +104,6 @@ void avr_spi_init(avr_t * avr, avr_spi_t * port);
103104
};
104105
#endif
105106

107+
static const uint8_t _avr_spi_clkdiv[4] = {4,16,64,128};
108+
106109
#endif /*__AVR_SPI_H__*/

0 commit comments

Comments
 (0)