spi_via_usi_driver.h


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();