Add libusb support and lots more examples
[fw/altos] / 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
21 void
22 ccdbg_quarter_clock(struct ccdbg *dbg)
23 {
24         usleep(CC_CLOCK_US / 4);
25 }
26
27 void
28 ccdbg_half_clock(struct ccdbg *dbg)
29 {
30         usleep(CC_CLOCK_US / 2);
31 }
32
33 struct ccdbg *
34 ccdbg_open(char *file)
35 {
36         struct ccdbg *dbg;
37
38         dbg = calloc(sizeof (struct ccdbg), 1);
39         if (!dbg) {
40                 perror("calloc");
41                 return NULL;
42         }
43         dbg->clock = 1;
44 #ifdef USE_KERNEL
45         dbg->fd = open(file, 2);
46         if (dbg->fd < 0) {
47                 perror(file);
48                 free(dbg);
49                 return NULL;
50         }
51         cccp_init(dbg);
52         cccp_write(dbg, CC_CLOCK, CC_CLOCK);
53 #else
54         cp_usb_init(dbg);
55 #endif
56         dbg->clock = 1;
57         return dbg;
58 }
59
60 void
61 ccdbg_close(struct ccdbg *dbg)
62 {
63 #if USE_KERNEL
64         cccp_fini(dbg);
65         close (dbg->fd);
66 #else
67         cp_usb_fini(dbg);
68 #endif
69         free (dbg);
70 }
71
72 int
73 ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)
74 {
75 #if USE_KERNEL
76         return cccp_write(dbg, mask, value);
77 #else
78         cp_usb_write(dbg, mask, value);
79         return 0;
80 #endif
81 }
82
83 uint8_t
84 ccdbg_read(struct ccdbg *dbg)
85 {
86 #if USE_KERNEL
87         return cccp_read_all(dbg);
88 #else
89         return cp_usb_read(dbg);
90 #endif
91 }
92         
93 void
94 ccdbg_clock_1_0(struct ccdbg *dbg)
95 {
96         ccdbg_quarter_clock(dbg);
97         assert(dbg->clock == 1);
98         ccdbg_write(dbg, CC_CLOCK, 0);
99         dbg->clock = 0;
100         ccdbg_quarter_clock(dbg);
101 }
102
103 void
104 ccdbg_clock_0_1(struct ccdbg *dbg)
105 {
106         ccdbg_quarter_clock(dbg);
107         assert(dbg->clock == 0);
108         ccdbg_write(dbg, CC_CLOCK, CC_CLOCK);
109         dbg->clock = 1;
110         ccdbg_quarter_clock(dbg);
111 }
112
113 /*
114  * By convention, every macro function is entered with dbg->clock == 1
115  */
116
117 void
118 ccdbg_write_bit(struct ccdbg *dbg, uint8_t bit)
119 {
120         uint8_t data;
121
122         assert(dbg->clock == 1);
123         data = CC_CLOCK;
124         if (bit)
125                 data |= CC_DATA;
126         ccdbg_half_clock(dbg);
127         ccdbg_write(dbg, CC_DATA|CC_CLOCK, data);
128         ccdbg_half_clock(dbg);
129         ccdbg_write(dbg, CC_CLOCK, 0);
130 //      printf ("%d", bit);
131 }
132
133 void
134 ccdbg_write_byte(struct ccdbg *dbg, uint8_t byte)
135 {
136         int     bit;
137
138         for (bit = 7; bit >= 0; bit--)
139                 ccdbg_write_bit(dbg, (byte >> bit) & 1);
140 }
141
142 uint8_t
143 ccdbg_read_bit(struct ccdbg *dbg)
144 {
145         uint8_t data;
146
147         ccdbg_half_clock(dbg);
148         ccdbg_write(dbg, CC_CLOCK, CC_CLOCK);
149         ccdbg_half_clock(dbg);
150         ccdbg_write(dbg, CC_CLOCK, 0);
151         data = ccdbg_read(dbg);
152         return (data & CC_DATA) ? 1 : 0;
153 }
154
155 uint8_t
156 ccdbg_read_byte(struct ccdbg *dbg)
157 {
158         int     bit;
159         uint8_t byte = 0;
160
161         for (bit = 7; bit >= 0; bit--)
162                 byte |= ccdbg_read_bit(dbg) << bit;
163         return byte;
164 }
165
166 void
167 ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
168 {
169         int     i;
170         ccdbg_write_byte(dbg, cmd);
171         for (i = 0; i < len; i++)
172                 ccdbg_write_byte(dbg, data[i]);
173 }
174
175 uint8_t
176 ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
177 {
178         uint8_t ret;
179         ccdbg_cmd_write(dbg, cmd, data, len);
180         ret = ccdbg_read_byte(dbg);
181         return ret;
182 }
183
184 uint16_t
185 ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len)
186 {
187         uint8_t byte1, byte0;
188         int     i;
189         ccdbg_cmd_write(dbg, cmd, data, len);
190         byte1 = ccdbg_read_byte(dbg); 
191         byte0 = ccdbg_read_byte(dbg);
192         for (i = 0; i < 4; i++)
193                 (void) ccdbg_read_byte(dbg);
194         return (byte1 << 8) | byte0;
195 }
196