Rename tools to ao-<foo>
[fw/altos] / ao-tools / target / ee / ee.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <stdint.h>
20
21 /*
22  * Validate the SPI-connected EEPROM
23  */
24
25 sfr at 0x80 P0;
26 sfr at 0x90 P1;
27 sfr at 0xA0 P2;
28 sfr at 0xC6 CLKCON;
29 sfr at 0xbe SLEEP;
30
31 # define SLEEP_USB_EN           (1 << 7)
32 # define SLEEP_XOSC_STB         (1 << 6)
33
34 sfr at 0xF1 PERCFG;
35 #define PERCFG_T1CFG_ALT_1      (0 << 6)
36 #define PERCFG_T1CFG_ALT_2      (1 << 6)
37
38 #define PERCFG_T3CFG_ALT_1      (0 << 5)
39 #define PERCFG_T3CFG_ALT_2      (1 << 5)
40
41 #define PERCFG_T4CFG_ALT_1      (0 << 4)
42 #define PERCFG_T4CFG_ALT_2      (1 << 4)
43
44 #define PERCFG_U1CFG_ALT_1      (0 << 1)
45 #define PERCFG_U1CFG_ALT_2      (1 << 1)
46
47 #define PERCFG_U0CFG_ALT_1      (0 << 0)
48 #define PERCFG_U0CFG_ALT_2      (1 << 0)
49
50 sfr at 0xF2 ADCCFG;
51 sfr at 0xF3 P0SEL;
52 sfr at 0xF4 P1SEL;
53 sfr at 0xF5 P2SEL;
54
55 sfr at 0xFD P0DIR;
56 sfr at 0xFE P1DIR;
57 sfr at 0xFF P2DIR;
58 sfr at 0x8F P0INP;
59 sfr at 0xF6 P1INP;
60 sfr at 0xF7 P2INP;
61
62 sfr at 0x89 P0IFG;
63 sfr at 0x8A P1IFG;
64 sfr at 0x8B P2IFG;
65
66 sbit at 0x90 P1_0;
67 sbit at 0x91 P1_1;
68 sbit at 0x92 P1_2;
69 sbit at 0x93 P1_3;
70 sbit at 0x94 P1_4;
71 sbit at 0x95 P1_5;
72 sbit at 0x96 P1_6;
73 sbit at 0x97 P1_7;
74
75 /*
76  * UART registers
77  */
78
79 sfr at 0x86 U0CSR;
80 sfr at 0xF8 U1CSR;
81
82 # define UxCSR_MODE_UART                (1 << 7)
83 # define UxCSR_MODE_SPI                 (0 << 7)
84 # define UxCSR_RE                       (1 << 6)
85 # define UxCSR_SLAVE                    (1 << 5)
86 # define UxCSR_MASTER                   (0 << 5)
87 # define UxCSR_FE                       (1 << 4)
88 # define UxCSR_ERR                      (1 << 3)
89 # define UxCSR_RX_BYTE                  (1 << 2)
90 # define UxCSR_TX_BYTE                  (1 << 1)
91 # define UxCSR_ACTIVE                   (1 << 0)
92
93 sfr at 0xc4 U0UCR;
94 sfr at 0xfb U1UCR;
95
96 sfr at 0xc5 U0GCR;
97 sfr at 0xfc U1GCR;
98
99 # define UxGCR_CPOL_NEGATIVE            (0 << 7)
100 # define UxGCR_CPOL_POSITIVE            (1 << 7)
101 # define UxGCR_CPHA_FIRST_EDGE          (0 << 6)
102 # define UxGCR_CPHA_SECOND_EDGE         (1 << 6)
103 # define UxGCR_ORDER_LSB                (0 << 5)
104 # define UxGCR_ORDER_MSB                (1 << 5)
105 # define UxGCR_BAUD_E_MASK              (0x1f)
106 # define UxGCR_BAUD_E_SHIFT             0
107
108 sfr at 0xc1 U0DBUF;
109 sfr at 0xf9 U1DBUF;
110 sfr at 0xc2 U0BAUD;
111 sfr at 0xfa U1BAUD;
112
113 #define MOSI    P1_5
114 #define MISO    P1_4
115 #define SCK     P1_3
116 #define CS      P1_2
117
118 #define DEBUG   P1_1
119
120 #define BITBANG 0
121 #define USART   1
122
123 #define nop()   _asm nop _endasm;
124
125 void
126 delay (unsigned char n)
127 {
128         unsigned char i = 0;
129         unsigned char j = 0;
130
131         while (--n != 0)
132                 while (--i != 0)
133                         while (--j != 0)
134                                 nop();
135 }
136
137 #if BITBANG
138
139 /*
140  * This version directly manipulates the GPIOs to synthesize SPI
141  */
142
143 void
144 bitbang_cs(uint8_t b)
145 {
146         SCK = 0;
147         CS = b;
148         delay(1);
149 }
150
151 void
152 bitbang_out_bit(uint8_t b)
153 {
154         MOSI = b;
155         delay(1);
156         SCK = 1;
157         delay(1);
158         SCK = 0;
159 }
160
161 void
162 bitbang_out_byte(uint8_t byte)
163 {
164         uint8_t s;
165
166         for (s = 0; s < 8; s++) {
167                 uint8_t b = (byte & 0x80) ? 1 : 0;
168                 bitbang_out_bit(b);
169                 byte <<= 1;
170         }
171 }
172
173 uint8_t
174 bitbang_in_bit(void)
175 {
176         uint8_t b;
177
178         delay(1);
179         SCK = 1;
180         delay(1);
181         b = MISO;
182         SCK = 0;
183         return b;
184 }
185
186 uint8_t
187 bitbang_in_byte(void)
188 {
189         uint8_t byte = 0;
190         uint8_t s;
191         uint8_t b;
192
193         for (s = 0; s < 8; s++) {
194                 b = bitbang_in_bit();
195                 byte = byte << 1;
196                 byte |= b;
197         }
198         return byte;
199 }
200
201 void
202 bit_bang_init(void)
203 {
204         CS = 1;
205         SCK = 0;
206         P1DIR = ((1 << 5) |
207                  (0 << 4) |
208                  (1 << 3) |
209                  (1 << 2) |
210                  (1 << 1));
211 }
212
213 #define spi_init()      bitbang_init()
214 #define spi_out_byte(b) bitbang_out_byte(b)
215 #define spi_in_byte()   bitbang_in_byte()
216 #define spi_cs(b)       bitbang_cs(b)
217 #endif
218
219 #if USART
220
221 /*
222  * This version uses the USART in SPI mode
223  */
224 void
225 usart_init(void)
226 {
227         /*
228          * Configure our chip select line
229          */
230         CS = 1;
231         P1DIR |= (1 << 2);
232         /*
233          * Configure the peripheral pin choices
234          * for both of the serial ports
235          *
236          * Note that telemetrum will use U1CFG_ALT_2
237          * but that overlaps with SPI ALT_2, so until
238          * we can test that this works, we'll set this
239          * to ALT_1
240          */
241         PERCFG = (PERCFG_U1CFG_ALT_1 |
242                   PERCFG_U0CFG_ALT_2);
243
244         /*
245          * Make the SPI pins controlled by the SPI
246          * hardware
247          */
248         P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3));
249
250         /*
251          * SPI in master mode
252          */
253         U0CSR = (UxCSR_MODE_SPI |
254                  UxCSR_MASTER);
255
256         /*
257          * The cc1111 is limited to a 24/8 MHz SPI clock,
258          * while the 25LC1024 is limited to 20MHz. So,
259          * use the 3MHz clock (BAUD_E 17, BAUD_M 0)
260          */
261         U0BAUD = 0;
262         U0GCR = (UxGCR_CPOL_NEGATIVE |
263                  UxGCR_CPHA_FIRST_EDGE |
264                  UxGCR_ORDER_MSB |
265                  (17 << UxGCR_BAUD_E_SHIFT));
266 }
267
268 void
269 usart_cs(uint8_t b)
270 {
271         CS = b;
272 }
273
274 uint8_t
275 usart_in_out(uint8_t byte)
276 {
277         U0DBUF = byte;
278         while ((U0CSR & UxCSR_TX_BYTE) == 0)
279                 ;
280         U0CSR &= ~UxCSR_TX_BYTE;
281         return U0DBUF;
282 }
283
284 void
285 usart_out_byte(uint8_t byte)
286 {
287         (void) usart_in_out(byte);
288 }
289
290 uint8_t
291 usart_in_byte(void)
292 {
293         return usart_in_out(0xff);
294 }
295
296 #define spi_init()      usart_init()
297 #define spi_out_byte(b) usart_out_byte(b)
298 #define spi_in_byte()   usart_in_byte()
299 #define spi_cs(b)       usart_cs(b)
300
301 #endif
302
303 uint8_t
304 rdsr(void)
305 {
306         uint8_t status;
307         spi_cs(0);
308         spi_out_byte(0x05);
309         status = spi_in_byte();
310         spi_cs(1);
311         return status;
312 }
313
314 void
315 wrsr(uint8_t status)
316 {
317         spi_cs(0);
318         spi_out_byte(0x01);
319         spi_out_byte(status);
320         spi_cs(1);
321 }
322
323 void
324 wren(void)
325 {
326         spi_cs(0);
327         spi_out_byte(0x06);
328         spi_cs(1);
329 }
330
331 void
332 write(uint32_t addr, uint8_t *bytes, uint16_t len)
333 {
334         wren();
335         spi_cs(0);
336         spi_out_byte(0x02);
337         spi_out_byte(addr >> 16);
338         spi_out_byte(addr >> 8);
339         spi_out_byte(addr);
340         while (len-- > 0)
341                 spi_out_byte(*bytes++);
342         spi_cs(1);
343         for (;;) {
344                 uint8_t status = rdsr();
345                 if ((status & (1 << 0)) == 0)
346                         break;
347         }
348 }
349
350 void
351 read(uint32_t addr, uint8_t *bytes, uint16_t len)
352 {
353         spi_cs(0);
354         spi_out_byte(0x03);
355         spi_out_byte(addr >> 16);
356         spi_out_byte(addr >> 8);
357         spi_out_byte(addr);
358         while (len-- > 0)
359                 *bytes++ = spi_in_byte();
360         spi_cs(1);
361 }
362
363 void
364 debug_byte(uint8_t byte)
365 {
366         uint8_t s;
367
368         for (s = 0; s < 8; s++) {
369                 DEBUG = byte & 1;
370                 delay(5);
371                 byte >>= 1;
372         }
373 }
374
375 #define STRING  "\360\252"
376 #define LENGTH  2
377
378 main ()
379 {
380         uint8_t status;
381         uint8_t buf[LENGTH];
382         int i;
383
384         P1DIR |= 2;
385         CLKCON = 0;
386         while (!(SLEEP & SLEEP_XOSC_STB))
387                 ;
388
389         spi_init();
390
391         status = rdsr();
392         /*
393          * Turn off both block-protect bits
394          */
395         status &= ~((1 << 3) | (1 << 2));
396         /*
397          * Turn off write protect enable
398          */
399         status &= ~(1 << 7);
400         wrsr(status);
401         write(0x0, STRING, LENGTH);
402         for (;;) {
403                 read(0x0, buf, LENGTH);
404                 for (i = 0; i < LENGTH; i++)
405                         debug_byte(buf[i]);
406         }
407 }