e00d2aa2376e22e3380406a8ef817aa7b63a9fbf
[goodfet] / firmware / apps / spi / spi.c
1 //GoodFET SPI Application
2 //Handles basic I/O
3
4 //Higher level left to client application.
5
6 #include "platform.h"
7 #include "command.h"
8
9 #include <signal.h>
10 #include <io.h>
11 #include <iomacros.h>
12
13
14 //Pins and I/O
15 #define SS   BIT0
16 #define MOSI BIT1
17 #define MISO BIT2
18 #define SCK  BIT3
19
20 //This could be more accurate.
21 //Does it ever need to be?
22 #define SPISPEED 0
23 #define SPIDELAY(x) delay(x)
24
25 #define SETMOSI P5OUT|=MOSI
26 #define CLRMOSI P5OUT&=~MOSI
27 #define SETCLK P5OUT|=SCK
28 #define CLRCLK P5OUT&=~SCK
29 #define READMISO (P5IN&MISO?1:0)
30
31
32
33 //! Set up the pins for SPI mode.
34 void spisetup(){
35   P5OUT|=SS;
36   P5DIR|=MOSI+SCK+SS;
37   P5DIR&=~MISO;
38 }
39
40 //! Read and write an SPI bit.
41 unsigned char spitrans8(unsigned char byte){
42   unsigned int bit;
43   //This function came from the SPI Wikipedia article.
44   //Minor alterations.
45   
46   for (bit = 0; bit < 8; bit++) {
47     /* write MOSI on trailing edge of previous clock */
48     if (byte & 0x80)
49       SETMOSI;
50     else
51       CLRMOSI;
52     byte <<= 1;
53  
54     /* half a clock cycle before leading/rising edge */
55     SPIDELAY(SPISPEED/2);
56     SETCLK;
57  
58     /* half a clock cycle before trailing/falling edge */
59     SPIDELAY(SPISPEED/2);
60  
61     /* read MISO on trailing edge */
62     byte |= READMISO;
63     CLRCLK;
64   }
65   
66   return byte;
67 }
68
69 //! Enable SPI writing
70 void spiflash_wrten(){
71   P5OUT&=~SS; //Drop !SS to begin transaction.
72   spitrans8(0x04);//Write Disable
73   P5OUT|=SS;  //Raise !SS to end transaction.
74   P5OUT&=~SS; //Drop !SS to begin transaction.
75   spitrans8(0x06);//Write Enable
76   P5OUT|=SS;  //Raise !SS to end transaction.
77 }
78
79 //! Grab the SPI flash status byte.
80 unsigned char spiflash_status(){
81   unsigned char c;
82   P5OUT|=SS;  //Raise !SS to end transaction.
83   P5OUT&=~SS; //Drop !SS to begin transaction.
84   spitrans8(0x05);//GET STATUS
85   c=spitrans8(0xFF);
86   P5OUT|=SS;  //Raise !SS to end transaction.
87   return c;
88 }
89 //! Grab the SPI flash status byte.
90 void spiflash_setstatus(unsigned char c){
91   P5OUT&=~SS; //Drop !SS to begin transaction.
92   spitrans8(0x01);//SET STATUS
93   spitrans8(c);
94   P5OUT|=SS;  //Raise !SS to end transaction.
95   return c;
96 }
97
98 //! Handles a monitor command.
99 void spihandle(unsigned char app,
100                unsigned char verb,
101                unsigned char len){
102   unsigned char i;
103   
104   
105   //Raise !SS to end transaction, just in case we forgot.
106   P5OUT|=SS;  
107   
108   switch(verb){
109     //PEEK and POKE might come later.
110   case READ:
111   case WRITE:
112     P5OUT&=~SS; //Drop !SS to begin transaction.
113     for(i=0;i<len;i++)
114       cmddata[i]=spitrans8(cmddata[i]);
115     P5OUT|=SS;  //Raise !SS to end transaction.
116     txdata(app,verb,len);
117     break;
118   case SPI_JEDEC://Grab 3-byte JEDEC ID.
119     P5OUT&=~SS; //Drop !SS to begin transaction.
120     spitrans8(0x9f);
121     len=3;
122     for(i=0;i<len;i++)
123       cmddata[i]=spitrans8(cmddata[i]);
124     txdata(app,verb,len);
125     P5OUT|=SS;  //Raise !SS to end transaction.
126     break;
127   case PEEK://Grab 128 bytes from an SPI Flash ROM
128     P5OUT&=~SS; //Drop !SS to begin transaction.
129     spitrans8(0x03);//Flash Read Command
130     len=3;//write 3 byte pointer
131     for(i=0;i<len;i++)
132       spitrans8(cmddata[i]);
133     len=0x80;//128 byte chunk
134     for(i=0;i<len;i++)
135       cmddata[i]=spitrans8(0);
136     P5OUT|=SS;  //Raise !SS to end transaction.
137     txdata(app,verb,len);
138     break;
139   case POKE://Poke up bytes from an SPI Flash ROM.
140     spiflash_setstatus(0x02);
141     spiflash_wrten();
142     
143     P5OUT&=~SS; //Drop !SS to begin transaction.
144     spitrans8(0x02); //Poke command.
145     
146     //First three bytes are address, then data.
147     for(i=0;i<len;i++)
148       spitrans8(cmddata[i]);
149     P5OUT|=SS;  //Raise !SS to end transaction.
150     while(spiflash_status()&0x01);//while busy
151     txdata(app,verb,len);
152     break;
153   case SPI_ERASE://Erase the SPI Flash ROM.
154     spiflash_wrten();
155     P5OUT&=~SS; //Drop !SS to begin transaction.
156     spitrans8(0xC7);//Chip Erase
157     P5OUT|=SS;  //Raise !SS to end transaction.
158     txdata(app,verb,0);
159     break;
160   case SETUP:
161     spisetup();
162     txdata(app,verb,0);
163     break;
164   }
165   
166 }