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
2526static 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 )) {
@@ -48,14 +49,22 @@ static uint8_t avr_spi_read(struct avr_t * avr, avr_io_addr_t addr, void * param
4849
4950static void avr_spi_write (struct avr_t * avr , avr_io_addr_t addr , uint8_t v , void * param )
5051{
52+
53+ static const uint8_t _avr_spi_clkdiv [4 ] = {4 ,16 ,64 ,128 };
5154 avr_spi_t * p = (avr_spi_t * )param ;
5255
5356 if (addr == p -> r_spdr ) {
5457 /* Clear the SPIF bit. See ATmega164/324/644 manual, Section 18.5.2. */
5558 avr_regbit_clear (avr , p -> spi .raised );
5659
5760 avr_core_watch_write (avr , addr , v );
58- avr_cycle_timer_register_usec (avr , 100 , avr_spi_raise , p ); // should be speed dependent
61+ uint16_t clock_shift = _avr_spi_clkdiv [avr -> data [p -> r_spcr ]& 0b11 ];
62+ // If master && 2X, double rate (half divisor)
63+ if (avr_regbit_get (avr , p -> mstr ) && avr_regbit_get (avr , p -> spr [2 ]))
64+ clock_shift >>=1 ;
65+
66+ // We can wait directly in clockshifts, it is a divisor, so /4 means 4 avr cycles to clock out one bit.
67+ avr_cycle_timer_register (avr , clock_shift <<3 , avr_spi_raise , p ); // *8 since 8 clocks to a byte.
5968 }
6069}
6170
@@ -72,7 +81,7 @@ static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * par
7281 p -> input_data_register = value ;
7382 avr_raise_interrupt (avr , & p -> spi );
7483
75- // if in slave mode,
84+ // if in slave mode,
7685 // 'output' the byte only when we received one...
7786 if (!avr_regbit_get (avr , p -> mstr )) {
7887 avr_raise_irq (p -> io .irq + SPI_IRQ_OUTPUT , avr -> data [p -> r_spdr ]);
@@ -108,4 +117,3 @@ void avr_spi_init(avr_t * avr, avr_spi_t * p)
108117 avr_register_io_write (avr , p -> r_spdr , avr_spi_write , p );
109118 avr_register_io_read (avr , p -> r_spdr , avr_spi_read , p );
110119}
111-
0 commit comments