1 | #include <avr/io.h>
|
2 | #include <stdio.h>
|
3 | #include <avr/interrupt.h>
|
4 | #include <util/delay.h>
|
5 |
|
6 | /* USI port and pin definitions.
|
7 | */
|
8 | #define USI_OUT_REG PORTB //!< USI port output register.
|
9 | #define USI_IN_REG PINB //!< USI port input register.
|
10 | #define USI_DIR_REG DDRB //!< USI port direction register.
|
11 | #define USI_CLOCK_PIN PB7 //!< USI clock I/O pin.
|
12 | #define USI_DATAIN_PIN PB5 //!< USI data input pin.
|
13 | #define USI_DATAOUT_PIN PB6 //!< USI data output pin.
|
14 |
|
15 | /* Speed configuration:
|
16 | * Bits per second = CPUSPEED / PRESCALER / (COMPAREVALUE+1) / 2.
|
17 | * Maximum = CPUSPEED / 64.
|
18 | */
|
19 | #define TC0_PRESCALER_VALUE 64 //!< Must be 1, 8, 64, 256 or 1024.
|
20 | #define TC0_COMPARE_VALUE 4 //!< Must be 0 to 255. Minimum 31 with prescaler CLK/1.
|
21 |
|
22 | #define SPI_MODE_RISING 0 //!< Sample data on _rising_ edge, setup on trailing _falling_ edge.
|
23 | #define SPI_MODE_FALLING 1 //!< Sample data on _falling_ edge, setup on trailing _rising_ edge.
|
24 |
|
25 | /* Prescaler value converted to bit settings.
|
26 | */
|
27 | #if TC0_PRESCALER_VALUE == 1
|
28 | #define TC0_PS_SETTING (1<<CS00)
|
29 | #elif TC0_PRESCALER_VALUE == 8
|
30 | #define TC0_PS_SETTING (1<<CS01)
|
31 | #elif TC0_PRESCALER_VALUE == 64
|
32 | #define TC0_PS_SETTING (1<<CS01)|(1<<CS00)
|
33 | #elif TC0_PRESCALER_VALUE == 256
|
34 | #define TC0_PS_SETTING (1<<CS02)
|
35 | #elif TC0_PRESCALER_VALUE == 1024
|
36 | #define TC0_PS_SETTING (1<<CS02)|(1<<CS00)
|
37 | #else
|
38 | #error Invalid T/C0 prescaler setting.
|
39 | #endif
|
40 |
|
41 | //unsigned char storedUSIDR;
|
42 |
|
43 | struct usidriverStatus_t {
|
44 | unsigned char masterMode : 1; //!< True if in master mode.
|
45 | unsigned char transferComplete : 1; //!< True when transfer completed.
|
46 | unsigned char writeCollision : 1; //!< True if put attempted during transfer.
|
47 | };
|
48 |
|
49 | /*! \brief Initialize USI as SPI master.
|
50 | *
|
51 | * This function sets up all pin directions and module configurations.
|
52 | * Use this function initially or when changing from slave to master mode.
|
53 | * Note that the stored USIDR value is cleared.
|
54 | *
|
55 | * \param spi_mode Required SPI mode, must be 0 or 1.
|
56 | */
|
57 | void spiX_initmaster( char spi_mode );
|
58 |
|
59 | /*! \brief Initialize USI as SPI slave.
|
60 | *
|
61 | * This function sets up all pin directions and module configurations.
|
62 | * Use this function initially or when changing from master to slave mode.
|
63 | * Note that the stored USIDR value is cleared.
|
64 | *
|
65 | * \param spi_mode Required SPI mode, must be 0 or 1.
|
66 | */
|
67 | void spiX_initslave( char spi_mode );
|
68 |
|
69 |
|
70 | /*! \brief Put one byte on bus.
|
71 | *
|
72 | * Use this function like you would write to the SPDR register in the native SPI module.
|
73 | * Calling this function in master mode starts a transfer, while in slave mode, a
|
74 | * byte will be prepared for the next transfer initiated by the master device.
|
75 | * If a transfer is in progress, this function will set the write collision flag
|
76 | * and return without altering the data registers.
|
77 | *
|
78 | * \returns 0 if a write collision occurred, 1 otherwise.
|
79 | */
|
80 | char spiX_put( unsigned char val );
|
81 |
|
82 | /*! \brief Get one byte from bus.
|
83 | *
|
84 | * This function only returns the previous stored USIDR value.
|
85 | * The transfer complete flag is not checked. Use this function
|
86 | * like you would read from the SPDR register in the native SPI module.
|
87 | */
|
88 | unsigned char spiX_get();
|
89 |
|
90 | /*! \brief Wait for transfer to complete.
|
91 | *
|
92 | * This function waits until the transfer complete flag is set.
|
93 | * Use this function like you would wait for the native SPI interrupt flag.
|
94 | */
|
95 | void spiX_wait();
|