1cb67e98ef61703b18edd158caddc08f69f8a596
[goodfet] / firmware / apps / avr / avr.c
1 /*! \file avr.c
2   \author Travis Goodspeed
3   \brief AVR SPI Programmer
4 */
5
6 #include "platform.h"
7 #include "command.h"
8
9 #include <signal.h>
10 #include <io.h>
11 #include <iomacros.h>
12
13 #include "avr.h"
14 #include "glitch.h"
15
16 //! Setup the AVR pins.
17 void avrsetup(){
18   spisetup();
19 }
20
21 //! Initialized an attached AVR.
22 void avrconnect(){
23   //set I/O pins
24   avrsetup();
25   
26   //Pulse !RST (SS) at least twice while CLK is low.
27   CLRCLK;
28   CLRSS;
29
30   SETSS;
31   CLRCLK;
32   //delay(5);
33   CLRSS;
34   //delay(5);
35   
36   //Enable programming
37   avr_prgen();
38 }
39
40 //! Read and write an SPI byte with delays.
41 u8 avrtrans8(u8 byte){
42   register u16 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     delay(2);
55     SETCLK;
56   
57     /* read MISO on trailing edge */
58     byte |= READMISO;
59     delay(2);
60     CLRCLK;
61   }
62   
63   return byte;
64 }
65
66 //! Perform a 4-byte exchange.
67 u8 avrexchange(u8 a, u8 b, u8 c, u8 d){
68   avrtrans8(a);
69   avrtrans8(b);
70   if(avrtrans8(c)!=b){
71     //debugstr("AVR sync error, b not returned as c.");
72     //Reconnect here?
73   }
74   return avrtrans8(d);
75 }
76
77 //! Enable AVR programming mode.
78 void avr_prgen(){
79   avrexchange(0xAC, 0x53, 0, 0);
80 }
81
82 //! Is the AVR ready or busy?
83 u8 avr_isready(){
84   return avrexchange(0xF0, 0, 0, 0);
85 }
86
87 //! Read AVR device code.
88 u8 avr_sig(u8 i){
89   return avrexchange(0x30, //Read signature byte
90               0x00,
91               i&0x03,      //sig adr
92               0x00         //don't care.
93               );
94 }
95
96 //! Erase an AVR device
97 void avr_erase(){
98   avrexchange(0xAC, 0x80, 0, 0);
99 }
100
101 //! Read lock bits.
102 u8 avr_lockbits(){
103   return avrexchange(0x58, 0, 0, 0);
104 }
105 //! Write lock bits.
106 void avr_setlock(u8 bits){
107   avrexchange(0xAC,0xE0,0x00,
108               bits);
109 }
110
111 //! Read a byte of EEPROM.
112 u8 avr_peekeeprom(u16 adr){
113   return avrexchange(0xA0, adr>>8, adr&0xFF, 0);
114 }
115 //! Read a byte of EEPROM.
116 u8 avr_pokeeeprom(u16 adr, u8 val){
117   return avrexchange(0xC0, adr>>8, adr&0xFF, val);
118 }
119
120 //! Read a byte of Flash
121 u8 avr_peekflash(u16 adr){
122   u16 a=adr>>1;
123   if(adr&1) //high byte
124     return avrexchange(0x28,a>>8,a&0xff,0);
125   else      //low byte
126     return avrexchange(0x20,a>>8,a&0xff,0);
127 }
128
129
130 //! Handles an AVR command.
131 void avrhandle(unsigned char app,
132                unsigned char verb,
133                unsigned long len){
134   unsigned long i;
135   unsigned int at;
136   static u8 connected=0;
137   
138   /*
139   if(!avr_isready() && connected)
140     debugstr("AVR is not yet ready.");
141   */
142   
143   switch(verb){
144   case READ:
145   case WRITE:
146     for(i=0;i<len;i++)
147       cmddata[i]=avrtrans8(cmddata[i]);
148     txdata(app,verb,len);
149     break;
150   case SETUP:
151     avrsetup();
152     txdata(app,verb,0);
153     break;
154   case START://returns device code
155     avrconnect();
156     //no break here
157   case AVR_PEEKSIG:
158     for(i=0;i<4;i++)
159       cmddata[i]=avr_sig(i);
160     txdata(app,verb,4);
161     break;
162   case AVR_ERASE:
163     avr_erase();
164     txdata(app,verb,0);
165     break;
166   case AVR_PEEKLOCK:
167     cmddata[0]=avr_lockbits();
168     txdata(app,verb,1);
169     break;
170   case AVR_POKELOCK:
171     avr_setlock(cmddata[0]);
172     txdata(app,verb,0);
173     break;
174   case AVR_POKEEEPROM:
175     avr_pokeeeprom(cmddataword[0], cmddata[2]);
176     //no break here.
177   case AVR_PEEKEEPROM:
178     cmddata[0]=avr_peekeeprom(cmddataword[0]);
179     txdata(app,verb,1);
180     break;
181   case PEEK:
182     //cmddata[0]=avr_peekflash(cmddataword[0]);
183     //txdata(app,verb,1);
184     at=cmddataword[0];
185     
186     //Fetch large blocks for bulk fetches,
187     //small blocks for individual peeks.
188     if(len>2){
189       len=(cmddataword[1]);//always even.
190     }else{
191       len=1;
192     }
193     txhead(app,verb,len);
194     for(i=0;i<len;i++){
195       serial_tx(avr_peekflash(at++));
196     }
197     break;
198   case POKE:
199   default:
200     debugstr("Verb unimplemented in AVR application.");
201     txdata(app,NOK,0);
202     break;
203   }
204 }
205