2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
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.
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.
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.
22 #include <ao_seven_segment.h>
23 #include <ao_quadrature.h>
24 #include <ao_radio_cmac.h>
25 #include <ao_adc_single.h>
27 #define AO_LCO_PAD_DIGIT 0
28 #define AO_LCO_BOX_DIGIT_1 1
29 #define AO_LCO_BOX_DIGIT_10 2
31 #define AO_LCO_DRAG_RACE_START_TIME AO_SEC_TO_TICKS(5)
32 #define AO_LCO_DRAG_RACE_STOP_TIME AO_SEC_TO_TICKS(2)
35 static uint8_t ao_lco_select_mode;
36 static uint8_t ao_lco_event_debug;
38 #define PRINTE(...) do { if (!ao_lco_debug && !ao_lco_event_debug) break; printf ("\r%5lu %s: ", (unsigned long) ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
39 #define AO_LCO_SELECT_PAD 0
40 #define AO_LCO_SELECT_BOX 1
42 static uint8_t ao_lco_display_mutex;
45 ao_lco_show_pad(int8_t pad)
47 ao_mutex_get(&ao_lco_display_mutex);
48 ao_seven_segment_set(AO_LCO_PAD_DIGIT, (uint8_t) (pad | (ao_lco_drag_race << 4)));
49 ao_mutex_put(&ao_lco_display_mutex);
52 #define SEVEN_SEGMENT_d ((0 << 0) | \
61 #define SEVEN_SEGMENT_r ((0 << 0) | \
70 ao_lco_show_box(int16_t box)
72 ao_mutex_get(&ao_lco_display_mutex);
73 ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, (uint8_t) (box % 10 | (ao_lco_drag_race << 4)));
74 ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, (uint8_t) (box / 10 | (ao_lco_drag_race << 4)));
75 ao_mutex_put(&ao_lco_display_mutex);
79 ao_lco_show_value(uint16_t value, uint8_t point)
81 uint8_t hundreds, tens, ones;
83 PRINTD("value %d\n", value);
84 ones = (uint8_t) (value % 10);
85 tens = (uint8_t) ((value / 10) % 10);
86 hundreds = (uint8_t) ((value / 100) % 10);
100 ao_mutex_get(&ao_lco_display_mutex);
101 ao_seven_segment_set(AO_LCO_PAD_DIGIT, ones);
102 ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, tens);
103 ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, hundreds);
104 ao_mutex_put(&ao_lco_display_mutex);
108 ao_lco_show_lco_voltage(void)
110 struct ao_adc packet;
113 ao_adc_single_get(&packet);
114 decivolt = ao_battery_decivolt(packet.v_batt);
115 ao_lco_show_value((uint16_t) decivolt, 1);
121 switch (ao_lco_box) {
122 case AO_LCO_LCO_VOLTAGE:
123 ao_lco_show_lco_voltage();
126 switch (ao_lco_pad) {
127 case AO_LCO_PAD_VOLTAGE:
128 ao_lco_show_value(ao_pad_query.battery, 1);
130 case AO_LCO_PAD_RSSI:
131 if (!(ao_lco_valid[ao_lco_box] & AO_LCO_VALID_LAST))
132 ao_lco_show_value(888, 0);
134 ao_lco_show_value((uint16_t) (-ao_radio_cmac_rssi), 0);
137 ao_lco_show_pad(ao_lco_pad);
138 ao_lco_show_box(ao_lco_box);
145 ao_lco_set_select(void)
148 ao_led_off(AO_LED_PAD);
149 ao_led_off(AO_LED_BOX);
151 switch (ao_lco_select_mode) {
152 case AO_LCO_SELECT_PAD:
153 ao_led_off(AO_LED_BOX);
154 ao_led_on(AO_LED_PAD);
156 case AO_LCO_SELECT_BOX:
157 ao_led_off(AO_LED_PAD);
158 ao_led_on(AO_LED_BOX);
166 static struct ao_task ao_lco_drag_task;
169 ao_lco_drag_monitor(void)
171 AO_TICK_TYPE delay = ~0UL;
174 ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
176 PRINTD("Drag monitor count %d delay %lu\n", ao_lco_drag_beep_count, (unsigned long) delay);
177 if (delay == (AO_TICK_TYPE) ~0)
178 ao_sleep(&ao_lco_drag_beep_count);
180 ao_sleep_for(&ao_lco_drag_beep_count, delay);
184 delay = ao_lco_drag_warn_check(now, delay);
185 delay = ao_lco_drag_beep_check(now, delay);
192 static struct ao_event event;
195 ao_event_get(&event);
196 PRINTE("event type %d unit %d value %ld\n",
197 event.type, event.unit, (long) event.value);
198 switch (event.type) {
199 case AO_EVENT_QUADRATURE:
200 switch (event.unit) {
201 case AO_QUADRATURE_SELECT:
203 switch (ao_lco_select_mode) {
204 case AO_LCO_SELECT_PAD:
205 ao_lco_step_pad((int8_t) event.value);
207 case AO_LCO_SELECT_BOX:
208 ao_lco_step_box((int8_t) event.value);
217 case AO_EVENT_BUTTON:
218 switch (event.unit) {
220 ao_lco_set_armed((uint8_t) event.value);
225 ao_lco_set_firing((uint8_t) event.value);
227 case AO_BUTTON_DRAG_SELECT:
229 ao_lco_toggle_drag();
231 case AO_BUTTON_DRAG_MODE:
233 ao_lco_drag_enable();
235 ao_lco_drag_disable();
237 case AO_BUTTON_ENCODER_SELECT:
240 ao_lco_select_mode = 1 - ao_lco_select_mode;
252 * Light up everything for a second at power on to let the user
253 * visually inspect the system for correct operation
256 ao_lco_display_test(void)
258 ao_mutex_get(&ao_lco_display_mutex);
259 ao_seven_segment_set(AO_LCO_PAD_DIGIT, 8 | 0x10);
260 ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, 8 | 0x10);
261 ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 8 | 0x10);
262 ao_mutex_put(&ao_lco_display_mutex);
263 ao_led_on(AO_LEDS_AVAILABLE);
264 ao_delay(AO_MS_TO_TICKS(1000));
265 ao_led_off(AO_LEDS_AVAILABLE);
269 ao_lco_batt_voltage(void)
271 ao_lco_show_lco_voltage();
272 ao_delay(AO_MS_TO_TICKS(1000));
275 static struct ao_task ao_lco_input_task;
276 static struct ao_task ao_lco_monitor_task;
277 static struct ao_task ao_lco_arm_warn_task;
278 static struct ao_task ao_lco_igniter_status_task;
283 ao_lco_display_test();
284 ao_lco_batt_voltage();
286 ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
287 ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
288 ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
289 ao_add_task(&ao_lco_drag_task, ao_lco_drag_monitor, "drag race");
295 ao_lco_set_debug(void)
297 uint32_t r = ao_cmd_decimal();
298 if (ao_cmd_status == ao_cmd_success){
299 ao_lco_debug = r & 1;
300 ao_lco_event_debug = (r & 2) >> 1;
304 const struct ao_cmds ao_lco_cmds[] = {
305 { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" },
306 { ao_lco_search, "s\0Search for pad boxes" },
307 { ao_lco_pretend, "p\0Pretend there are lots of pad boxes" },
315 ao_add_task(&ao_lco_monitor_task, ao_lco_main, "lco monitor");
317 ao_cmd_register(&ao_lco_cmds[0]);