Block reads in CC_READ_XDATA_MEMORY.
[goodfet] / firmware / lib / command.c
1 /*! \file command.c
2   \author Travis Goodspeed
3   \brief These functions manage command interpretation and timing.
4 */
5
6 #include "command.h"
7 #include "platform.h"
8 #include <string.h>
9
10 unsigned char cmddata[CMDDATALEN];
11 unsigned char silent=0;
12
13 //! Transmit a string.
14 void txstring(unsigned char app,
15               unsigned char verb,
16               const char *str){
17   unsigned long len=strlen(str);
18   txhead(app,verb,len);
19   while(len--)
20     serial_tx(*(str++));
21 }
22
23 /*! \brief Transmit a debug string.
24   
25   Transmits a debugging string that is to be printed
26   out of line by the client.  This is just for record-keeping;
27   it is not considered a proper reply to a query.
28  */
29 void debugstr(const char *str){
30   txstring(0xFF,0xFF,str);
31 }
32
33 //! brief Debug a hex word string.
34 void debughex(u16 v) {
35   debugbytes((void *)&v, 2);
36 }
37
38 //! brief Debug a hex word string.
39 void debughex32(u32 v) {
40   debugbytes((void *)&v, 4);
41 }
42
43 /*! \brief Transmit debug bytes.
44   
45   Transmits bytes for debugging.
46 */
47 void debugbytes(const char *bytes, unsigned int len){
48   u16 i;
49   txhead(0xFF,0xFE,len);
50   for(i=0;i<len;i++)
51     serial_tx(bytes[i]);
52 }
53
54
55 //! Transmit a header.
56 void txhead(unsigned char app,
57             unsigned char verb,
58             unsigned long len){
59   serial_tx(app);
60   serial_tx(verb);
61   //serial_tx(len); //old protocol
62   txword(len);
63 }
64
65 //! Transmit data.
66 void txdata(unsigned char app,
67             unsigned char verb,
68             unsigned long len){
69   unsigned int i=0;
70   if(silent)
71     return;
72   txhead(app,verb,len);
73   for(i=0;i<len;i++){
74     serial_tx(cmddata[i]);
75   }
76 }
77
78 //! Receive a long.
79 unsigned long rxlong(){
80   unsigned long toret=0;
81   toret=serial_rx();
82   toret|=(((long)serial_rx())<<8);
83   toret|=(((long)serial_rx())<<16);
84   toret|=(((long)serial_rx())<<24);
85   return toret;
86 }
87 //! Receive a word.
88 unsigned int rxword(){
89   unsigned long toret=0;
90   toret=serial_rx();
91   toret|=(((long)serial_rx())<<8);
92   return toret;
93 }
94 //! Transmit a long.
95 void txlong(unsigned long l){
96   serial_tx(l&0xFF);
97   l>>=8;
98   serial_tx(l&0xFF);
99   l>>=8;
100   serial_tx(l&0xFF);
101   l>>=8;
102   serial_tx(l&0xFF);
103   l>>=8;
104 }
105 //! Transmit a word.
106 void txword(unsigned int l){
107   serial_tx(l&0xFF);
108   l>>=8;
109   serial_tx(l&0xFF);
110   l>>=8;
111 }
112
113 //Be very careful changing delay().
114 //It was chosen poorly by trial and error.
115
116 //! Delay for a count.
117 void delay(unsigned int count){
118   volatile unsigned int i=count;
119   while(i--) asm("nop");
120 }
121 //! MSDelay
122 void msdelay(unsigned int ms){
123   volatile unsigned int i,j;
124   i=100;
125   while(i--){
126     j=ms;
127     while(j--) asm("nop");
128   }
129   //Using TimerA might be cleaner.
130 }
131
132
133 /* To better satisfy the somewhat odd timing requirements for
134    PIC33F/24H/24F ICSP programming, and for better control of GoodFET
135    timing more generally, here are a few delay routines that use Timer B.
136
137    Note that I wrote these referring only to the MSP430x2xx family
138    manual. Beware on MSP430x1xx chips. Further note that, assuming
139    some minor errors will be made, I try to err on the side of
140    delaying slightly longer than requested. */
141 void prep_timer()
142 {
143   BCSCTL2 = 0x00; /* In particular, use DCOCLK as SMCLK source with
144                      divider 1. Hence, Timer B ticks with system
145                      clock at 16 MHz. */
146
147   TBCTL = 0x0204; /* Driven by SMCLK; disable Timer B interrupts;
148                      reset timer in case it was previously in use */
149 }
150
151 //! Delay for specified number of milliseconds (given 16 MHz clock)
152 void delay_ms( unsigned int ms )
153 {
154   // 16000 ticks = 1 ms
155   TBCTL |= 0x20; // Start timer!
156   while (ms--) {
157     while (TBR < 16000)
158       asm( "nop" );
159     TBCTL = 0x0224;
160   }
161   TBCTL = 0x0204; // Reset Timer B, till next time
162 }
163
164 //! Delay for specified number of microseconds (given 16 MHz clock)
165 void delay_us( unsigned int us )
166 {
167   // 16 ticks = 1 us
168   TBCTL |= 0x20; // Start timer!
169   while (us--) {
170     while (TBR < 16)
171       asm( "nop" );
172     TBCTL = 0x0224;
173   }
174   TBCTL = 0x0204; // Reset Timer B, till next time
175 }
176
177 //! Delay for specified number of clock ticks (16 MHz clock implies 62.5 ns per tick).
178 void delay_ticks( unsigned int num_ticks )
179 {
180   TBCTL |= 0x20; // Start timer
181   while (TBR < num_ticks)
182     asm( "nop" );
183   TBCTL = 0x0204; // Reset Timer B, till next time
184 }