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