ebus: Switch to a 10ms ticker
[wk-misc.git] / ebus / testnode.c
1 /* testnode.c - Elektor Bus test Node
2  * Copyright (C) 2011 g10 Code GmbH
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 3 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,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17
18 /* This node continuously sends messages with status information.  S2
19    and S3 are used to change the send interval.  */
20
21 #include "hardware.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <avr/io.h>
27 #include <avr/interrupt.h>
28 #include <avr/sleep.h>
29 #include <util/delay.h>
30
31 #include <util/crc16.h>
32
33 #include "ebus.h"
34 #include "proto-dbgmsg.h"
35
36
37 static volatile unsigned short send_interval;
38
39 static volatile byte send_flag;
40
41
42
43 /* This code is called by the 1ms ticker interrupt service routine
44    with the current clock value given in milliseconds from 0..999. */
45 void
46 ticker_bottom (unsigned int clock)
47 {
48
49   /* Run the main loop every N ms.  */
50   if (send_interval && !(clock % send_interval))
51     {
52       send_flag = 1;
53       wakeup_main = 1;
54     }
55
56   if (read_key_s2 ())
57     {
58       switch (send_interval)
59         {
60         case 1000:
61           /* Disable sending but send one more frame to show the
62              new sending interval.  */
63           send_interval = 0;
64           send_flag = 1;
65           wakeup_main = 1;
66           break;
67         case  500: send_interval = 1000; break;
68         case  250: send_interval =  500; break;
69         case  125: send_interval =  250; break;
70         case  100: send_interval =  125; break;
71         case   50: send_interval =  100; break;
72         case   25: send_interval =   50; break;
73         }
74     }
75   if (read_key_s3 ())
76     {
77       switch (send_interval)
78         {
79         case 0:    send_interval = 1000; break;
80         case 1000: send_interval = 500; break;
81         case  500: send_interval = 250; break;
82         case  250: send_interval = 125; break;
83         case  125: send_interval = 100; break;
84         case  100: send_interval =  50; break;
85         case   50: send_interval =  25; break;
86         }
87     }
88 }
89
90
91 static void
92 send_msg (void)
93 {
94   byte msg[MSGSIZE];
95   int idx = 0;
96   unsigned int val;
97
98   msg[idx++] = PROTOCOL_EBUS_TEST;
99   msg[idx++] = 0;
100   msg[idx++] = config.nodeid_lo;
101   msg[idx++] = 0;
102   msg[idx++] = (val = get_current_time ()) >> 8;
103   msg[idx++] = val;
104   msg[idx++] = (val = csma_get_stats (1)) >> 8;
105   msg[idx++] = val;
106   msg[idx++] = (val = csma_get_stats (2)) >> 8;
107   msg[idx++] = val;
108   msg[idx++] = (val = csma_get_stats (3)) >> 8;
109   msg[idx++] = val;
110   msg[idx++] = (val = csma_get_stats (4)) >> 8;
111   msg[idx++] = val;
112   msg[idx++] = send_interval >> 8;
113   msg[idx++] = send_interval;
114
115   csma_send_message (msg, MSGSIZE);
116 }
117
118
119 static void
120 send_dbgmsg (const char *string)
121 {
122   byte msg[16];
123
124   msg[0] = PROTOCOL_EBUS_DBGMSG;
125   msg[1] = config.nodeid_hi;
126   msg[2] = config.nodeid_lo;
127   memset (msg+3, 0, 13);
128   strncpy (msg+3, string, 13);
129   csma_send_message (msg, 16);
130 }
131
132 static void
133 send_dbgmsg_fmt (const char *format, ...)
134 {
135   va_list arg_ptr;
136   char buffer[16];
137
138   va_start (arg_ptr, format);
139   vsnprintf (buffer, 16, format, arg_ptr);
140   va_end (arg_ptr);
141   send_dbgmsg (buffer);
142 }
143
144
145
146 /* A new message has been received and we must now parse the message
147    quickly and see what to do.  We need to return as soon as possible,
148    so that the caller may re-enable the receiver.  */
149 static void
150 process_ebus_test (void)
151 {
152   /* Is this a broadcast or is it directed to us.  If not we don't
153      need to care about it.  */
154
155 }
156
157
158
159 /*
160     Entry point
161  */
162 int
163 main (void)
164 {
165   byte *msg;
166   hardware_setup (NODETYPE_UNDEFINED);
167   csma_setup ();
168   onewire_setup ();
169
170   send_interval = 1000;
171
172   sei (); /* Enable interrupts.  */
173
174
175   /* for (;;) */
176   /*   { */
177   /*     byte i, crc, buf[9]; */
178
179   /*     send_dbgmsg_fmt ("serial..."); */
180   /*     onewire_enable (); */
181   /*     onewire_write_byte (0x33); /\* Read ROM.  *\/ */
182   /*     _delay_ms (50); */
183   /*     onewire_enable (); */
184   /*     for (i=0; i < 8; i++) */
185   /*       buf[i] = onewire_read_byte (); */
186   /*     _delay_ms (1); */
187   /*     crc = 0; */
188   /*     for (i=0; i < 7; i++) */
189   /*       crc = _crc_ibutton_update (crc, buf[i]); */
190
191   /*     send_dbgmsg_fmt ("%02x %02x%02x%02x %02x", */
192   /*                      buf[0], buf[1], buf[2], buf[3], buf[7]); */
193   /*     send_dbgmsg_fmt ("%02x%02x%02x %s", */
194   /*                      buf[4], buf[5], buf[6], */
195   /*                      buf[7] == crc? "ok":"bad"); */
196
197   /*     _delay_ms (2000); */
198   /*   } */
199
200   for (;;)
201     {
202       byte i, crc, buf[9];
203
204       onewire_enable ();
205       onewire_write_byte (0xcc); /* Skip ROM.  */
206       onewire_write_byte (0x44); /* Convert T.  */
207       /* onewire_wait_for_one (); */
208       _delay_ms (900);
209       onewire_enable ();         /* Reset */
210       onewire_write_byte (0xcc); /* Skip ROM.  */
211       onewire_write_byte (0xbe); /* Read scratchpad.  */
212       for (i=0; i < 9; i++)
213         buf[i] = onewire_read_byte ();
214
215       crc = 0;
216       for (i=0; i < 8; i++)
217         crc = _crc_ibutton_update (crc, buf[i]);
218
219       if (buf[8] == crc)
220         {
221           int16_t tread = (buf[1] << 8) | buf[0];
222           int16_t t;
223
224           t = (tread*100 - 25 + ((16 - buf[6])*100 / 16)) / 20;
225
226           send_dbgmsg_fmt ("t=%d (%d)", t, tread);
227         }
228       else
229         send_dbgmsg_fmt ("badcrc");
230
231       onewire_disable ();
232       _delay_ms (1000);
233     }
234
235
236
237   for (;;)
238     {
239       set_sleep_mode (SLEEP_MODE_IDLE);
240       while (!wakeup_main)
241         {
242           cli();
243           if (!wakeup_main)
244             {
245               sleep_enable ();
246               sei ();
247               sleep_cpu ();
248               sleep_disable ();
249             }
250           sei ();
251         }
252       wakeup_main = 0;
253
254       msg = csma_get_message ();
255       if (msg)
256         {
257           /* Process the message.  */
258           switch ((msg[0] & PROTOCOL_TYPE_MASK))
259             {
260             case PROTOCOL_EBUS_TEST:
261               process_ebus_test ();
262               break;
263             default:
264               /* Ignore all other protocols.  */
265               break;
266             }
267           /* Re-enable the receiver.  */
268           csma_message_done ();
269         }
270
271       if (send_flag)
272         {
273           send_msg ();
274           send_flag = 0;
275         }
276     }
277 }