Switch from GPLv2 to GPLv2+
[fw/altos] / src / kernel / ao_log_micro.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
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 2 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, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <ao.h>
20 #include <ao_micropeak.h>
21 #include <ao_log_micro.h>
22 #include <ao_async.h>
23
24 static uint16_t ao_log_offset = STARTING_LOG_OFFSET;
25
26 #define AO_LOG_ID_SHIFT 12
27 #define AO_LOG_ID_MASK  ((1 << AO_LOG_ID_SHIFT) - 1)
28
29 void
30 ao_log_micro_save(void)
31 {
32         uint16_t        n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t);
33
34 #if AO_LOG_ID
35         n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT;
36 #endif
37         ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground));
38         ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min));
39         ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
40 }
41
42 void
43 ao_log_micro_restore(void)
44 {
45         ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground));
46         ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min));
47 }
48
49 void
50 ao_log_micro_data(void)
51 {
52         uint16_t        low_bits = pa;
53
54         if (ao_log_offset < MAX_LOG_OFFSET) {
55                 ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits));
56                 ao_log_offset += sizeof (low_bits);
57         }
58 }
59
60 #define POLY 0x8408
61
62 static uint16_t
63 ao_log_micro_crc(uint16_t crc, uint8_t byte)
64 {
65         uint8_t i;
66
67         for (i = 0; i < 8; i++) {
68                 if ((crc & 0x0001) ^ (byte & 0x0001))
69                         crc = (crc >> 1) ^ POLY;
70                 else
71                         crc = crc >> 1;
72                 byte >>= 1;
73         }
74         return crc;
75 }
76
77 static void
78 ao_log_hex_nibble(uint8_t b)
79 {
80         if (b < 10)
81                 ao_async_byte('0' + b);
82         else
83                 ao_async_byte('a' - 10 + b);
84 }
85
86 static void
87 ao_log_hex(uint8_t b)
88 {
89         ao_log_hex_nibble(b>>4);
90         ao_log_hex_nibble(b&0xf);
91 }
92
93 static void
94 ao_log_newline(void)
95 {
96         ao_async_byte('\r');
97         ao_async_byte('\n');
98 }
99
100 void
101 ao_log_micro_dump(void)
102 {
103         uint16_t        n_samples;
104         uint16_t        nbytes;
105         uint8_t         byte;
106         uint16_t        b;
107         uint16_t        crc = 0xffff;
108
109         ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));
110
111         if (n_samples == 0xffff)
112                 n_samples = 0;
113 #if AO_LOG_ID
114         n_samples &= AO_LOG_ID_MASK;
115 #endif
116         nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;
117         ao_async_start();
118         ao_async_byte('M');
119         ao_async_byte('P');
120         for (b = 0; b < nbytes; b++) {
121                 if ((b & 0xf) == 0)
122                         ao_log_newline();
123                 ao_eeprom_read(b, &byte, 1);
124                 ao_log_hex(byte);
125                 crc = ao_log_micro_crc(crc, byte);
126         }
127         ao_log_newline();
128         crc = ~crc;
129         ao_log_hex(crc >> 8);
130         ao_log_hex(crc);
131         ao_log_newline();
132         ao_async_stop();
133 }