firmware  v0.1.2
Chromation Spectrometer Dev-Kit
SpiSlave.h
Go to the documentation of this file.
1 #ifndef _SPISLAVE_H
2 #define _SPISLAVE_H
3 #include <stdint.h>
4 #include <stdbool.h>
5 #include "ReadWriteBits.h"
6 #include "Spi.h"
7 
8 #ifdef USE_FAKES
9 #include "Spi_faked.h"
10 #include "SpiSlave_faked.h" // declare fakes
11 #endif
12 
13 // ---Private---
14 inline void _SignalDataReady(void)
15 {
27  ClearBit(Spi_PortOutput, Spi_DataReady);
28  // ---Expected Assembly---
29  // cbi 0x05, 1 ; 5
30 }
31 inline void _SignalDataNotReady(void)
32 {
34  SetBit(Spi_PortOutput, Spi_DataReady);
35  // ---Expected Assembly---
36  // sbi 0x05, 1 ; 5
37 }
38 
39 // ---API (Go to the Doxygen documentation of this file)---
48 inline void DisableSpiInterrupt(void)
49 {
51 
62  // Disable the "transfer complete" interrupt
63  ClearBit(Spi_SPCR, Spi_InterruptEnable);
64  // ---Expected Assembly---
65  // in r24, 0x2c ; 44
66  // andi r24, 0x7F ; 127
67  // out 0x2c, r24 ; 44
68  // This is three instructions because SPCR is outside the
69  // address range for using `cbi`.
70 }
71 
72 // ---API functions that call fakes when testing---
73 //
74 #ifdef USE_FAKES
75 #define ClearSpiInterruptFlag ClearSpiInterruptFlag_fake
76 #endif
77 inline void EnableSpiInterrupt(void)
78 {
94  // Global interrupt disable
95  cli(); // cli
96  // Clear SPI interrupt flag (SPIF) before enabling interrupt
98  // Enable the "transfer complete" interrupt
99  SetBit(Spi_SPCR, Spi_InterruptEnable);
100  // ---Expected Assembly---
101  // in r24, 0x2c;
102  // ori r24, 0x80;
103  // out 0x2c, r24
104  // This is three instructions because SPCR is outside the
105  // address range for using `sbi`.
106  //
107  // Global interrupt enable
108  sei(); // sei
109 }
110 #ifdef USE_FAKES
111 #undef ClearSpiInterruptFlag
112 #endif
113 
114 #ifdef USE_FAKES
115 // Call fakes by renaming faked calls with _fake suffix.
116 #define EnableSpiInterrupt EnableSpiInterrupt_fake
117 #endif
118 inline void SpiSlaveInit(void)
119 {
128  // DataReady pin idle high
129  SetBit(Spi_PortOutput, Spi_DataReady); // sbi 0x05, 1
130  // Set DataReady as an output pin
131  SetBit(Spi_PortDirection, Spi_DataReady); // sbi 0x04, 1
132 
133  // Set Miso as an an output pin
134  SetBit(Spi_PortDirection, Spi_Miso); // sbi 0x04, 4
135 
137  // Enable interrupts for robust SPI communication
139 }
140 #ifdef USE_FAKES
141 // Remove `_fake` suffix from function names.
142 #undef EnableSpiInterrupt
143 #endif
144 
145 #ifdef USE_FAKES
146 #define _SpiTransferIsDone _SpiTransferIsDone_fake
147 #define _SignalDataReady _SignalDataReady_fake
148 #define DisableSpiInterrupt DisableSpiInterrupt_fake
149 #endif
150 inline void SpiSlaveTxByte(uint8_t input_byte)
151 {
153 
162  *Spi_SPDR = input_byte;
163  // ---Expected Assembly---
164  // out 0x2e, r23 ; 46
166  // ---Expected Assembly---
167  // in r24, 0x2c ; 44
168  // andi r24, 0x7F ; 127
169  // out 0x2c, r24 ; 44
171  // ---Expected Assembly---
172  // cbi 0x05, 1 ; 5
173  // Wait for a byte from the SPI Master.
174  while ( !_SpiTransferIsDone() ); // Check SPI interrupt flag
175  // ---Expected Assembly---
176  // Total number of cycles: 5
177  // in r0, 0x2d
178  // sbrs r0, 7
179  // rjmp .-6
181  // Re-enable interrupt and reset (clear) SPI interrupt flag
183  // ---Expected Assembly---
184  // Total number of cycles: 7
185  // cli
186  // in r24, 0x2d
187  // in r24, 0x2e
188  // in r24, 0x2c
189  // ori r24, 0x80
190  // out 0x2c, r24
191  // sei
192 }
193 #ifdef USE_FAKES
194 #undef _SpiTransferIsDone
195 #undef _SignalDataReady
196 #undef DisableSpiInterrupt
197 #endif
198 
199 #ifdef USE_FAKES
200 #define SpiSlaveTxByte SpiSlaveTxByte_fake
201 #endif
202 inline void SpiSlaveTx(uint8_t const *input_buffer, uint16_t nbytes)
203 {
207  uint16_t byte_index;
208  for (byte_index = 0; byte_index < nbytes; byte_index++)
209  {
210  SpiSlaveTxByte(input_buffer[byte_index]);
211  }
212 }
213 #ifdef USE_FAKES
214 #undef SpiSlaveTxByte
215 #endif
216 
217 #endif // _SPISLAVE_H
spi_ptr Spi_SPCR
SPI Control Register.
spi_ptr Spi_SPDR
SPI Data Register.
void _SignalDataNotReady(void)
Definition: SpiSlave.h:31
void EnableSpiInterrupt(void)
Definition: SpiSlave.h:77
void DisableSpiInterrupt(void)
Definition: SpiSlave.h:48
void SpiSlaveInit(void)
Definition: SpiSlave.h:118
void SpiSlaveTx(uint8_t const *input_buffer, uint16_t nbytes)
Definition: SpiSlave.h:202
void SpiSlaveTxByte(uint8_t input_byte)
Definition: SpiSlave.h:150
void _SignalDataReady(void)
Definition: SpiSlave.h:14
Spi.h declares SPI hardware types and variables common to the SPI Master and SPI Slave.
void _EnableSpiModule(void)
Definition: Spi.h:75
spi_reg Spi_PortOutput
Atmel PORT.
spi_reg Spi_PortDirection
Atmel DDR.
bool _SpiTransferIsDone(void)
Definition: Spi.h:88
void ClearSpiInterruptFlag(void)
Definition: Spi.h:116