0
|
1 /*
|
|
2 * Copyright (c) 2004
|
|
3 * Daniel O'Connor <darius@dons.net.au>. All rights reserved.
|
|
4 *
|
|
5 * Redistribution and use in source and binary forms, with or without
|
|
6 * modification, are permitted provided that the following conditions
|
|
7 * are met:
|
|
8 * 1. Redistributions of source code must retain the above copyright
|
|
9 * notice, this list of conditions and the following disclaimer.
|
|
10 * 2. Redistributions in binary form must reproduce the above copyright
|
|
11 * notice, this list of conditions and the following disclaimer in the
|
|
12 * documentation and/or other materials provided with the distribution.
|
|
13 *
|
|
14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
24 * SUCH DAMAGE.
|
|
25 */
|
|
26
|
|
27 #include <stdio.h>
|
|
28 #include <avr/io.h>
|
|
29 #include <avr/interrupt.h>
|
|
30 #include <avr/signal.h>
|
|
31 #include <avr/pgmspace.h>
|
|
32 #include <string.h>
|
4
|
33 #include <ctype.h>
|
0
|
34
|
|
35 #include "1wire.h"
|
|
36
|
|
37 #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
|
|
38 #define XTAL_CPU 4000000 /* 4Mhz */
|
4
|
39 #define UART_BAUD_RATE 19200
|
0
|
40
|
|
41 void uart_putsP(const char *addr);
|
|
42 void uart_puts(const char *addr);
|
|
43 int uart_putc(char c);
|
4
|
44 int uart_getc(void);
|
|
45 int beginswith_P(const char *s1, const char *s2);
|
0
|
46
|
4
|
47 #if 0
|
0
|
48 uint8_t PROGMEM ledvals[] = {0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc0, 0x80};
|
4
|
49 static uint8_t dir = 0;
|
|
50 static volatile uint8_t leds = 0;
|
|
51 static uint8_t ledpos = 0;
|
0
|
52
|
|
53 INTERRUPT(SIG_OVERFLOW0) {
|
|
54 if (!leds)
|
|
55 return;
|
|
56
|
|
57 /* Going up */
|
|
58 if (dir == 0) {
|
|
59 if (ledpos == 9) {
|
|
60 dir = 1;
|
|
61 TCNT0 = 0;
|
|
62 goto doleds;
|
|
63 }
|
|
64
|
|
65 ledpos++;
|
|
66 } else {
|
|
67 if (ledpos == 0) {
|
|
68 dir = 0;
|
|
69 TCNT0 = 0;
|
|
70 goto doleds;
|
|
71 }
|
|
72
|
|
73 ledpos--;
|
|
74 }
|
|
75
|
|
76 doleds:
|
|
77 TCNT0 = 0;
|
|
78
|
|
79 PORTA = pgm_read_byte(&ledvals[ledpos]);
|
|
80 }
|
4
|
81 #endif
|
0
|
82
|
|
83 void
|
|
84 usleep(uint16_t usec) {
|
|
85 /* 4Mhz = 250ns per clock cycle */
|
|
86 usec /= 2;
|
|
87 if (usec < 1)
|
|
88 return;
|
|
89
|
|
90 while (usec--)
|
|
91 asm volatile (
|
|
92 ""
|
|
93 ::);
|
|
94 }
|
|
95
|
|
96 int
|
|
97 main(void) {
|
4
|
98 uint8_t ROM[8];
|
|
99 char cmdbuf[40];
|
0
|
100 int i;
|
|
101
|
|
102 cli();
|
4
|
103 #if 0
|
0
|
104 outp(0xff, DDRA);
|
4
|
105
|
|
106 /* Timer Clock divisor - CK/1024 */
|
|
107 outp(BV(CS00) | BV(CS02), TCCR0);
|
|
108 #endif
|
0
|
109 outp(0xfe, DDRC);
|
|
110 outp(0x00, PORTC);
|
|
111
|
|
112 /* Init UART */
|
|
113 outp(UART_BAUD_SELECT(UART_BAUD_RATE,XTAL_CPU), UBRR);
|
|
114
|
|
115 /* Enable receiver and transmitter. Turn on transmit interrupts */
|
|
116 outp(BV(RXEN) | BV(TXEN), UCR);
|
|
117
|
4
|
118 uart_putsP(PSTR("\n\r\n\r===============\n\r"
|
|
119 "Inited!\n\r\n\r"));
|
|
120
|
|
121 while (1) {
|
|
122 uart_putsP(PSTR("> "));
|
|
123 i = 0;
|
|
124 while (1) {
|
|
125 cmdbuf[i] = tolower(uart_getc());
|
|
126 if (cmdbuf[i] == '\n' || cmdbuf[i] == '\r')
|
|
127 break;
|
|
128
|
|
129 /* Backspace */
|
|
130 if (cmdbuf[i] == 010) {
|
|
131 if (i > 0) {
|
|
132 uart_putsP(PSTR("\010\040\010"));
|
|
133 i--;
|
|
134 }
|
|
135 continue;
|
|
136 }
|
0
|
137
|
4
|
138 /* Anything unprintable just ignore it */
|
|
139 if (!isprint(cmdbuf[i]))
|
|
140 continue;
|
|
141
|
|
142 uart_putc(cmdbuf[i]);
|
|
143 i++;
|
|
144 if (i == sizeof(cmdbuf)) {
|
|
145 uart_putsP(PSTR("\n\rLine too long\n\r"));
|
|
146 i = 0;
|
|
147 continue;
|
|
148 }
|
|
149 }
|
|
150 cmdbuf[i + 1] = '\0';
|
|
151 uart_putsP(PSTR("\n\r"));
|
|
152 if (i == 0)
|
|
153 continue;
|
0
|
154
|
4
|
155 if (cmdbuf[0] == '?') {
|
|
156 uart_putsP(PSTR("rs Reset and check for presence\n\r"
|
7
|
157 "sr Search the bus for ROMs\n\r"
|
4
|
158 "re Read a bit\n\r"
|
|
159 "rb Read a byte\n\r"
|
|
160 "wr bit Write a bit\n\r"
|
|
161 "wb byte Write a byte (hex)\n\r"
|
|
162 "wc cmd [ROMID] Write command\n\r"
|
|
163 "te ROMID Read the temperature from a DS1820\n\r"));
|
|
164 continue;
|
|
165 }
|
0
|
166
|
4
|
167 if (i < 2)
|
|
168 goto badcmd;
|
|
169
|
|
170 if (cmdbuf[0] == 'r' && cmdbuf[1] == 's') {
|
|
171 uart_putsP(PSTR("Resetting... "));
|
|
172
|
|
173 if (OWTouchReset() == 1)
|
|
174 uart_putsP(PSTR("No presense\n\r"));
|
|
175 else
|
|
176 uart_putsP(PSTR("Presense\n\r"));
|
|
177 } else if (cmdbuf[0] == 'r' && cmdbuf[1] == 'e') {
|
0
|
178 if (OWReadBit())
|
|
179 uart_putsP(PSTR("Read a 1\n\r"));
|
|
180 else
|
|
181 uart_putsP(PSTR("Read a 0\n\r"));
|
4
|
182 } else if (cmdbuf[0] == 'r' && cmdbuf[1] == 'b') {
|
|
183 sprintf_P(cmdbuf, PSTR("Read a 0x%02x\n\r"), OWReadByte());
|
|
184 uart_puts(cmdbuf);
|
|
185 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'r') {
|
|
186 int arg;
|
|
187
|
|
188 if (sscanf_P(cmdbuf + 3, PSTR("%d"), &arg) != 1) {
|
|
189 uart_putsP(PSTR("Unable to parse wr command\n\r"));
|
|
190 continue;
|
|
191 }
|
|
192
|
|
193 OWWriteBit(arg);
|
|
194 sprintf_P(cmdbuf, PSTR("Wrote a %d\n\r"), arg);
|
|
195 uart_puts(cmdbuf);
|
|
196 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'b') {
|
|
197 int arg;
|
|
198
|
|
199 if (sscanf_P(cmdbuf + 3, PSTR("%2x"), &arg) != 1) {
|
|
200 uart_putsP(PSTR("Unable to parse wb command\n\r"));
|
|
201 continue;
|
|
202 }
|
|
203
|
|
204 OWWriteByte(arg);
|
|
205 sprintf_P(cmdbuf, PSTR("Wrote a 0x%02x\n\r"), arg);
|
|
206 uart_puts(cmdbuf);
|
|
207 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'c') {
|
|
208 int arg;
|
0
|
209
|
4
|
210 switch (sscanf_P(cmdbuf + 3, PSTR("%x %x:%x:%x:%x:%x:%x:%x:%x:%x"), &arg,
|
|
211 &ROM[0], &ROM[1], &ROM[2], &ROM[3],
|
|
212 &ROM[4], &ROM[5], &ROM[6], &ROM[7])) {
|
|
213 break;
|
|
214
|
|
215 case 1:
|
|
216 OWSendCmd(NULL, arg);
|
|
217 sprintf_P(cmdbuf, PSTR("Sent 0x%02x to all ROMS\n\r"), arg);
|
|
218 uart_puts(cmdbuf);
|
|
219 break;
|
|
220
|
|
221 case 9:
|
|
222 OWSendCmd(ROM, arg);
|
|
223 sprintf_P(cmdbuf, PSTR("Sent 0x%02x to ROM %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n\r"),
|
|
224 arg, ROM[0], ROM[1], ROM[2], ROM[3],
|
|
225 ROM[4], ROM[5], ROM[6], ROM[7]);
|
|
226 uart_puts(cmdbuf);
|
|
227
|
|
228 break;
|
|
229
|
|
230 case 0:
|
|
231 default:
|
|
232 uart_putsP(PSTR("Unable to parse wc command\n\r"));
|
|
233 break;
|
|
234 }
|
|
235
|
|
236 OWWriteByte(arg);
|
|
237 sprintf_P(cmdbuf, PSTR("Wrote a 0x%02x\n\r"), arg);
|
|
238 uart_puts(cmdbuf);
|
|
239 } else if (cmdbuf[0] == 't' && cmdbuf[1] == 'e') {
|
|
240 uint8_t crc;
|
|
241 uint16_t temp;
|
|
242 uint8_t buf[9];
|
|
243
|
|
244 if (sscanf_P(cmdbuf + 3, PSTR("%x:%x:%x:%x:%x:%x:%x:%x:%x"),
|
|
245 &ROM[0], &ROM[1], &ROM[2], &ROM[3],
|
|
246 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
|
|
247 uart_putsP(PSTR("Unable to parse ROM ID\n\r"));
|
|
248 continue;
|
|
249 }
|
|
250
|
|
251 if (ROM[0] != OW_FAMILY_TEMP) {
|
|
252 uart_putsP(PSTR("ROM specified isn't a temperature sensor\n\r"));
|
|
253 continue;
|
|
254 }
|
|
255
|
|
256 OWSendCmd(ROM, OW_CONVERTT_CMD);
|
|
257 #if OW_DEBUG
|
|
258 uart_putsP(PSTR("Command sent, waiting\n\r"));
|
|
259 #endif
|
|
260 i = 0;
|
|
261 while (OWReadBit() == 0) {
|
|
262 i++;
|
|
263 }
|
|
264 #if OW_DEBUG
|
|
265 sprintf_P(cmdbuf, PSTR("Temp comversion took %d cycles\n\r"), i);
|
|
266 uart_puts(cmdbuf);
|
|
267 #endif
|
|
268 OWSendCmd(ROM, OW_RD_SCR_CMD);
|
|
269 crc = 0;
|
|
270 for (i = 0; i < 9; i++) {
|
|
271 buf[i] = OWReadByte();
|
|
272 if (i < 8)
|
|
273 OWCRC(buf[i], &crc);
|
|
274 }
|
|
275
|
|
276 temp = buf[0];
|
|
277 temp |= (uint16_t)buf[1] << 8;
|
|
278 temp <<= 3;
|
|
279
|
|
280 if (crc != buf[8]) {
|
|
281 sprintf_P(cmdbuf, PSTR("CRC mismatch got %d vs calcd %d\n\r"), buf[8], crc);
|
|
282 uart_puts(cmdbuf);
|
|
283 continue;
|
|
284 }
|
|
285
|
|
286 sprintf_P(cmdbuf, PSTR("temperature %d.%01d\n\r"),
|
|
287 temp >> 4, (temp << 12) / 6553);
|
|
288 uart_puts(cmdbuf);
|
|
289 } else if (cmdbuf[0] == 's' && cmdbuf[1] == 'r') {
|
|
290 memset(ROM, 0, 8);
|
0
|
291 if (OWTouchReset()) {
|
|
292 uart_putsP(PSTR("No devices on bus\n\r"));
|
|
293 break;
|
|
294 }
|
|
295 if (OWFirst(ROM, 1, 0) == 0) {
|
|
296 uart_putsP(PSTR("No module found\n\r"));
|
|
297 break;
|
|
298 }
|
|
299 do {
|
4
|
300 sprintf_P(cmdbuf, PSTR("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n\r"),
|
0
|
301 ROM[0],
|
|
302 ROM[1],
|
|
303 ROM[2],
|
|
304 ROM[3],
|
|
305 ROM[4],
|
|
306 ROM[5],
|
|
307 ROM[6],
|
|
308 ROM[7]);
|
4
|
309 uart_puts(cmdbuf);
|
|
310 } while (OWNext(ROM, 1, 0));
|
|
311 #if 0
|
0
|
312
|
4
|
313 } else if (cmdbuf[0] == 'l' && cmdbuf[1] == 'e' && cmdbuf[2] == 'd') {
|
0
|
314 if (leds == 0) {
|
|
315 leds = 1;
|
|
316 ledpos = 0;
|
|
317 outp(0, TCNT0);
|
|
318 sbi(TIMSK, TOIE0);
|
|
319 sei();
|
|
320 uart_putsP(PSTR("Starting\n\r"));
|
|
321 } else {
|
|
322 leds = 0;
|
|
323 ledpos = 0;
|
|
324 PORTA = 0x00;
|
|
325 cbi(TIMSK, TOIE0);
|
|
326 cli();
|
|
327 uart_putsP(PSTR("Stopping\n\r"));
|
|
328 }
|
4
|
329 #endif
|
|
330 } else {
|
|
331 badcmd:
|
|
332 uart_putsP(PSTR("Unknown command, ? for a list\n\r"));
|
0
|
333 }
|
|
334
|
|
335 }
|
|
336
|
|
337 return(0);
|
|
338 }
|
|
339
|
|
340 int
|
|
341 uart_putc(char c) {
|
|
342 loop_until_bit_is_set(USR, UDRE);
|
|
343 outp(c, UDR);
|
|
344
|
|
345 return(0);
|
|
346 }
|
|
347
|
|
348 void
|
|
349 uart_putsP(const char *addr) {
|
|
350 char c;
|
|
351
|
|
352 while ((c = PRG_RDB((unsigned short)addr++)))
|
|
353 uart_putc(c);
|
|
354 }
|
|
355
|
|
356 void
|
|
357 uart_puts(const char *addr) {
|
|
358 while (*addr)
|
|
359 uart_putc(*addr++);
|
|
360 }
|
|
361
|
4
|
362 int
|
0
|
363 uart_getc(void) {
|
|
364 while (!(inp(USR) & 0x80))
|
|
365 ;
|
|
366
|
|
367 return (inp(UDR));
|
|
368 }
|
4
|
369
|