Fixed GoodFET22. GSEL must be high or DAC0 must be high and DAC1 low.
[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:
155     avrconnect();
156     txdata(app,verb,0);
157     break;//Used to fall through here.
158   case AVR_PEEKSIG:
159     for(i=0;i<4;i++)
160       cmddata[i]=avr_sig(i);
161     txdata(app,verb,4);
162     break;
163   case AVR_ERASE:
164     avr_erase();
165     txdata(app,verb,0);
166     break;
167   case AVR_PEEKLOCK:
168     cmddata[0]=avr_lockbits();
169     txdata(app,verb,1);
170     break;
171   case AVR_POKELOCK:
172     avr_setlock(cmddata[0]);
173     txdata(app,verb,0);
174     break;
175   case AVR_POKEEEPROM:
176     avr_pokeeeprom(cmddataword[0], cmddata[2]);
177     //no break here.
178   case AVR_PEEKEEPROM:
179     cmddata[0]=avr_peekeeprom(cmddataword[0]);
180     txdata(app,verb,1);
181     break;
182   case PEEK:
183     //cmddata[0]=avr_peekflash(cmddataword[0]);
184     //txdata(app,verb,1);
185     at=cmddataword[0];
186     
187     //Fetch large blocks for bulk fetches,
188     //small blocks for individual peeks.
189     if(len>2){
190       len=(cmddataword[1]);//always even.
191     }else{
192       len=1;
193     }
194     txhead(app,verb,len);
195     for(i=0;i<len;i++){
196       serial_tx(avr_peekflash(at++));
197     }
198     break;
199   case POKE:
200   default:
201     debugstr("Verb unimplemented in AVR application.");
202     txdata(app,NOK,0);
203     break;
204   }
205 }
206