Mercurial > ~darius > hgwebdir.cgi > avr
annotate testavr.c @ 52:3217e93b28a3
Missed variable declaration changes from previous commit.
author | darius@Inchoate |
---|---|
date | Wed, 29 Oct 2008 16:10:20 +1030 |
parents | cb184206344d |
children | 98b5a43fc748 |
rev | line source |
---|---|
0 | 1 /* |
9
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
2 * Test various AVR bits and pieces |
7ed10c59ba06
Supply clock speed via the command line so 1wire-delay.h can use it.
darius
parents:
7
diff
changeset
|
3 * |
41 | 4 * Copyright (c) 2008 |
0 | 5 * Daniel O'Connor <darius@dons.net.au>. All rights reserved. |
6 * | |
7 * Redistribution and use in source and binary forms, with or without | |
8 * modification, are permitted provided that the following conditions | |
9 * are met: | |
10 * 1. Redistributions of source code must retain the above copyright | |
11 * notice, this list of conditions and the following disclaimer. | |
12 * 2. Redistributions in binary form must reproduce the above copyright | |
13 * notice, this list of conditions and the following disclaimer in the | |
14 * documentation and/or other materials provided with the distribution. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
26 * SUCH DAMAGE. | |
27 */ | |
28 | |
29 #include <avr/io.h> | |
30 #include <avr/interrupt.h> | |
31 #include <avr/pgmspace.h> | |
41 | 32 #include <stdio.h> |
0 | 33 #include <string.h> |
4 | 34 #include <ctype.h> |
13 | 35 #include <stdlib.h> |
24 | 36 #include <util/delay.h> |
47 | 37 #include <avr/wdt.h> |
0 | 38 |
41 | 39 #include "cons.h" |
0 | 40 #include "1wire.h" |
37 | 41 #ifdef WITHUSB |
24 | 42 #include "usb.h" |
37 | 43 #endif |
41 | 44 #include "tempctrl.h" |
24 | 45 |
47 | 46 /* |
47 * Mirror of the MCUCSR register, taken early during startup. | |
48 */ | |
49 uint8_t mcucsr __attribute__((section(".noinit"))); | |
50 | |
24 | 51 void process_cmd(void); |
0 | 52 |
47 | 53 /* |
54 * Read out and reset MCUCSR early during startup. | |
55 */ | |
56 void handle_mcucsr(void) | |
57 __attribute__((section(".init3"))) | |
58 __attribute__((naked)); | |
59 void handle_mcucsr(void) { | |
60 mcucsr = MCUCSR; | |
61 MCUCSR = 0; | |
62 } | |
63 | |
24 | 64 int |
65 main(void) { | |
66 /* Disable interrupts while we frob stuff */ | |
67 cli(); | |
68 | |
41 | 69 #if 0 |
24 | 70 /* Disable JTAG (yes twice) */ |
71 MCUCSR |= _BV(JTD); | |
72 MCUCSR |= _BV(JTD); | |
37 | 73 #endif |
74 | |
75 #ifdef WITHUSB | |
24 | 76 /* USB data bus (7:0) */ |
77 DDRA = 0x00; | |
78 PORTA = 0x00; | |
79 | |
37 | 80 /* USB control (4:0) */ |
81 DDRB = 0x0d; | |
24 | 82 PORTB = 0x00; |
37 | 83 #else |
84 DDRA = 0xff; | |
85 PORTA = 0x00; | |
86 #endif | |
24 | 87 /* GPIO (0:7) */ |
88 DDRC = 0xff; | |
89 PORTC = 0x00; | |
90 | |
37 | 91 /* USART (0:1), IDBus (2:5), 485 (6:6), GPIO (7:7) */ |
92 DDRD = 0xf7; | |
93 PORTD = 0xf7; | |
94 | |
95 /* Set up the one wire stuff */ | |
96 OWInit(); | |
24 | 97 |
98 /* Init UART */ | |
41 | 99 cons_init(); |
24 | 100 |
41 | 101 printf_P(PSTR("\r\n\r\n===============\r\n" |
102 "Inited!\r\n\r\n")); | |
24 | 103 |
47 | 104 if ((mcucsr & _BV(PORF)) == _BV(PORF)) |
105 printf_P(PSTR("Power on reset\r\n")); | |
106 | |
107 if ((mcucsr & _BV(EXTRF)) == _BV(EXTRF)) | |
108 printf_P(PSTR("External reset\r\n")); | |
109 | |
110 if ((mcucsr & _BV(BORF)) == _BV(BORF)) | |
111 printf_P(PSTR("Brown-out reset\r\n")); | |
112 | |
113 if ((mcucsr & _BV(WDRF)) == _BV(WDRF)) | |
114 printf_P(PSTR("Watchdog reset\r\n")); | |
115 | |
116 if ((mcucsr & _BV(JTRF)) == _BV(JTRF)) | |
117 printf_P(PSTR("JTAG reset\r\n")); | |
118 | |
41 | 119 tempctrl_init(); |
120 | |
24 | 121 /* Ready to go! */ |
122 sei(); | |
123 | |
47 | 124 /* |
125 * Enable the watchdog with the largest prescaler. Will cause a | |
126 * watchdog reset after approximately 2 s @ Vcc = 5 V | |
127 * | |
128 * Gets reset in the loop below and in the tempctrl.c timer IRQ | |
129 */ | |
130 wdt_enable(WDTO_2S); | |
131 | |
37 | 132 #ifdef WITHUSB |
41 | 133 printf_P(PSTR("Calling usb_init\r\n")); |
24 | 134 usb_init(); |
41 | 135 printf_P(PSTR("done\r\n")); |
136 _delay_us(1000); | |
37 | 137 #endif |
41 | 138 printf_P(PSTR("> ")); |
24 | 139 cmd.state = 0; |
140 | |
141 /* Wait for user input or an "interrupt" */ | |
142 while (1) { | |
47 | 143 wdt_reset(); |
144 | |
41 | 145 tempctrl_update(); |
146 | |
24 | 147 if (cmd.state == 255) { |
148 process_cmd(); | |
41 | 149 printf_P(PSTR("> ")); |
24 | 150 /* Allow new characters to be processed */ |
151 cmd.state = 0; | |
152 } | |
153 | |
37 | 154 #ifdef WITHUSB |
155 if (!(PDICTL & _BV(PDIINT))) | |
24 | 156 usb_intr(); |
37 | 157 #endif |
24 | 158 } |
159 } | |
160 | |
161 void | |
162 process_cmd(void) { | |
52
3217e93b28a3
Missed variable declaration changes from previous commit.
darius@Inchoate
parents:
51
diff
changeset
|
163 uint8_t ROM[8], crc, buf[9], temp; |
24 | 164 int8_t i, arg; |
52
3217e93b28a3
Missed variable declaration changes from previous commit.
darius@Inchoate
parents:
51
diff
changeset
|
165 int16_t t; |
0 | 166 |
24 | 167 /* User just pressed enter */ |
168 if (cmd.len == 0) | |
169 return; | |
170 | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
171 if (!strcasecmp_P((char *)cmd.buf, PSTR("?")) || |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
172 !strcasecmp_P((char *)cmd.buf, PSTR("help"))) { |
41 | 173 printf_P(PSTR("rs Reset and check for presence\r\n" |
174 "sr Search the bus for ROMs\r\n" | |
175 "re Read a bit\r\n" | |
176 "rb Read a byte\r\n" | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
177 "wr bit Write a bit\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
178 "wb byte Write a byte (hex)\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
179 "wc cmd [ROMID] Write command\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
180 "te ROMID Read the temperature from a DS1820\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
181 "in port Read from a port\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
182 "ou port val Write to a port (val in hex)\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
183 "dd port [val] Read/write DDR for a port (val in hex)\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
184 "rt ROMID Read DS2502 status page\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
185 "we ROMID adr val Write data into a DS2502 PROM (adr & val in hex)\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
186 "rr ROMID Read DS2502 PROM\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
187 "zz Reset MCU\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
188 #ifdef WITHUSB |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
189 "us Generate USB data\r\n" |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
190 #endif |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
191 "tc ... Temperature control related (tc help for more)\r\n")); |
41 | 192 |
24 | 193 return; |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
194 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("zz"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
195 cli(); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
196 wdt_enable(WDTO_15MS); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
197 for (;;) |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
198 ; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
199 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rs"), 2)) { |
41 | 200 printf_P(PSTR("Resetting... ")); |
4 | 201 |
24 | 202 if (OWTouchReset() == 1) |
41 | 203 printf_P(PSTR("No presence pulse found\r\n")); |
24 | 204 else |
41 | 205 printf_P(PSTR("Presence pulse found\r\n")); |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
206 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("re"), 2)) { |
24 | 207 if (OWReadBit()) |
41 | 208 printf_P(PSTR("Read a 1\r\n")); |
24 | 209 else |
41 | 210 printf_P(PSTR("Read a 0\r\n")); |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
211 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rb"), 2)) { |
41 | 212 printf_P(PSTR("Read a 0x%02x\r\n"), OWReadByte()); |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
213 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wr"), 2)) { |
24 | 214 arg = strtol((char *)cmd.buf + 3, (char **)NULL, 10); |
215 OWWriteBit(arg); | |
41 | 216 printf_P(PSTR("Wrote a %c\r\n"), arg ? '1' : '0'); |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
217 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wb"), 2)) { |
24 | 218 arg = (int)strtol((char *)cmd.buf + 3, (char **)NULL, 16); |
219 OWWriteByte(arg); | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
220 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rt"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
221 if (sscanf_P((char *)cmd.buf, PSTR("rt %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
222 &ROM[0], &ROM[1], &ROM[2], &ROM[3], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
223 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) { |
41 | 224 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 225 return; |
226 } | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
227 |
37 | 228 if (ROM[0] != OW_FAMILY_ROM) { |
41 | 229 printf_P(PSTR("ROM specified isn't a DS2502\r\n")); |
37 | 230 return; |
231 } | |
232 | |
233 if (OWTouchReset() != 0) { | |
41 | 234 printf_P(PSTR("No presence\r\n")); |
37 | 235 return; |
236 } | |
237 | |
238 crc = 0; | |
239 | |
240 OWCRC(OW_READ_STATUS, &crc); | |
241 OWSendCmd(ROM, OW_READ_STATUS); | |
242 | |
243 OWWriteByte(0x00); | |
244 OWCRC(0x00, &crc); | |
245 | |
246 OWWriteByte(0x00); | |
247 OWCRC(0x00, &crc); | |
248 | |
249 if (crc != OWReadByte()) { | |
41 | 250 printf_P(PSTR("CRC mismatch on command & address\r\n")); |
37 | 251 return; |
252 } | |
253 | |
254 crc = 0; | |
255 for (i = 0; i < 8; i++) { | |
256 temp = OWReadByte(); | |
41 | 257 printf_P(PSTR("%02x "), temp); |
37 | 258 OWCRC(temp, &crc); |
259 } | |
41 | 260 printf_P(PSTR("\r\n")); |
37 | 261 if (crc != OWReadByte()) { |
41 | 262 printf_P(PSTR("CRC mismatch on data\r\n")); |
37 | 263 return; |
264 } | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
265 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("we"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
266 uint8_t adr, data; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
267 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
268 if (sscanf_P((char *)cmd.buf, PSTR("we %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhx %hhx"), |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
269 &ROM[0], &ROM[1], &ROM[2], &ROM[3], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
270 &ROM[4], &ROM[5], &ROM[6], &ROM[7], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
271 &adr, &data) != 10) { |
41 | 272 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 273 return; |
274 } | |
275 | |
276 if (ROM[0] != OW_FAMILY_ROM) { | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
277 printf_P(PSTR("ID specified isn't a ROM\r\n")); |
37 | 278 return; |
279 } | |
280 | |
281 if (OWTouchReset() != 0) { | |
41 | 282 printf_P(PSTR("No presence\r\n")); |
37 | 283 return; |
284 } | |
285 | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
286 printf_P(PSTR("OWProgROM returned %S\r\n"), OWProgROM_Status[OWProgROM(ROM, buf[0], 2, &buf[1], 0, 0)]); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
287 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("rr"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
288 if (sscanf_P((char *)cmd.buf, PSTR("rr %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
289 &ROM[0], &ROM[1], &ROM[2], &ROM[3], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
290 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) { |
41 | 291 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
37 | 292 return; |
293 } | |
294 | |
295 if (ROM[0] != OW_FAMILY_ROM) { | |
41 | 296 printf_P(PSTR("ROM specified isn't a ROM\r\n")); |
37 | 297 return; |
298 } | |
299 | |
300 crc = 0; | |
301 OWSendCmd(ROM, OW_READ_MEMORY); | |
302 OWCRC(OW_READ_MEMORY, &crc); | |
303 | |
304 OWWriteByte(0x00); | |
305 OWCRC(0x00, &crc); | |
306 | |
307 OWWriteByte(0x00); | |
308 OWCRC(0x00, &crc); | |
309 | |
310 if (crc != OWReadByte()) { | |
41 | 311 printf_P(PSTR("CRC mismatch on command & address\r\n")); |
37 | 312 return; |
313 } | |
314 | |
315 crc = 0; | |
316 for (buf[0] = 0; buf[0] < 128; buf[0]++) { | |
317 buf[1] = OWReadByte(); | |
318 if (buf[0] > 0) { | |
319 if (buf[0] % 16 != 0) | |
41 | 320 printf_P(PSTR(" ")); |
37 | 321 else |
41 | 322 printf_P(PSTR("\r\n")); |
37 | 323 } |
324 | |
41 | 325 printf_P(PSTR("%02x"), buf[1]); |
37 | 326 OWCRC(buf[1], &crc); |
327 } | |
41 | 328 printf_P(PSTR("\r\n")); |
37 | 329 if (crc != OWReadByte()) { |
41 | 330 printf_P(PSTR("CRC mismatch on data\r\n")); |
37 | 331 return; |
332 } | |
333 | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
334 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("wc"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
335 uint8_t c; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
336 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
337 i = sscanf_P((char *)cmd.buf, PSTR("wc %hhx %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
338 &ROM[0], &ROM[1], &ROM[2], &ROM[3], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
339 &ROM[4], &ROM[5], &ROM[6], &ROM[7], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
340 &c); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
341 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
342 if (i != 1 && i != 9) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
343 printf_P(PSTR("Incorrect usage\r\n")); |
24 | 344 return; |
345 } | |
346 | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
347 if (i == 1) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
348 OWSendCmd(i == 1 ? NULL : ROM, c); |
24 | 349 return; |
350 } | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
351 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("te"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
352 if (sscanf_P((char *)cmd.buf, PSTR("te %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx"), |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
353 &ROM[0], &ROM[1], &ROM[2], &ROM[3], |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
354 &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) { |
41 | 355 printf_P(PSTR("Unable to parse ROM ID\r\n")); |
24 | 356 return; |
357 } | |
358 | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
359 t = OWGetTemp(ROM); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
360 switch (t) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
361 case OW_TEMP_WRONG_FAM: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
362 printf_P(PSTR("ROM specified isn't a temperature sensor\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
363 break; |
24 | 364 |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
365 case OW_TEMP_CRC_ERR: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
366 printf_P(PSTR("CRC mismatch\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
367 break; |
41 | 368 |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
369 case OW_TEMP_NO_ROM: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
370 printf_P(PSTR("No ROM found\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
371 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
372 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
373 default: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
374 printf_P(PSTR("%d.%02d\r\n"), GETWHOLE(t), GETFRAC(t)); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
375 break; |
24 | 376 } |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
377 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("sr"), 2)) { |
24 | 378 memset(ROM, 0, 8); |
10 | 379 |
24 | 380 i = OWFirst(ROM, 1, 0); |
381 do { | |
382 switch (i) { | |
10 | 383 case OW_BADWIRE: |
41 | 384 printf_P(PSTR("Presence pulse, but no module found, bad module/cabling?\r\n")); |
10 | 385 break; |
386 | |
387 case OW_NOPRESENCE: | |
41 | 388 printf_P(PSTR("No presence pulse found\r\n")); |
10 | 389 break; |
390 | |
391 case OW_BADCRC: | |
41 | 392 printf_P(PSTR("Bad CRC\r\n")); |
10 | 393 break; |
394 | |
395 case OW_NOMODULES: | |
396 case OW_FOUND: | |
397 break; | |
398 | |
399 default: | |
41 | 400 printf_P(PSTR("Unknown error from 1 wire library\r\n")); |
10 | 401 break; |
24 | 402 } |
10 | 403 |
24 | 404 if (i != OW_FOUND) |
405 break; | |
13 | 406 |
41 | 407 for (i = 0; i < 8; i++) |
408 printf_P(PSTR("%02x%S"), ROM[i], i == 7 ? PSTR("\r\n") : PSTR(":")); | |
10 | 409 |
24 | 410 i = OWNext(ROM, 1, 0); |
411 } while (1); | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
412 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("in"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
413 uint8_t inp; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
414 |
24 | 415 switch (tolower(cmd.buf[3])) { |
416 case 'a': | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
417 inp = PINA; |
24 | 418 break; |
419 | |
420 case 'b': | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
421 inp = PINB; |
24 | 422 break; |
423 | |
424 case 'c': | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
425 inp = PINC; |
24 | 426 break; |
427 | |
428 case 'd': | |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
429 inp = PIND; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
430 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
431 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
432 default: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
433 printf_P(PSTR("Unknown port\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
434 return; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
435 } |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
436 printf_P(PSTR("0x%02x\r\n"), inp); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
437 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("ou"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
438 char port; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
439 int val; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
440 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
441 if (sscanf_P((char *)cmd.buf, PSTR("ou %c %x"), &port, &val) != 2) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
442 printf_P(PSTR("Unable to parse ou arguments\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
443 return; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
444 } |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
445 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
446 switch (port) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
447 case 'a': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
448 PORTA = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
449 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
450 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
451 case 'b': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
452 PORTB = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
453 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
454 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
455 case 'c': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
456 PORTC = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
457 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
458 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
459 case 'd': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
460 PORTD = val & 0xff; |
24 | 461 break; |
462 | |
463 default: | |
41 | 464 printf_P(PSTR("Unknown port\r\n")); |
24 | 465 return; |
0 | 466 } |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
467 printf_P(PSTR("PORT%c <= 0x%02x\r\n"), toupper(port), val); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
468 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("dd"), 2)) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
469 char port; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
470 uint8_t val; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
471 int num; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
472 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
473 num = sscanf_P((char *)cmd.buf, PSTR("dd %c %x"), &port, &val); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
474 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
475 if (num != 2 && num != 3) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
476 printf_P(PSTR("Unable to parse dd arguments\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
477 return; |
24 | 478 } |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
479 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
480 if (num == 2) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
481 switch (port) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
482 case 'a': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
483 val = DDRA; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
484 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
485 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
486 case 'b': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
487 val = DDRB; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
488 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
489 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
490 case 'c': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
491 val = DDRC; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
492 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
493 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
494 case 'd': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
495 val = DDRD; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
496 break; |
37 | 497 |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
498 default: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
499 printf_P(PSTR("Unknown port\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
500 return; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
501 } |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
502 printf_P(PSTR("DDR%c => 0x%02x\r\n"), toupper(port), val); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
503 } else { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
504 switch (port) { |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
505 case 'a': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
506 DDRA = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
507 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
508 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
509 case 'b': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
510 DDRB = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
511 break; |
37 | 512 |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
513 case 'c': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
514 DDRC = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
515 break; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
516 |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
517 case 'd': |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
518 DDRD = val & 0xff; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
519 break; |
37 | 520 |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
521 default: |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
522 printf_P(PSTR("Unknown port\r\n")); |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
523 return; |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
524 } |
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
525 printf_P(PSTR("DDR%c <= 0x%02x\r\n"), toupper(port), val); |
37 | 526 } |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
527 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("tc"), 2)) { |
41 | 528 tempctrl_cmd((char *)cmd.buf); |
37 | 529 #ifdef WITHUSB |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
530 } else if (!strncasecmp_P((char *)cmd.buf, PSTR("us"), 2)) { |
24 | 531 usb_gendata(); |
37 | 532 #endif |
24 | 533 } else { |
51
cb184206344d
Rejig command parsing and assume the compiler isn't dumb (eg it can reuse
darius@Inchoate
parents:
47
diff
changeset
|
534 printf_P(PSTR("Unknown command, help for a list\r\n")); |
0 | 535 } |
24 | 536 } |
0 | 537 |
538 |