e5e85e4390ff1220c3eebf12f30fe42a820b2d9e
[fw/altos] / lib / ccdbg-io.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 #include <time.h>
21 #ifdef CP_USB_ASYNC
22 #include "cp-usb-async.h"
23 #else
24 #include "cp-usb.h"
25 #endif
26
27 static uint32_t cc_clock_us = CC_CLOCK_US;
28
29 void
30 ccdbg_set_clock(uint32_t us)
31 {
32         cc_clock_us = us;
33 }
34
35 void
36 ccdbg_half_clock(struct ccdbg *dbg)
37 {
38         struct timespec req, rem;
39         req.tv_sec = (cc_clock_us / 2) / 1000000;
40         req.tv_nsec = ((cc_clock_us / 2) % 1000000) * 1000;
41         nanosleep(&req, &rem);
42 }
43
44 struct ccdbg *
45 ccdbg_open(void)
46 {
47         struct ccdbg *dbg;
48
49         dbg = calloc(sizeof (struct ccdbg), 1);
50         if (!dbg) {
51                 perror("calloc");
52                 return NULL;
53         }
54 #ifdef CP_USB_ASYNC
55         dbg->cp_async = cp_usb_async_open();
56         if (!dbg->cp_async) {
57                 free (dbg);
58                 return NULL;
59         }
60 #else
61         dbg->cp = cp_usb_open ();
62         if (!dbg->cp) {
63                 free (dbg);
64                 return NULL;
65         }
66 #endif
67         return dbg;
68 }
69
70 void
71 ccdbg_close(struct ccdbg *dbg)
72 {
73 #ifdef CP_USB_ASYNC
74         cp_usb_async_close(dbg->cp_async);
75 #else
76         cp_usb_close(dbg->cp);
77 #endif
78         free (dbg);
79 }
80
81 int
82 ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
83 {
84 #ifdef CP_USB_ASYNC
85         cp_usb_async_write(dbg->cp_async, mask, value);
86 #else
87         cp_usb_write(dbg->cp, mask, value);
88 #endif
89         return 0;
90 }
91
92 void
93 ccdbg_read(struct ccdbg *dbg, uint8_t *valuep)
94 {
95 #ifdef CP_USB_ASYNC
96         cp_usb_async_read(dbg->cp_async, valuep);
97 #else
98         *valuep = cp_usb_read(dbg->cp);
99 #endif
100 }
101
102 void
103 ccdbg_sync_io(struct ccdbg *dbg)
104 {
105 #ifdef CP_USB_ASYNC
106         cp_usb_async_sync(dbg->cp_async);
107 #endif
108 }
109
110 static char
111 is_bit(uint8_t get, uint8_t mask, char on, uint8_t bit)
112 {
113         if (mask&bit) {
114                 if (get&bit)
115                         return on;
116                 else
117                         return '.';
118         } else
119                 return '-';
120 }
121 void
122 ccdbg_print(char *format, uint8_t mask, uint8_t set)
123 {
124         ccdbg_debug (CC_DEBUG_BITBANG, format,
125                      is_bit(set, mask, 'C', CC_CLOCK),
126                      is_bit(set, mask, 'D', CC_DATA),
127                      is_bit(set, mask, 'R', CC_RESET_N));
128 }
129
130 void
131 ccdbg_send(struct ccdbg *dbg, uint8_t mask, uint8_t set)
132 {
133         ccdbg_write(dbg, mask, set);
134         ccdbg_print("%c %c %c\n", mask, set);
135         ccdbg_half_clock(dbg);
136 }
137
138 void
139 ccdbg_send_bit(struct ccdbg *dbg, uint8_t bit)
140 {
141         if (bit) bit = CC_DATA;
142         ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|bit|CC_RESET_N);
143         ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N,          bit|CC_RESET_N);
144 }
145
146 void
147 ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte)
148 {
149         int bit;
150         ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Send Byte 0x%02x\n#\n", byte);
151         for (bit = 7; bit >= 0; bit--) {
152                 ccdbg_send_bit(dbg, (byte >> bit) & 1);
153                 if (bit == 3)
154                         ccdbg_debug(CC_DEBUG_BITBANG, "\n");
155         }
156         ccdbg_sync_io(dbg);
157 }
158
159 void
160 ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)
161 {
162         while (nbytes--)
163                 ccdbg_send_byte(dbg, *bytes++);
164 }
165
166 void
167 ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit)
168 {
169         uint8_t mask = first ? CC_DATA : 0;
170
171         ccdbg_send(dbg, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N);
172         ccdbg_read(dbg, bit);
173         ccdbg_send(dbg, CC_CLOCK|     CC_RESET_N,                  CC_RESET_N);
174 }
175
176 void
177 ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *bytep)
178 {
179         uint8_t byte = 0;
180         uint8_t bits[8];
181         int     bit;
182
183         ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv byte\n#\n");
184         for (bit = 0; bit < 8; bit++) {
185                 ccdbg_recv_bit(dbg, first, &bits[bit]);
186                 first = 0;
187         }
188         ccdbg_sync_io(dbg);
189         for (bit = 0; bit < 8; bit++) {
190                 byte = byte << 1;
191                 byte |= (bits[bit] & CC_DATA) ? 1 : 0;
192                 ccdbg_print("#\t%c %c %c\n", CC_DATA, bits[bit]);
193                 if (bit == 3)
194                         ccdbg_debug(CC_DEBUG_BITBANG, "\n");
195         }
196         ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte);
197         *bytep = byte;
198 }
199
200 void
201 ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)
202 {
203         int i;
204         int first = 1;
205         for (i = 0; i < nbytes; i++) {
206                 ccdbg_recv_byte(dbg, first, &bytes[i]);
207                 first = 0;
208         }
209 }
210
211 void
212 ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
213 {
214         int     i;
215         ccdbg_send_byte(dbg, cmd);
216         for (i = 0; i < len; i++)
217                 ccdbg_send_byte(dbg, data[i]);
218 }
219
220 uint8_t
221 ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
222 {
223         uint8_t byte[1];
224         ccdbg_cmd_write(dbg, cmd, data, len);
225         ccdbg_recv_bytes(dbg, byte, 1);
226         return byte[0];
227 }
228
229 uint16_t
230 ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
231 {
232         uint8_t byte[2];
233         ccdbg_cmd_write(dbg, cmd, data, len);
234         ccdbg_recv_bytes(dbg, byte, 2);
235         return (byte[0] << 8) | byte[1];
236 }