Statistics
| Revision:

root / Ports / Ports.cpp

History | View | Annotate | Download (26.1 KB)

1 7763 jcw
//>>> The latest version of this code can be found at https://github.com/jcw/ !!
2 7763 jcw
3 4727 jcw
// Ports library definitions
4 4727 jcw
// 2009-02-13 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
5 4727 jcw
// $Id$
6 4727 jcw
7 4727 jcw
#include "Ports.h"
8 5984 jcw
#include <avr/sleep.h>
9 6060 jcw
#include <util/atomic.h>
10 4727 jcw
11 4727 jcw
// flag bits sent to the receiver
12 4727 jcw
#define MODE_CHANGE 0x80    // a pin mode was changed
13 4727 jcw
#define DIG_CHANGE  0x40    // a digital output was changed
14 4727 jcw
#define PWM_CHANGE  0x30    // an analog (pwm) value was changed on port 2..3
15 4727 jcw
#define ANA_MASK    0x0F    // an analog read was requested on port 1..4
16 4727 jcw
17 4727 jcw
uint16_t Port::shiftRead(uint8_t bitOrder, uint8_t count) const {
18 4727 jcw
    uint16_t value = 0, mask = bit(LSBFIRST ? 0 : count - 1);
19 4727 jcw
    for (uint8_t i = 0; i < count; ++i) {
20 4727 jcw
        digiWrite2(1);
21 4727 jcw
        delayMicroseconds(5);
22 4727 jcw
        if (digiRead())
23 4727 jcw
            value |= mask;
24 4727 jcw
        if (bitOrder == LSBFIRST)
25 4727 jcw
            mask <<= 1;
26 4727 jcw
        else
27 4727 jcw
            mask >>= 1;
28 4727 jcw
        digiWrite2(0);
29 4727 jcw
        delayMicroseconds(5);
30 4727 jcw
    }
31 4727 jcw
    return value;
32 4727 jcw
}
33 4727 jcw
34 4727 jcw
void Port::shiftWrite(uint8_t bitOrder, uint16_t value, uint8_t count) const {
35 4727 jcw
    uint16_t mask = bit(LSBFIRST ? 0 : count - 1);
36 4727 jcw
    for (uint8_t i = 0; i < count; ++i) {
37 6481 jcw
        digiWrite((value & mask) != 0);
38 4727 jcw
        if (bitOrder == LSBFIRST)
39 4727 jcw
            mask <<= 1;
40 4727 jcw
        else
41 4727 jcw
            mask >>= 1;
42 4727 jcw
        digiWrite2(1);
43 4727 jcw
        digiWrite2(0);
44 4727 jcw
    }
45 4727 jcw
}
46 4727 jcw
47 4727 jcw
RemoteNode::RemoteNode (char id, uint8_t band, uint8_t group)
48 4727 jcw
    : nid (id & 0x1F)
49 4727 jcw
{
50 4727 jcw
    memset(&data, 0, sizeof data);
51 4727 jcw
    RemoteHandler::setup(nid, band, group);
52 4727 jcw
}
53 4727 jcw
54 4727 jcw
void RemoteNode::poll(uint16_t msecs) {
55 4727 jcw
    uint8_t pending = millis() >= lastPoll + msecs;
56 4727 jcw
    if (RemoteHandler::poll(*this, pending))
57 4727 jcw
        lastPoll = millis();
58 4727 jcw
}
59 4727 jcw
60 4727 jcw
void RemotePort::mode(uint8_t value) const {
61 4727 jcw
    node.data.flags |= MODE_CHANGE;
62 4727 jcw
    bitWrite(node.data.modes, pinBit(), value);
63 4727 jcw
}
64 4727 jcw
65 4727 jcw
uint8_t RemotePort::digiRead() const {
66 4727 jcw
    return bitRead(node.data.digiIO, pinBit());
67 4727 jcw
}
68 4727 jcw
69 4727 jcw
void RemotePort::digiWrite(uint8_t value) const {
70 4727 jcw
    node.data.flags |= DIG_CHANGE;
71 4727 jcw
    bitWrite(node.data.digiIO, pinBit(), value);
72 4727 jcw
}
73 4727 jcw
74 4727 jcw
void RemotePort::anaWrite(uint8_t val) const {
75 4727 jcw
    if (portNum == 2 || portNum == 3) {
76 4727 jcw
        bitSet(node.data.flags, portNum + 2);
77 4727 jcw
        node.data.anaOut[portNum - 2] = val;
78 4727 jcw
    } else
79 4727 jcw
        digiWrite2(val >= 128);
80 4727 jcw
}
81 4727 jcw
82 4727 jcw
void RemotePort::mode2(uint8_t value) const {
83 4727 jcw
    node.data.flags |= MODE_CHANGE;
84 4727 jcw
    bitWrite(node.data.modes, pinBit2(), value);
85 4727 jcw
}
86 4727 jcw
87 4727 jcw
uint16_t RemotePort::anaRead() const {
88 4727 jcw
    bitSet(node.data.flags, pinBit());
89 4727 jcw
    return node.data.anaIn[pinBit()];
90 4727 jcw
}
91 4727 jcw
92 4727 jcw
uint8_t RemotePort::digiRead2() const {
93 4727 jcw
    return bitRead(node.data.digiIO, pinBit2());
94 4727 jcw
}
95 4727 jcw
96 4727 jcw
void RemotePort::digiWrite2(uint8_t value) const {
97 4727 jcw
    node.data.flags |= DIG_CHANGE;
98 4727 jcw
    bitWrite(node.data.digiIO, pinBit2(), value);
99 4727 jcw
}
100 4727 jcw
101 4727 jcw
PortI2C::PortI2C (uint8_t num, uint8_t rate)
102 4727 jcw
    : Port (num), uswait (rate)
103 4727 jcw
{
104 4727 jcw
    sdaOut(1);
105 4727 jcw
    mode2(OUTPUT);
106 4727 jcw
    sclHi();
107 4727 jcw
}
108 4727 jcw
109 4727 jcw
uint8_t PortI2C::start(uint8_t addr) const {
110 4727 jcw
    sclLo();
111 4727 jcw
    sclHi();
112 4727 jcw
    sdaOut(0);
113 4727 jcw
    return write(addr);
114 4727 jcw
}
115 4727 jcw
116 4727 jcw
void PortI2C::stop() const {
117 4727 jcw
    sdaOut(0);
118 4727 jcw
    sclHi();
119 4727 jcw
    sdaOut(1);
120 4727 jcw
}
121 4727 jcw
122 4727 jcw
uint8_t PortI2C::write(uint8_t data) const {
123 4727 jcw
    sclLo();
124 4727 jcw
    for (uint8_t mask = 0x80; mask != 0; mask >>= 1) {
125 4727 jcw
        sdaOut(data & mask);
126 4727 jcw
        sclHi();
127 4727 jcw
        sclLo();
128 4727 jcw
    }
129 4727 jcw
    sdaOut(1);
130 4727 jcw
    sclHi();
131 4727 jcw
    uint8_t ack = ! sdaIn();
132 4727 jcw
    sclLo();
133 4727 jcw
    return ack;
134 4727 jcw
}
135 4727 jcw
136 4727 jcw
uint8_t PortI2C::read(uint8_t last) const {
137 4727 jcw
    uint8_t data = 0;
138 4727 jcw
    for (uint8_t mask = 0x80; mask != 0; mask >>= 1) {
139 4727 jcw
        sclHi();
140 4727 jcw
        if (sdaIn())
141 4727 jcw
            data |= mask;
142 4727 jcw
        sclLo();
143 4727 jcw
    }
144 4727 jcw
    sdaOut(last);
145 4727 jcw
    sclHi();
146 4727 jcw
    sclLo();
147 4727 jcw
    if (last)
148 4727 jcw
        stop();
149 4727 jcw
    sdaOut(1);
150 4727 jcw
    return data;
151 4727 jcw
}
152 4727 jcw
153 4729 jcw
bool DeviceI2C::isPresent () const {
154 4729 jcw
    byte ok = send();
155 4729 jcw
    stop();
156 4729 jcw
    return ok;
157 4729 jcw
}
158 4729 jcw
159 4727 jcw
byte MilliTimer::poll(word ms) {
160 4727 jcw
    byte ready = 0;
161 4727 jcw
    if (armed) {
162 4727 jcw
        word remain = next - millis();
163 4727 jcw
        // since remain is unsigned, it will overflow to large values when
164 4727 jcw
        // the timeout is reached, so this test works as long as poll() is
165 4727 jcw
        // called no later than 5535 millisecs after the timer has expired
166 4727 jcw
        if (remain <= 60000)
167 4727 jcw
            return 0;
168 4727 jcw
        // return a value between 1 and 255, being msecs+1 past expiration
169 4727 jcw
        // note: the actual return value is only reliable if poll() is
170 4727 jcw
        // called no later than 255 millisecs after the timer has expired
171 4727 jcw
        ready = -remain;
172 4727 jcw
    }
173 4727 jcw
    set(ms);
174 4727 jcw
    return ready;
175 4727 jcw
}
176 4727 jcw
177 4727 jcw
word MilliTimer::remaining() const {
178 4727 jcw
    word remain = armed ? next - millis() : 0;
179 4727 jcw
    return remain <= 60000 ? remain : 0;
180 4727 jcw
}
181 4727 jcw
182 4727 jcw
void MilliTimer::set(word ms) {
183 4727 jcw
    armed = ms != 0;
184 4727 jcw
    if (armed)
185 4727 jcw
        next = millis() + ms - 1;
186 4727 jcw
}
187 4729 jcw
188 4729 jcw
void BlinkPlug::ledOn (byte mask) {
189 4729 jcw
    if (mask & 1) {
190 4729 jcw
        digiWrite(0);
191 4729 jcw
        mode(OUTPUT);
192 4729 jcw
    }
193 4729 jcw
    if (mask & 2) {
194 4729 jcw
        digiWrite2(0);
195 4729 jcw
        mode2(OUTPUT);
196 4729 jcw
    }
197 5961 jcw
    leds |= mask; //TODO could be read back from pins, i.s.o. saving here
198 4729 jcw
}
199 4729 jcw
200 4729 jcw
void BlinkPlug::ledOff (byte mask) {
201 4729 jcw
    if (mask & 1) {
202 4729 jcw
        mode(INPUT);
203 4729 jcw
        digiWrite(1);
204 4729 jcw
    }
205 4729 jcw
    if (mask & 2) {
206 4729 jcw
        mode2(INPUT);
207 4729 jcw
        digiWrite2(1);
208 4729 jcw
    }
209 5961 jcw
    leds &= ~ mask; //TODO could be read back from pins, i.s.o. saving here
210 4729 jcw
}
211 4729 jcw
212 4729 jcw
byte BlinkPlug::state () {
213 4729 jcw
    byte saved = leds;
214 4729 jcw
    ledOff(1+2);
215 4729 jcw
    byte result = !digiRead() | (!digiRead2() << 1);
216 4729 jcw
    ledOn(saved);
217 4729 jcw
    return result;
218 4729 jcw
}
219 4729 jcw
220 5961 jcw
//TODO deprecated, use buttonCheck() !
221 4729 jcw
byte BlinkPlug::pushed () {
222 4729 jcw
    if (debounce.idle() || debounce.poll()) {
223 4729 jcw
        byte newState = state();
224 4729 jcw
        if (newState != lastState) {
225 5961 jcw
            debounce.set(100); // don't check again for at least 100 ms
226 4729 jcw
            byte nowOn = (lastState ^ newState) & newState;
227 4729 jcw
            lastState = newState;
228 4729 jcw
            return nowOn;
229 4729 jcw
        }
230 4729 jcw
    }
231 4729 jcw
    return 0;
232 4729 jcw
}
233 4729 jcw
234 5961 jcw
byte BlinkPlug::buttonCheck () {
235 5961 jcw
    // collect button changes in the checkFlags bits, with proper debouncing
236 5961 jcw
    if (debounce.idle() || debounce.poll()) {
237 5961 jcw
        byte newState = state();
238 5961 jcw
        if (newState != lastState) {
239 5961 jcw
            debounce.set(100); // don't check again for at least 100 ms
240 5961 jcw
            if ((lastState ^ newState) & 1)
241 5961 jcw
                bitSet(checkFlags, newState & 1 ? ON1 : OFF1);
242 5961 jcw
            if ((lastState ^ newState) & 2)
243 5961 jcw
                bitSet(checkFlags, newState & 2 ? ON2 : OFF2);
244 5961 jcw
            lastState = newState;
245 5961 jcw
        }
246 5961 jcw
    }
247 5961 jcw
    // note that simultaneous button events will be returned in successive calls
248 5961 jcw
    if (checkFlags)
249 5961 jcw
        for (byte i = ON1; i <= OFF2; ++i) {
250 5961 jcw
            if (bitRead(checkFlags, i)) {
251 5961 jcw
                bitClear(checkFlags, i);
252 5961 jcw
                return i;
253 5961 jcw
            }
254 5961 jcw
        }
255 5961 jcw
    // if there are no button events, return the overall current button state
256 6089 jcw
    return lastState == 3 ? ALL_ON : lastState ? SOME_ON : ALL_OFF;
257 5961 jcw
}
258 5961 jcw
259 4729 jcw
void MemoryPlug::load (word page, void* buf, byte offset, int count) {
260 4729 jcw
    setAddress(0x50 + (page >> 8));
261 4729 jcw
    send();
262 4729 jcw
    write((byte) page);
263 4729 jcw
    write(offset);
264 4729 jcw
    receive();
265 4729 jcw
    byte* p = (byte*) buf;
266 4729 jcw
    while (--count >= 0)
267 4729 jcw
        *p++ = read(count == 0);
268 4729 jcw
    stop();
269 4729 jcw
}
270 4729 jcw
271 4729 jcw
void MemoryPlug::save (word page, const void* buf, byte offset, int count) {
272 5761 jcw
    // don't do back-to-back saves, last one must have had time to finish!
273 5761 jcw
    while (millis() < nextSave)
274 5761 jcw
        ;
275 5761 jcw
276 4729 jcw
    setAddress(0x50 + (page >> 8));
277 4729 jcw
    send();
278 4729 jcw
    write((byte) page);
279 4729 jcw
    write(offset);
280 4729 jcw
    const byte* p = (const byte*) buf;
281 4729 jcw
    while (--count >= 0)
282 4729 jcw
        write(*p++);
283 4729 jcw
    stop();
284 5761 jcw
285 5761 jcw
    nextSave = millis() + 6;
286 5761 jcw
    // delay(5);
287 4729 jcw
}
288 4729 jcw
289 4729 jcw
long MemoryStream::position (byte writing) const {
290 4729 jcw
    long v = (curr - start) * step;
291 5761 jcw
    if (pos > 0 && !writing)
292 4729 jcw
        --v; // get() advances differently than put()
293 4729 jcw
    return (v << 8) | pos;
294 4729 jcw
}
295 4729 jcw
296 4729 jcw
byte MemoryStream::get () {
297 4729 jcw
    if (pos == 0) {
298 4729 jcw
        dev.load(curr, buffer);
299 4729 jcw
        curr += step;
300 4729 jcw
    }
301 4729 jcw
    return buffer[pos++];
302 4729 jcw
}
303 4729 jcw
304 4729 jcw
void MemoryStream::put (byte data) {
305 4729 jcw
    buffer[pos++] = data;
306 4729 jcw
    if (pos == 0) {
307 4729 jcw
        dev.save(curr, buffer);
308 4729 jcw
        curr += step;
309 4729 jcw
    }
310 4729 jcw
}
311 4729 jcw
312 4729 jcw
word MemoryStream::flush () {
313 5761 jcw
    if (pos != 0) {
314 5761 jcw
        memset(buffer + pos, 0xFF, 256 - pos);
315 5761 jcw
        dev.save(curr, buffer);
316 5761 jcw
    }
317 4729 jcw
    return curr;
318 4729 jcw
}
319 4729 jcw
320 4729 jcw
void MemoryStream::reset () {
321 4729 jcw
    curr = start;
322 4729 jcw
    pos = 0;
323 4729 jcw
}
324 4747 jcw
325 4747 jcw
// uart register definitions
326 4747 jcw
#define RHR     (0 << 3)
327 4747 jcw
#define THR     (0 << 3)
328 4747 jcw
#define DLL     (0 << 3)
329 4747 jcw
#define DLH     (1 << 3)
330 4747 jcw
#define FCR     (2 << 3)
331 4747 jcw
#define LCR     (3 << 3)
332 4747 jcw
#define RXLVL   (9 << 3)
333 4747 jcw
334 4747 jcw
void UartPlug::regSet (byte reg, byte value) {
335 4747 jcw
  dev.send();
336 4747 jcw
  dev.write(reg);
337 4747 jcw
  dev.write(value);
338 4747 jcw
}
339 4747 jcw
340 4747 jcw
void UartPlug::regRead (byte reg) {
341 4747 jcw
  dev.send();
342 4747 jcw
  dev.write(reg);
343 4747 jcw
  dev.receive();
344 4747 jcw
}
345 4747 jcw
346 4747 jcw
void UartPlug::begin (long baud) {
347 4747 jcw
    word divisor = 230400 / baud;
348 4747 jcw
    regSet(LCR, 0x80);          // divisor latch enable
349 4747 jcw
    regSet(DLL, divisor);       // low byte
350 4747 jcw
    regSet(DLH, divisor >> 8);  // high byte
351 4747 jcw
    regSet(LCR, 0x03);          // 8 bits, no parity
352 4747 jcw
    regSet(FCR, 0x07);          // fifo enable (and flush)
353 4747 jcw
    dev.stop();
354 4747 jcw
}
355 4747 jcw
356 4747 jcw
byte UartPlug::available () {
357 4752 jcw
    if (in != out)
358 4752 jcw
        return 1;
359 4752 jcw
    out = 0;
360 4747 jcw
    regRead(RXLVL);
361 4752 jcw
    in = dev.read(1);
362 4752 jcw
    if (in == 0)
363 4752 jcw
        return 0;
364 4752 jcw
    if (in > sizeof rxbuf)
365 4752 jcw
        in = sizeof rxbuf;
366 4752 jcw
    regRead(RHR);
367 4752 jcw
    for (byte i = 0; i < in; ++i)
368 4752 jcw
        rxbuf[i] = dev.read(i == in - 1);
369 4752 jcw
    return 1;
370 4747 jcw
}
371 4747 jcw
372 4747 jcw
int UartPlug::read () {
373 4752 jcw
    return available() ? rxbuf[out++] : -1;
374 4747 jcw
}
375 4747 jcw
376 4747 jcw
void UartPlug::flush () {
377 4747 jcw
    regSet(FCR, 0x07); // flush both RX and TX queues
378 4747 jcw
    dev.stop();
379 4752 jcw
    in = out;
380 4747 jcw
}
381 4747 jcw
382 4747 jcw
void UartPlug::write (byte data) {
383 4747 jcw
    regSet(THR, data);
384 4747 jcw
    dev.stop();
385 4747 jcw
}
386 4881 jcw
387 7705 jcw
void DimmerPlug::begin () {
388 7705 jcw
    setReg(MODE1, 0x00);     // normal
389 7705 jcw
    setReg(MODE2, 0x14);     // inverted, totem-pole
390 7705 jcw
    setReg(GRPPWM, 0xFF);    // set group dim to max brightness
391 7705 jcw
    setMulti(LEDOUT0, 0xFF, 0xFF, 0xFF, 0xFF, -1); // all LEDs group-dimmable
392 4881 jcw
}
393 4881 jcw
394 4881 jcw
byte DimmerPlug::getReg(byte reg) const {
395 4881 jcw
    send();
396 4881 jcw
    write(reg);
397 4881 jcw
    receive();
398 4881 jcw
    byte result = read(1);
399 4881 jcw
    stop();
400 4881 jcw
    return result;
401 4881 jcw
}
402 4882 jcw
403 7705 jcw
void DimmerPlug::setReg(byte reg, byte value) const {
404 7705 jcw
    send();
405 7705 jcw
    write(reg);
406 7705 jcw
    write(value);
407 7705 jcw
    stop();
408 7705 jcw
}
409 7705 jcw
410 7705 jcw
void DimmerPlug::setMulti(byte reg, ...) const {
411 7705 jcw
    va_list ap;
412 7705 jcw
    va_start(ap, reg);
413 7705 jcw
    send();
414 7705 jcw
    write(0xE0 | reg); // auto-increment
415 7705 jcw
    for (;;) {
416 7705 jcw
        int v = va_arg(ap, int);
417 7705 jcw
        if (v < 0) break;
418 7705 jcw
        write(v);
419 7705 jcw
    }
420 7705 jcw
    stop();
421 7705 jcw
}
422 7705 jcw
423 6481 jcw
void LuxPlug::setGain(byte high) {
424 6481 jcw
    send();
425 6481 jcw
    write(0x81); // write to Timing regiser
426 6481 jcw
    write(high ? 0x12 : 0x02);
427 6481 jcw
    stop();
428 6481 jcw
}
429 6481 jcw
430 4882 jcw
const word* LuxPlug::getData() {
431 4882 jcw
    send();
432 4882 jcw
    write(0xA0 | DATA0LOW);
433 4882 jcw
    receive();
434 4882 jcw
    data.b[0] = read(0);
435 4882 jcw
    data.b[1] = read(0);
436 4882 jcw
    data.b[2] = read(0);
437 4882 jcw
    data.b[3] = read(1);
438 4882 jcw
    stop();
439 4882 jcw
    return data.w;
440 4882 jcw
}
441 4882 jcw
442 4882 jcw
#define LUX_SCALE        14        // scale by 2^14
443 4882 jcw
#define RATIO_SCALE 9        // scale ratio by 2^9
444 4882 jcw
#define CH_SCALE    10        // scale channel values by 2^10
445 4882 jcw
446 4882 jcw
word LuxPlug::calcLux(byte iGain, byte tInt) const
447 4882 jcw
{
448 4882 jcw
    unsigned long chScale;
449 4882 jcw
    switch (tInt) {
450 4882 jcw
        case 0:  chScale = 0x7517; break;
451 4882 jcw
        case 1:  chScale = 0x0fe7; break;
452 4882 jcw
        default: chScale = (1 << CH_SCALE); break;
453 4882 jcw
    }
454 4882 jcw
    if (!iGain)
455 4882 jcw
        chScale <<= 4;
456 4882 jcw
    unsigned long channel0 = (data.w[0] * chScale) >> CH_SCALE;
457 4882 jcw
    unsigned long channel1 = (data.w[1] * chScale) >> CH_SCALE;
458 4882 jcw
459 4882 jcw
    unsigned long ratio1 = 0;
460 4882 jcw
    if (channel0 != 0)
461 4882 jcw
        ratio1 = (channel1 << (RATIO_SCALE+1)) / channel0;
462 4882 jcw
    unsigned long ratio = (ratio1 + 1) >> 1;
463 4882 jcw
464 4882 jcw
    word b, m;
465 4882 jcw
         if (ratio <= 0x0040) { b = 0x01F2; m = 0x01BE; }
466 4882 jcw
    else if (ratio <= 0x0080) { b = 0x0214; m = 0x02D1; }
467 4882 jcw
    else if (ratio <= 0x00C0) { b = 0x023F; m = 0x037B; }
468 4882 jcw
    else if (ratio <= 0x0100) { b = 0x0270; m = 0x03FE; }
469 4882 jcw
    else if (ratio <= 0x0138) { b = 0x016F; m = 0x01FC; }
470 4882 jcw
    else if (ratio <= 0x019A) { b = 0x00D2; m = 0x00FB; }
471 4882 jcw
    else if (ratio <= 0x029A) { b = 0x0018; m = 0x0012; }
472 4882 jcw
    else                      { b = 0x0000; m = 0x0000; }
473 4882 jcw
474 4882 jcw
    unsigned long temp = channel0 * b - channel1 * m;
475 4882 jcw
    temp += 1 << (LUX_SCALE-1);
476 4882 jcw
    return temp >> LUX_SCALE;
477 4882 jcw
}
478 4884 jcw
479 4884 jcw
const int* GravityPlug::getAxes() {
480 4884 jcw
    send();
481 4884 jcw
    write(0x02);
482 4884 jcw
    receive();
483 4884 jcw
    for (byte i = 0; i < 5; ++i)
484 4884 jcw
        data.b[i] = read(0);
485 4884 jcw
    data.b[5] = read(1);
486 4884 jcw
    stop();
487 4884 jcw
    data.w[0] = (data.b[0] >> 6) | (data.b[1] << 2);
488 4884 jcw
    data.w[1] = (data.b[2] >> 6) | (data.b[3] << 2);
489 4884 jcw
    data.w[2] = (data.b[4] >> 6) | (data.b[5] << 2);
490 5887 jcw
    for (byte i = 0; i < 3; ++i)
491 5887 jcw
        data.w[i] = (data.w[i] ^ 0x200) - 0x200; // sign extends bit 9
492 4884 jcw
    return data.w;
493 4884 jcw
}
494 4887 jcw
495 6083 jcw
void InputPlug::select(uint8_t channel) {
496 6083 jcw
    digiWrite(0);
497 6083 jcw
    mode(OUTPUT);
498 6083 jcw
499 6083 jcw
    delayMicroseconds(slow ? 400 : 50);
500 6083 jcw
    byte data = 0x10 | (channel & 0x0F);
501 6083 jcw
    byte mask = 1 << (portNum + 3); // digitalWrite is too slow
502 6083 jcw
503 6083 jcw
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
504 6083 jcw
        for (byte i = 0; i < 5; ++i) {
505 6083 jcw
            byte us = bitRead(data, 4 - i) ? 9 : 3;
506 6083 jcw
            if (slow)
507 6083 jcw
                us <<= 3;
508 6481 jcw
#ifdef PORTD
509 6083 jcw
            PORTD |= mask;
510 6083 jcw
            delayMicroseconds(us);
511 6083 jcw
            PORTD &= ~ mask;
512 6481 jcw
#else
513 6481 jcw
            //XXX TINY!
514 6481 jcw
#endif
515 6083 jcw
            delayMicroseconds(slow ? 32 : 4);
516 6083 jcw
        }
517 6083 jcw
    }
518 6083 jcw
}
519 6083 jcw
520 6089 jcw
byte HeadingBoard::eepromByte(byte reg) const {
521 4887 jcw
    eeprom.send();
522 4887 jcw
    eeprom.write(reg);
523 4887 jcw
    eeprom.receive();
524 4887 jcw
    byte result = eeprom.read(1);
525 4887 jcw
    eeprom.stop();
526 4887 jcw
    return result;
527 4887 jcw
}
528 4887 jcw
529 6089 jcw
void HeadingBoard::getConstants() {
530 4887 jcw
    for (byte i = 0; i < 18; ++i)
531 4887 jcw
        ((byte*) &C1)[i < 14 ? i^1 : i] = eepromByte(16 + i);
532 4887 jcw
    // Serial.println(C1);
533 4887 jcw
    // Serial.println(C2);
534 4887 jcw
    // Serial.println(C3);
535 4887 jcw
    // Serial.println(C4);
536 4887 jcw
    // Serial.println(C5);
537 4887 jcw
    // Serial.println(C6);
538 4887 jcw
    // Serial.println(C7);
539 4887 jcw
    // Serial.println(A, DEC);
540 4887 jcw
    // Serial.println(B, DEC);
541 4887 jcw
    // Serial.println(C, DEC);
542 4887 jcw
    // Serial.println(D, DEC);
543 4887 jcw
}
544 4887 jcw
545 6089 jcw
word HeadingBoard::adcValue(byte press) const {
546 4887 jcw
    aux.digiWrite(1);
547 4887 jcw
    adc.send();
548 4887 jcw
    adc.write(0xFF);
549 4888 jcw
    adc.write(0xE0 | (press << 4));
550 4887 jcw
    adc.stop();
551 4887 jcw
    delay(40);
552 4887 jcw
    adc.send();
553 4887 jcw
    adc.write(0xFD);
554 4887 jcw
    adc.receive();
555 4887 jcw
    byte msb = adc.read(0);
556 4887 jcw
    int result = (msb << 8) | adc.read(1);
557 4887 jcw
    adc.stop();
558 4887 jcw
    aux.digiWrite(0);
559 4887 jcw
    return result;
560 4887 jcw
}
561 4887 jcw
562 6089 jcw
void HeadingBoard::begin() {
563 4887 jcw
    // prepare ADC
564 4887 jcw
    aux.mode(OUTPUT);
565 4887 jcw
    aux.digiWrite(0);
566 4887 jcw
567 4887 jcw
    // generate 32768 Hz on IRQ pin (OC2B)
568 6481 jcw
#ifdef TCCR2A
569 4887 jcw
    TCCR2A = bit(COM2B0) | bit(WGM21);
570 4887 jcw
    TCCR2B = bit(CS20);
571 4887 jcw
    OCR2A = 243;
572 6481 jcw
#else
573 6481 jcw
    //XXX TINY!
574 6481 jcw
#endif
575 4887 jcw
    aux.mode3(OUTPUT);
576 4887 jcw
577 4887 jcw
    getConstants();
578 4887 jcw
}
579 4887 jcw
580 6089 jcw
void HeadingBoard::pressure(int& temp, int& pres) const {
581 4887 jcw
    word D2 = adcValue(0);
582 4887 jcw
    // Serial.print("D2 = ");
583 4887 jcw
    // Serial.println(D2);
584 4887 jcw
    int corr = (D2 - C5) >> 7;
585 4887 jcw
    // Serial.print("corr = ");
586 4887 jcw
    // Serial.println(corr);
587 4887 jcw
    int dUT = (D2 - C5) - (corr * (long) corr * (D2 >= C5 ? A : B) >> C);
588 4887 jcw
    // Serial.print("dUT = ");
589 4887 jcw
    // Serial.println(dUT);
590 4888 jcw
    temp = 250 + (dUT * C6 >> 16) - (dUT >> D);
591 4888 jcw
592 4888 jcw
    word D1 = adcValue(1);
593 4888 jcw
    // Serial.print("D1 = ");
594 4888 jcw
    // Serial.println(D1);
595 4887 jcw
    word OFF = (C2 + ((C4 - 1024) * dUT >> 14)) << 2;
596 4887 jcw
    // Serial.print("OFF = ");
597 4887 jcw
    // Serial.println(OFF);
598 4887 jcw
    word SENS = C1 + (C3 * dUT >> 10);
599 4887 jcw
    // Serial.print("SENS = ");
600 4887 jcw
    // Serial.println(SENS);
601 4887 jcw
    word X = (SENS * (D1 - 7168L) >> 14) - OFF;
602 4887 jcw
    // Serial.print("X = ");
603 4887 jcw
    // Serial.println(X);
604 4887 jcw
    pres = (X * 10L >> 5) + C7;
605 4887 jcw
}
606 4888 jcw
607 6089 jcw
void HeadingBoard::heading(int& xaxis, int& yaxis) {
608 6089 jcw
    // set or reset the magnetometer coil
609 4888 jcw
    compass.send();
610 4888 jcw
    compass.write(0x00);
611 6089 jcw
    compass.write(setReset);
612 6089 jcw
    compass.stop();
613 6089 jcw
    delayMicroseconds(50);
614 6089 jcw
    setReset = 6 - setReset;
615 6089 jcw
    // perform measurement
616 6089 jcw
    compass.send();
617 6089 jcw
    compass.write(0x00);
618 4888 jcw
    compass.write(0x01);
619 4888 jcw
    compass.stop();
620 6089 jcw
    delay(5);
621 4888 jcw
    compass.send();
622 4888 jcw
    compass.write(0x00);
623 4888 jcw
    compass.receive();
624 4888 jcw
    byte tmp, reg = compass.read(0);
625 4888 jcw
    tmp = compass.read(0);
626 6089 jcw
    xaxis = ((tmp << 8) | compass.read(0)) - 2048;
627 4888 jcw
    tmp = compass.read(0);
628 6089 jcw
    yaxis = ((tmp << 8) | compass.read(1)) - 2048;
629 4888 jcw
    compass.stop();
630 4888 jcw
}
631 5346 jcw
632 6083 jcw
InfraredPlug::InfraredPlug (uint8_t num)
633 6083 jcw
        : Port (num), slot (140), gap (80), fill (-1), prev (0) {
634 5346 jcw
    digiWrite(0);
635 5346 jcw
    mode(OUTPUT);
636 6083 jcw
    mode2(INPUT);
637 6083 jcw
    digiWrite2(1); // pull-up
638 6083 jcw
}
639 5346 jcw
640 6083 jcw
void InfraredPlug::configure(uint8_t slot4, uint8_t gap256) {
641 6083 jcw
    slot = slot4;
642 6083 jcw
    gap = gap256;
643 6083 jcw
    fill = -1;
644 6083 jcw
}
645 6083 jcw
646 6083 jcw
void InfraredPlug::poll() {
647 6083 jcw
    byte bit = digiRead2(); // 0 is interpreted as pulse ON
648 6083 jcw
    if (fill < 0) {
649 6083 jcw
        if (fill < -1 || bit == 1)
650 6083 jcw
            return;
651 6083 jcw
        fill = 0;
652 6083 jcw
        prev = micros();
653 6083 jcw
        memset(buf, 0, sizeof buf);
654 6083 jcw
    }
655 6083 jcw
    // act only if the bit changed, using the low bit of the nibble fill count
656 6083 jcw
    if (bit != (fill & 1) && fill < 2 * sizeof buf) {
657 6083 jcw
        uint32_t curr = micros(), diff = (curr - prev + 2) >> 2;
658 6083 jcw
        if (diff > 65000)
659 6083 jcw
            diff = 65000; // * 4 us, i.e. 260 ms
660 6083 jcw
        // convert to a slot number, with rounding halfway between each slot
661 6083 jcw
        word ticks = ((word) diff + slot / 2) / slot;
662 6083 jcw
        if (ticks > 20)
663 6083 jcw
            ticks = 20;
664 6083 jcw
        // condense upper values to fit in the range 0..15
665 6083 jcw
        byte nibble = ticks;
666 6083 jcw
        if (nibble > 10)
667 6083 jcw
            nibble -= (nibble - 10) / 2;
668 6083 jcw
        buf[fill>>1] |= nibble << ((fill & 1) << 2);
669 6083 jcw
        ++fill;
670 6083 jcw
        prev = curr;
671 6083 jcw
    }
672 6083 jcw
}
673 6083 jcw
674 6083 jcw
uint8_t InfraredPlug::done() {
675 6083 jcw
    byte result = 0;
676 6083 jcw
    if (fill > 0)
677 6083 jcw
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
678 6083 jcw
            if (((micros() - prev) >> 8) >= gap) {
679 6083 jcw
                result = fill;
680 6083 jcw
                fill = -2; // prevent new pulses from clobbering buf
681 6083 jcw
            }
682 6083 jcw
        }
683 6083 jcw
    else if (fill < -1)
684 6083 jcw
        fill = -1; // second call to done() release buffer again for capture
685 6083 jcw
    return result;
686 6083 jcw
}
687 6168 jcw
688 6168 jcw
uint8_t InfraredPlug::decoder(uint8_t nibbles) {
689 6168 jcw
    switch (nibbles) {
690 6168 jcw
        case 67: // 2 + 64 + 1 nibbles could be a NEC packet
691 6168 jcw
            if (buf[0] == 0x8D && buf[33] == 0x01) {
692 6168 jcw
                // check that all nibbles are either 1 or 3
693 6168 jcw
                for (byte i = 1; i < 33; ++i)
694 6168 jcw
                    if ((buf[i] & ~0x20) != 0x11)
695 6168 jcw
                        return UNKNOWN;
696 6168 jcw
                // valid packet, convert in-place
697 6168 jcw
                for (byte i = 0; i < 4; ++i) {
698 6168 jcw
                    byte v;
699 6168 jcw
                    for (byte j = 0; j < 8; ++j)
700 6168 jcw
                        v = (v << 1) | (buf[1+j+8*i] >> 5);
701 6168 jcw
                    buf[i] = v;
702 6168 jcw
                }
703 6168 jcw
                return NEC;
704 6168 jcw
            }
705 6168 jcw
            break;
706 6168 jcw
        case 3: // 2 + 1 nibbles could be a NEC repeat packet
707 6168 jcw
            if (buf[0] == 0x4D && buf[1] == 0x01)
708 6168 jcw
                return NEC_REP;
709 6168 jcw
            break;
710 6168 jcw
    }
711 6168 jcw
    return UNKNOWN;
712 6168 jcw
}
713 5346 jcw
714 6173 jcw
void InfraredPlug::send(const uint8_t* data, uint16_t bits) {
715 6083 jcw
    // TODO: switch to an interrupt-driven design
716 6083 jcw
    for (byte i = 0; i < bits; ++i) {
717 6173 jcw
        digiWrite(bitRead(data[i/8], i%8));
718 6083 jcw
        delayMicroseconds(4 * slot);
719 5346 jcw
    }
720 6083 jcw
    digiWrite(0);
721 5346 jcw
}
722 5980 jcw
723 6083 jcw
void ProximityPlug::begin() {
724 6083 jcw
    delay(100);
725 6083 jcw
    setReg(CONFIG, 0x04);   // reset, STOP1
726 6083 jcw
    delay(100);
727 6083 jcw
    // setReg(TPCONFIG, 0xB5); // TPSE, BKA, ACE, TPTBE, TPE
728 6083 jcw
    setReg(TPCONFIG, 0xB1); // TPSE, BKA, ACE, TPE
729 6083 jcw
    setReg(CONFIG, 0x15);   // RUN1
730 6083 jcw
    delay(100);
731 6083 jcw
}
732 6083 jcw
733 6083 jcw
void ProximityPlug::setReg(byte reg, byte value) const {
734 6083 jcw
    send();
735 6083 jcw
    write(reg);
736 6083 jcw
    write(value);
737 6083 jcw
    stop();
738 6083 jcw
}
739 6083 jcw
740 6083 jcw
byte ProximityPlug::getReg(byte reg) const {
741 6083 jcw
    send();
742 6083 jcw
    write(reg);
743 6083 jcw
    receive();
744 6083 jcw
    byte result = read(1);
745 6083 jcw
    stop();
746 6083 jcw
    return result;
747 6083 jcw
}
748 6083 jcw
749 6065 jcw
// ISR(WDT_vect) { Sleepy::watchdogEvent(); }
750 5980 jcw
751 6065 jcw
static volatile byte watchdogCounter;
752 6065 jcw
753 5980 jcw
void Sleepy::watchdogInterrupts (char mode) {
754 5980 jcw
    // correct for the fact that WDP3 is *not* in bit position 3!
755 5980 jcw
    if (mode & bit(3))
756 5980 jcw
        mode ^= bit(3) | bit(WDP3);
757 5980 jcw
    // pre-calculate the WDTCSR value, can't do it inside the timed sequence
758 7726 jcw
    // we only generate interrupts, no reset
759 5980 jcw
    byte wdtcsr = mode >= 0 ? bit(WDIE) | mode : 0;
760 7726 jcw
    MCUSR &= ~(1<<WDRF);
761 6060 jcw
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
762 6060 jcw
        WDTCSR |= (1<<WDCE) | (1<<WDE); // timed sequence
763 6060 jcw
        WDTCSR = wdtcsr;
764 6060 jcw
    }
765 5980 jcw
}
766 5980 jcw
767 6816 jcw
void Sleepy::powerDown (byte prrOff) {
768 7377 jcw
    byte adcsraSave = ADCSRA;
769 5980 jcw
    ADCSRA &= ~ bit(ADEN); // disable the ADC
770 7377 jcw
#ifdef PRR
771 7377 jcw
    byte prrSave = PRR;
772 6816 jcw
    PRR = prrOff;
773 7377 jcw
#endif
774 5984 jcw
    // see http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
775 5984 jcw
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
776 6060 jcw
    ATOMIC_BLOCK(ATOMIC_FORCEON) {
777 7377 jcw
    sleep_enable();
778 7377 jcw
    // sleep_bod_disable(); // can't use this - not in my avr-libc version!
779 6080 jcw
#ifdef BODSE
780 7377 jcw
    MCUCR = MCUCR | bit(BODSE) | bit(BODS); // timed sequence
781 7377 jcw
    MCUCR = MCUCR & ~ bit(BODSE) | bit(BODS);
782 6080 jcw
#endif
783 6060 jcw
    }
784 5984 jcw
    sleep_cpu();
785 5984 jcw
    sleep_disable();
786 5980 jcw
    // re-enable what we disabled
787 7377 jcw
#ifdef PRR
788 5980 jcw
    PRR = prrSave;
789 7377 jcw
#endif
790 5980 jcw
    ADCSRA = adcsraSave;
791 5980 jcw
}
792 5980 jcw
793 6065 jcw
byte Sleepy::loseSomeTime (word msecs) {
794 5980 jcw
    // only slow down for periods longer than the watchdog granularity
795 5980 jcw
    while (msecs >= 16) {
796 5980 jcw
        char wdp = 0; // wdp 0..9 corresponds to roughly 16..8192 ms
797 5980 jcw
        while (msecs >= (32 << wdp) && wdp < 9)
798 5980 jcw
            ++wdp;
799 6065 jcw
        watchdogCounter = 0;
800 5980 jcw
        watchdogInterrupts(wdp);
801 5980 jcw
        powerDown();
802 5980 jcw
        watchdogInterrupts(-1); // off
803 6065 jcw
        if (watchdogCounter == 0)
804 6065 jcw
            return 0; // lost some time, but got interrupted
805 5980 jcw
        // adjust the milli ticks, since we will have missed several
806 5980 jcw
        extern volatile unsigned long timer0_millis;
807 5980 jcw
        timer0_millis += 16 << wdp;
808 5980 jcw
        msecs -= 16 << wdp;
809 5980 jcw
    }
810 6065 jcw
    return 1; // lost some time as planned
811 5980 jcw
}
812 6059 jcw
813 6065 jcw
void Sleepy::watchdogEvent() {
814 6065 jcw
    ++watchdogCounter;
815 6065 jcw
}
816 6065 jcw
817 6064 jcw
Scheduler::Scheduler (byte size) : maxTasks (size) {
818 6064 jcw
    byte bytes = size * sizeof *tasks;
819 6064 jcw
    tasks = (word*) malloc(bytes);
820 6064 jcw
    memset(tasks, 0xFF, bytes);
821 6064 jcw
}
822 6064 jcw
823 6064 jcw
Scheduler::Scheduler (word* buf, byte size) : tasks (buf), maxTasks (size) {
824 6064 jcw
    byte bytes = size * sizeof *tasks;
825 6064 jcw
    memset(tasks, 0xFF, bytes);
826 6064 jcw
}
827 6064 jcw
828 6064 jcw
char Scheduler::poll() {
829 6064 jcw
    // all times in the tasks array are relative to the "remaining" value
830 6064 jcw
    // i.e. only remaining counts down while waiting for the next timeout
831 6064 jcw
    if (remaining == 0) {
832 6064 jcw
        word lowest = ~0;
833 6064 jcw
        for (byte i = 0; i < maxTasks; ++i) {
834 6064 jcw
            if (tasks[i] == 0) {
835 6064 jcw
                tasks[i] = ~0;
836 6064 jcw
                return i;
837 6064 jcw
            }
838 6064 jcw
            if (tasks[i] < lowest)
839 6064 jcw
                lowest = tasks[i];
840 6064 jcw
        }
841 6064 jcw
        if (lowest != ~0)
842 6064 jcw
            for (byte i = 0; i < maxTasks; ++i)
843 6064 jcw
                tasks[i] -= lowest;
844 6064 jcw
        remaining = lowest;
845 6064 jcw
    } else if (ms100.poll(100))
846 6064 jcw
        --remaining;
847 6064 jcw
    return -1;
848 6064 jcw
}
849 6064 jcw
850 6064 jcw
char Scheduler::pollWaiting() {
851 6067 jcw
    // first wait until the remaining time we need to wait is less than 0.1s
852 6067 jcw
    while (remaining > 0) {
853 6072 jcw
        if (!Sleepy::loseSomeTime(100)) // approximate, actually waits 96 ms
854 6067 jcw
            return -1;
855 6067 jcw
        --remaining;
856 6067 jcw
    }
857 6067 jcw
    // now lose some more time until that 0.1s mark
858 6067 jcw
    if (!Sleepy::loseSomeTime(ms100.remaining()))
859 6067 jcw
        return -1;
860 6072 jcw
    // lastly, just ignore the 0..15 ms still left to go until the 0.1s mark
861 6064 jcw
    return poll();
862 6064 jcw
}
863 6064 jcw
864 6064 jcw
void Scheduler::timer(byte task, word tenths) {
865 6064 jcw
    // if new timer will go off sooner than the rest, then adjust all entries
866 6064 jcw
    if (tenths < remaining) {
867 6064 jcw
        word diff = remaining - tenths;
868 6064 jcw
        for (byte i = 0; i < maxTasks; ++i)
869 6064 jcw
            if (tasks[i] != ~0)
870 6064 jcw
                tasks[i] += diff;
871 6064 jcw
        remaining = tenths;
872 6064 jcw
    }
873 6064 jcw
    tasks[task] = tenths - remaining;
874 6064 jcw
}
875 6064 jcw
876 6064 jcw
void Scheduler::cancel(byte task) {
877 6064 jcw
    tasks[task] = ~0;
878 6064 jcw
}
879 6064 jcw
880 6102 jcw
#ifdef Stream_h // only available in recent Arduino IDE versions
881 6102 jcw
882 6081 jcw
InputParser::InputParser (byte* buf, byte size, Commands* ctab, Stream& stream)
883 6081 jcw
        : buffer (buf), limit (size), cmds (ctab), io (stream) {
884 6081 jcw
    reset();
885 6081 jcw
}
886 6081 jcw
887 6081 jcw
InputParser::InputParser (byte size, Commands* ctab, Stream& stream)
888 6081 jcw
        : limit (size), cmds (ctab), io (stream) {
889 6081 jcw
    buffer = (byte*) malloc(size);
890 6081 jcw
    reset();
891 6081 jcw
}
892 6081 jcw
893 6081 jcw
void InputParser::reset() {
894 6081 jcw
    fill = next = 0;
895 6081 jcw
    instring = hexmode = hasvalue = 0;
896 6081 jcw
    top = limit;
897 6081 jcw
}
898 6081 jcw
899 6081 jcw
void InputParser::poll() {
900 6081 jcw
    if (!io.available())
901 6081 jcw
        return;
902 6081 jcw
    char ch = io.read();
903 6081 jcw
    if (ch < ' ' || fill >= top) {
904 6081 jcw
        reset();
905 6081 jcw
        return;
906 6081 jcw
    }
907 6081 jcw
    if (instring) {
908 6081 jcw
        if (ch == '"') {
909 6081 jcw
            buffer[fill++] = 0;
910 6081 jcw
            do
911 6081 jcw
                buffer[--top] = buffer[--fill];
912 6081 jcw
            while (fill > value);
913 6081 jcw
            ch = top;
914 6081 jcw
            instring = 0;
915 6081 jcw
        }
916 6081 jcw
        buffer[fill++] = ch;
917 6081 jcw
        return;
918 6081 jcw
    }
919 6081 jcw
    if (hexmode && ('0' <= ch && ch <= '9' ||
920 6081 jcw
                    'A' <= ch && ch <= 'F' ||
921 6081 jcw
                    'a' <= ch && ch <= 'f')) {
922 6081 jcw
        if (!hasvalue)
923 6081 jcw
            value = 0;
924 6081 jcw
        if (ch > '9')
925 6081 jcw
            ch += 9;
926 6081 jcw
        value <<= 4;
927 6081 jcw
        value |= (byte) (ch & 0x0F);
928 6081 jcw
        hasvalue = 1;
929 6081 jcw
        return;
930 6081 jcw
    }
931 6081 jcw
    if ('0' <= ch && ch <= '9') {
932 6081 jcw
        if (!hasvalue)
933 6081 jcw
            value = 0;
934 6081 jcw
        value = 10 * value + (ch - '0');
935 6081 jcw
        hasvalue = 1;
936 6081 jcw
        return;
937 6081 jcw
    }
938 6081 jcw
    hexmode = 0;
939 6081 jcw
    switch (ch) {
940 6081 jcw
        case '$':   hexmode = 1;
941 6081 jcw
                    return;
942 6081 jcw
        case '"':   instring = 1;
943 6081 jcw
                    value = fill;
944 6081 jcw
                    return;
945 6081 jcw
        case ':':   (word&) buffer[fill] = value;
946 6081 jcw
                    fill += 2;
947 6081 jcw
                    value >>= 16;
948 6081 jcw
                    // fall through
949 6081 jcw
        case '.':   (word&) buffer[fill] = value;
950 6081 jcw
                    fill += 2;
951 6081 jcw
                    hasvalue = 0;
952 6081 jcw
                    return;
953 6081 jcw
        case '-':   value = - value;
954 6081 jcw
                    hasvalue = 0;
955 6081 jcw
                    return;
956 6081 jcw
        case ' ':   if (!hasvalue)
957 6081 jcw
                        return;
958 6081 jcw
                    // fall through
959 6081 jcw
        case ',':   buffer[fill++] = value;
960 6081 jcw
                    hasvalue = 0;
961 6081 jcw
                    return;
962 6081 jcw
    }
963 6081 jcw
    if (hasvalue) {
964 6081 jcw
        io.print("Unrecognized character: ");
965 6081 jcw
        io.print(ch);
966 6081 jcw
        io.println();
967 6081 jcw
        reset();
968 6081 jcw
        return;
969 6081 jcw
    }
970 6081 jcw
971 6081 jcw
    for (Commands* p = cmds; ; ++p) {
972 6081 jcw
        char code = pgm_read_byte(&p->code);
973 6081 jcw
        if (code == 0)
974 6081 jcw
            break;
975 6081 jcw
        if (ch == code) {
976 6081 jcw
            byte bytes = pgm_read_byte(&p->bytes);
977 6081 jcw
            if (fill < bytes) {
978 6081 jcw
                io.print("Not enough data, need ");
979 6081 jcw
                io.print((int) bytes);
980 6081 jcw
                io.println(" bytes");
981 6081 jcw
            } else {
982 6081 jcw
                memset(buffer + fill, 0, top - fill);
983 6081 jcw
                ((void (*)()) pgm_read_word(&p->fun))();
984 6081 jcw
            }
985 6081 jcw
            reset();
986 6081 jcw
            return;
987 6081 jcw
        }
988 6081 jcw
    }
989 6081 jcw
990 6081 jcw
    io.print("Known commands:");
991 6081 jcw
    for (Commands* p = cmds; ; ++p) {
992 6081 jcw
        char code = pgm_read_byte(&p->code);
993 6081 jcw
        if (code == 0)
994 6081 jcw
            break;
995 6081 jcw
        io.print(' ');
996 6081 jcw
        io.print(code);
997 6081 jcw
    }
998 6081 jcw
    io.println();
999 6081 jcw
}
1000 6081 jcw
1001 6081 jcw
InputParser& InputParser::get(void* ptr, byte len) {
1002 6081 jcw
    memcpy(ptr, buffer + next, len);
1003 6081 jcw
    next += len;
1004 6081 jcw
    return *this;
1005 6081 jcw
}
1006 6081 jcw
1007 6081 jcw
InputParser& InputParser::operator >> (const char*& v) {
1008 6081 jcw
    byte offset = buffer[next++];
1009 6081 jcw
    v = top <= offset && offset < limit ? (char*) buffer + offset : "";
1010 6081 jcw
    return *this;
1011 6081 jcw
}
1012 6102 jcw
1013 6102 jcw
#endif // Stream_h