Add another example
[fw/altos] / ccdbg.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 "ccdbg.h"
20
21 static uint8_t
22 get_bit(char *line, int i, char on, uint8_t bit)
23 {
24         if (line[i] == on)
25                 return bit;
26         if (line[i] == '.')
27                 return 0;
28         fprintf(stderr, "bad line %s\n", line);
29         exit (1);
30 }
31
32 static char
33 is_bit(uint8_t get, char on, uint8_t bit)
34 {
35         if (get&bit)
36                 return on;
37         else
38                 return '.';
39 }
40
41 static uint8_t
42 ccdbg_write_read(struct ccdbg *dbg, uint8_t set)
43 {
44         uint8_t get;
45
46         ccdbg_write(dbg, CC_DATA|CC_CLOCK|CC_RESET_N, set);
47         get = ccdbg_read(dbg);
48         printf("%c %c %c -> %c %c %c\n",
49                is_bit(set, 'C', CC_CLOCK),
50                is_bit(set, 'D', CC_DATA),
51                is_bit(set, 'R', CC_RESET_N),
52                is_bit(get, 'C', CC_CLOCK),
53                is_bit(get, 'D', CC_DATA),
54                is_bit(get, 'R', CC_RESET_N));
55         ccdbg_half_clock(dbg);
56         return get;
57 }
58
59 static void
60 _ccdbg_debug_mode(struct ccdbg *dbg)
61 {
62         printf ("#\n");
63         printf ("# Debug mode\n");
64         printf ("#\n");
65         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA|CC_RESET_N);
66         ccdbg_write_read(dbg,          CC_DATA           );
67         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA           );
68         ccdbg_write_read(dbg,          CC_DATA           );
69         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA           );
70         ccdbg_write_read(dbg,          CC_DATA|CC_RESET_N);
71 }
72
73 static void
74 _ccdbg_reset(struct ccdbg *dbg)
75 {
76         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA|CC_RESET_N);
77         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA           );
78         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA           );
79         ccdbg_write_read(dbg, CC_CLOCK|CC_DATA|CC_RESET_N);
80 }
81
82 static void
83 _ccdbg_send_bit(struct ccdbg *dbg, uint8_t bit)
84 {
85         if (bit) bit = CC_DATA;
86         ccdbg_write_read(dbg, CC_CLOCK|bit|CC_RESET_N);
87         ccdbg_write_read(dbg,          bit|CC_RESET_N);
88 }
89
90 static void
91 _ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte)
92 {
93         int bit;
94         printf ("#\n");
95         printf ("# Send Byte 0x%02x\n", byte);
96         printf ("#\n");
97         for (bit = 7; bit >= 0; bit--) {
98                 _ccdbg_send_bit(dbg, (byte >> bit) & 1);
99                 if (bit == 3)
100                         printf ("\n");
101         }
102 }
103
104 static void
105 _ccdbg_send_bits(struct ccdbg *dbg, int n, uint32_t bits)
106 {
107         int bit;
108         printf ("#\n");
109         printf ("# Send %d bits 0x%08x\n", n, bits);
110         printf ("#\n");
111         for (bit = n - 1; bit >= 0; bit--) {
112                 _ccdbg_send_bit(dbg, (bits >> bit) & 1);
113                 if ((bit & 3) == 3)
114                         printf ("\n");
115         }
116 }
117
118 static void
119 _ccdbg_print_bits(int n, uint32_t bits)
120 {
121         int     bit;
122
123         for (bit = n - 1; bit >= 0; bit--)
124                 printf ("%d", (bits >> bit) & 1);
125 }
126
127 static uint32_t
128 _ccdbg_read_bits(struct ccdbg *dbg, int bits)
129 {
130         int             bit;
131         uint32_t        val = 0;
132         uint8_t         get;
133
134         printf ("#\n");
135         printf ("# Read %d bits\n", bits);
136         printf ("#\n");
137         for (bit = 0; bit < bits; bit++) {
138                       ccdbg_write_read(dbg, CC_CLOCK|CC_DATA|CC_RESET_N);
139                 get = ccdbg_write_read(dbg,          CC_DATA|CC_RESET_N);
140                 val <<= 1;
141                 if (get & CC_DATA)
142                         val |= 1;
143                 if ((bit & 3) == 3)
144                         printf ("\n");
145         }
146         printf ("#\n");
147         printf ("# Read "); _ccdbg_print_bits(bits, val); printf ("\n");
148         printf ("#\n");
149         return val;
150 }
151
152 static int
153 _ccdbg_check_bits(uint32_t bits, uint8_t match)
154 {
155         int     bit;
156
157         for (bit = 0; bit < 24; bit++)
158                 if (((bits >> bit) & 0xff) == match)
159                         return 1;
160         return 0;
161 }
162
163 static uint32_t
164 _ccdbg_play(struct ccdbg *dbg, int num_sync, uint32_t sync)
165 {
166         uint32_t        bits;
167         _ccdbg_debug_mode(dbg);
168         _ccdbg_send_bits(dbg, num_sync, sync);
169         _ccdbg_send_byte(dbg, CC_GET_CHIP_ID);
170         bits = _ccdbg_read_bits(dbg, 16);
171         _ccdbg_send_byte(dbg, CC_GET_CHIP_ID);
172         bits = _ccdbg_read_bits(dbg, 16);
173 //      _ccdbg_send_byte(dbg, CC_READ_STATUS);
174         _ccdbg_reset(dbg);
175         if (_ccdbg_check_bits(bits, 0x11)) {
176                 printf("#\n#match with %d bits 0x%08x\n#\n", num_sync, sync);
177                 return 1;
178         }
179         return 0;
180 }
181
182 static int
183 _ccdbg_play_num(struct ccdbg *dbg, int num)
184 {
185         uint32_t        sync;
186         uint32_t        max;
187
188         printf ("#\n#play %d\n#\n", num);
189         max = (1 << num);
190         for (sync = 0; sync < max; sync++)
191                 if (_ccdbg_play(dbg, num, sync))
192                         return 1;
193         return 0;
194 }
195
196 static int
197 _ccdbg_play_many(struct ccdbg *dbg, int max)
198 {
199         int     num;
200
201         for (num = 0; num < max; num++)
202                 if (_ccdbg_play_num(dbg, num))
203                         return 1;
204         return 0;
205 }
206
207 static void
208 ccdbg_manual(struct ccdbg *dbg, FILE *input)
209 {
210         char    line[80];
211         uint8_t set;
212
213         while (fgets(line, sizeof line, input)) {
214                 if (line[0] == '#' || line[0] == '\n') {
215                         printf ("%s", line);
216                         continue;
217                 }
218                 set = 0;
219                 set |= get_bit(line, 0, 'C', CC_CLOCK);
220                 set |= get_bit(line, 2, 'D', CC_DATA);
221                 set |= get_bit(line, 4, 'R', CC_RESET_N);
222                 ccdbg_write_read(dbg, set);
223         }
224 }
225
226 int
227 main (int argc, char **argv)
228 {
229         struct ccdbg    *dbg;
230         uint8_t         status;
231         uint16_t        chip_id;
232
233         dbg = ccdbg_open("/dev/ttyUSB0");
234         if (!dbg)
235                 exit (1);
236 #if 0   
237         _ccdbg_play(dbg, 0, 0);
238         _ccdbg_play_many(dbg, 8);
239 #endif
240         ccdbg_manual(dbg, stdin);
241 #if 0
242         ccdbg_debug_mode(dbg);
243         status = ccdbg_read_status(dbg);
244         printf("Status: 0x%02x\n", status);
245         chip_id = ccdbg_get_chip_id(dbg);
246         printf("Chip id: 0x%04x\n", chip_id);
247         _ccdbg_reset(dbg);
248 #endif
249         ccdbg_close(dbg);
250         exit (0);
251 }