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"
|
|
157 "re Read a bit\n\r"
|
|
158 "rb Read a byte\n\r"
|
|
159 "wr bit Write a bit\n\r"
|
|
160 "wb byte Write a byte (hex)\n\r"
|
|
161 "wc cmd [ROMID] Write command\n\r"
|
|
162 "te ROMID Read the temperature from a DS1820\n\r"));
|
|
163 continue;
|
|
164 }
|
0
|
165
|
4
|
166 if (i < 2)
|
|
167 goto badcmd;
|
|
168
|
|
169 if (cmdbuf[0] == 'r' && cmdbuf[1] == 's') {
|
|
170 uart_putsP(PSTR("Resetting... "));
|
|
171
|
|
172 if (OWTouchReset() == 1)
|
|
173 uart_putsP(PSTR("No presense\n\r"));
|
|
174 else
|
|
175 uart_putsP(PSTR("Presense\n\r"));
|
|
176 } else if (cmdbuf[0] == 'r' && cmdbuf[1] == 'e') {
|
0
|
177 if (OWReadBit())
|
|
178 uart_putsP(PSTR("Read a 1\n\r"));
|
|
179 else
|
|
180 uart_putsP(PSTR("Read a 0\n\r"));
|
4
|
181 } else if (cmdbuf[0] == 'r' && cmdbuf[1] == 'b') {
|
|
182 sprintf_P(cmdbuf, PSTR("Read a 0x%02x\n\r"), OWReadByte());
|
|
183 uart_puts(cmdbuf);
|
|
184 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'r') {
|
|
185 int arg;
|
|
186
|
|
187 if (sscanf_P(cmdbuf + 3, PSTR("%d"), &arg) != 1) {
|
|
188 uart_putsP(PSTR("Unable to parse wr command\n\r"));
|
|
189 continue;
|
|
190 }
|
|
191
|
|
192 OWWriteBit(arg);
|
|
193 sprintf_P(cmdbuf, PSTR("Wrote a %d\n\r"), arg);
|
|
194 uart_puts(cmdbuf);
|
|
195 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'b') {
|
|
196 int arg;
|
|
197
|
|
198 if (sscanf_P(cmdbuf + 3, PSTR("%2x"), &arg) != 1) {
|
|
199 uart_putsP(PSTR("Unable to parse wb command\n\r"));
|
|
200 continue;
|
|
201 }
|
|
202
|
|
203 OWWriteByte(arg);
|
|
204 sprintf_P(cmdbuf, PSTR("Wrote a 0x%02x\n\r"), arg);
|
|
205 uart_puts(cmdbuf);
|
|
206 } else if (cmdbuf[0] == 'w' && cmdbuf[1] == 'c') {
|
|
207 int arg;
|
0
|
208
|
4
|
209 switch (sscanf_P(cmdbuf + 3, PSTR("%x %x:%x:%x:%x:%x:%x:%x:%x:%x"), &arg,
|
|
210 &ROM[0], &ROM[1], &ROM[2], &ROM[3],
|
|
211 &ROM[4], &ROM[5], &ROM[6], &ROM[7])) {
|
|
212 break;
|
|
213
|
|
214 case 1:
|
|
215 OWSendCmd(NULL, arg);
|
|
216 sprintf_P(cmdbuf, PSTR("Sent 0x%02x to all ROMS\n\r"), arg);
|
|
217 uart_puts(cmdbuf);
|
|
218 break;
|
|
219
|
|
220 case 9:
|
|
221 OWSendCmd(ROM, arg);
|
|
222 sprintf_P(cmdbuf, PSTR("Sent 0x%02x to ROM %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n\r"),
|
|
223 arg, ROM[0], ROM[1], ROM[2], ROM[3],
|
|
224 ROM[4], ROM[5], ROM[6], ROM[7]);
|
|
225 uart_puts(cmdbuf);
|
|
226
|
|
227 break;
|
|
228
|
|
229 case 0:
|
|
230 default:
|
|
231 uart_putsP(PSTR("Unable to parse wc command\n\r"));
|
|
232 break;
|
|
233 }
|
|
234
|
|
235 OWWriteByte(arg);
|
|
236 sprintf_P(cmdbuf, PSTR("Wrote a 0x%02x\n\r"), arg);
|
|
237 uart_puts(cmdbuf);
|
|
238 } else if (cmdbuf[0] == 't' && cmdbuf[1] == 'e') {
|
|
239 uint8_t crc;
|
|
240 uint16_t temp;
|
|
241 uint8_t buf[9];
|
|
242
|
|
243 if (sscanf_P(cmdbuf + 3, PSTR("%x:%x:%x:%x:%x:%x:%x:%x:%x"),
|
|
244 &ROM[0], &ROM[1], &ROM[2], &ROM[3],
|
|
245 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) {
|
|
246 uart_putsP(PSTR("Unable to parse ROM ID\n\r"));
|
|
247 continue;
|
|
248 }
|
|
249
|
|
250 if (ROM[0] != OW_FAMILY_TEMP) {
|
|
251 uart_putsP(PSTR("ROM specified isn't a temperature sensor\n\r"));
|
|
252 continue;
|
|
253 }
|
|
254
|
|
255 OWSendCmd(ROM, OW_CONVERTT_CMD);
|
|
256 #if OW_DEBUG
|
|
257 uart_putsP(PSTR("Command sent, waiting\n\r"));
|
|
258 #endif
|
|
259 i = 0;
|
|
260 while (OWReadBit() == 0) {
|
|
261 i++;
|
|
262 }
|
|
263 #if OW_DEBUG
|
|
264 sprintf_P(cmdbuf, PSTR("Temp comversion took %d cycles\n\r"), i);
|
|
265 uart_puts(cmdbuf);
|
|
266 #endif
|
|
267 OWSendCmd(ROM, OW_RD_SCR_CMD);
|
|
268 crc = 0;
|
|
269 for (i = 0; i < 9; i++) {
|
|
270 buf[i] = OWReadByte();
|
|
271 if (i < 8)
|
|
272 OWCRC(buf[i], &crc);
|
|
273 }
|
|
274
|
|
275 temp = buf[0];
|
|
276 temp |= (uint16_t)buf[1] << 8;
|
|
277 temp <<= 3;
|
|
278
|
|
279 if (crc != buf[8]) {
|
|
280 sprintf_P(cmdbuf, PSTR("CRC mismatch got %d vs calcd %d\n\r"), buf[8], crc);
|
|
281 uart_puts(cmdbuf);
|
|
282 continue;
|
|
283 }
|
|
284
|
|
285 sprintf_P(cmdbuf, PSTR("temperature %d.%01d\n\r"),
|
|
286 temp >> 4, (temp << 12) / 6553);
|
|
287 uart_puts(cmdbuf);
|
|
288 } else if (cmdbuf[0] == 's' && cmdbuf[1] == 'r') {
|
|
289 memset(ROM, 0, 8);
|
0
|
290 if (OWTouchReset()) {
|
|
291 uart_putsP(PSTR("No devices on bus\n\r"));
|
|
292 break;
|
|
293 }
|
|
294 if (OWFirst(ROM, 1, 0) == 0) {
|
|
295 uart_putsP(PSTR("No module found\n\r"));
|
|
296 break;
|
|
297 }
|
|
298 do {
|
4
|
299 sprintf_P(cmdbuf, PSTR("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n\r"),
|
0
|
300 ROM[0],
|
|
301 ROM[1],
|
|
302 ROM[2],
|
|
303 ROM[3],
|
|
304 ROM[4],
|
|
305 ROM[5],
|
|
306 ROM[6],
|
|
307 ROM[7]);
|
4
|
308 uart_puts(cmdbuf);
|
|
309 } while (OWNext(ROM, 1, 0));
|
|
310 #if 0
|
0
|
311
|
4
|
312 } else if (cmdbuf[0] == 'l' && cmdbuf[1] == 'e' && cmdbuf[2] == 'd') {
|
0
|
313 if (leds == 0) {
|
|
314 leds = 1;
|
|
315 ledpos = 0;
|
|
316 outp(0, TCNT0);
|
|
317 sbi(TIMSK, TOIE0);
|
|
318 sei();
|
|
319 uart_putsP(PSTR("Starting\n\r"));
|
|
320 } else {
|
|
321 leds = 0;
|
|
322 ledpos = 0;
|
|
323 PORTA = 0x00;
|
|
324 cbi(TIMSK, TOIE0);
|
|
325 cli();
|
|
326 uart_putsP(PSTR("Stopping\n\r"));
|
|
327 }
|
4
|
328 #endif
|
|
329 } else {
|
|
330 badcmd:
|
|
331 uart_putsP(PSTR("Unknown command, ? for a list\n\r"));
|
0
|
332 }
|
|
333
|
|
334 }
|
|
335
|
|
336 return(0);
|
|
337 }
|
|
338
|
|
339 int
|
|
340 uart_putc(char c) {
|
|
341 loop_until_bit_is_set(USR, UDRE);
|
|
342 outp(c, UDR);
|
|
343
|
|
344 return(0);
|
|
345 }
|
|
346
|
|
347 void
|
|
348 uart_putsP(const char *addr) {
|
|
349 char c;
|
|
350
|
|
351 while ((c = PRG_RDB((unsigned short)addr++)))
|
|
352 uart_putc(c);
|
|
353 }
|
|
354
|
|
355 void
|
|
356 uart_puts(const char *addr) {
|
|
357 while (*addr)
|
|
358 uart_putc(*addr++);
|
|
359 }
|
|
360
|
4
|
361 int
|
0
|
362 uart_getc(void) {
|
|
363 while (!(inp(USR) & 0x80))
|
|
364 ;
|
|
365
|
|
366 return (inp(UDR));
|
|
367 }
|
4
|
368
|