altos/telelco-v3.0: Add contrast setting
[fw/altos] / src / telelco-v3.0 / ao_telelco.c
1 /*
2  * Copyright © 2011 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_exti.h>
21 #include <ao_packet.h>
22 #include <ao_companion.h>
23 #include <ao_aes.h>
24 #include <ao_quadrature.h>
25 #include <ao_button.h>
26 #include <ao_lco.h>
27 #include <ao_lco_cmd.h>
28 #include <ao_radio_cmac_cmd.h>
29 #include <ao_eeprom.h>
30 #include <ao_adc_single.h>
31 #include <ao_st7565.h>
32
33 #define WIDTH   AO_ST7565_WIDTH
34 #define HEIGHT  AO_ST7565_HEIGHT
35 #define STRIDE  AO_BITMAP_STRIDE(WIDTH)
36
37 static uint32_t image[STRIDE * HEIGHT];
38
39 static struct ao_bitmap fb = {
40         .base = image,
41         .stride = STRIDE,
42         .width = WIDTH,
43         .height = HEIGHT,
44         .damage = AO_BOX_INIT,
45 };
46
47 static void
48 ao_st7565_test(void)
49 {
50         ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
51         ao_st7565_update(&fb);
52         ao_text(&fb, &BitstreamVeraSans_Roman_24_font,
53                 0, 20, "hello world", AO_BLACK, AO_COPY);
54         ao_st7565_update(&fb);
55 }
56
57 static int16_t  x1 = 32, _y1 = 10, x2 = 32, y2 = 40;
58 static int16_t  dx1 = 2, dy1 = 2, dx2 = -2, dy2 = -1;
59
60 #define bounds(v,m,M,d) \
61                 if (v < m) {                    \
62                         v = m + m - v;          \
63                         d = -d;                 \
64                 } else if (v > M) {             \
65                         v = M - (v - M);        \
66                         d = -d;                 \
67                 }
68
69 static void
70 ao_st7565_line(void)
71 {
72         int     i;
73
74         for (i = 0; i < 100; i++) {
75                 ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
76                 ao_line(&fb, x1, _y1, x2, y2, AO_BLACK, AO_COPY);
77                 ao_st7565_update(&fb);
78                 x1 += dx1;
79                 _y1 += dy1;
80                 x2 += dx2;
81                 y2 += dy2;
82                 printf("%d,%d - %d,%d\n", x1, _y1, x2, y2);
83                 fflush(stdout);
84                 bounds(x1, 0, WIDTH, dx1);
85                 bounds(x2, 0, WIDTH, dx2);
86                 bounds(_y1, 0, HEIGHT, dy1);
87                 bounds(y2, 0, HEIGHT, dy2);
88                 ao_delay(AO_MS_TO_TICKS(200));
89         }
90 }
91
92 static const float pad_volts = 12.3f;
93 static const float lco_volts = 4.1f;
94 static const int rssi = -30;
95
96 static int      boxes[] = { 1, 2, 3, 5, 8, 11, 13, 17, 19, 23, 29, 31, 37, 62, 97 };
97
98 //static int    max_box = 97;
99
100 #define ARRAYSIZE(a)    (sizeof(a) / sizeof((a)[0]))
101
102 static bool
103 valid_box(int box)
104 {
105         size_t i;
106         if (box == 0)
107                 return true;
108         for (i = 0; i < ARRAYSIZE(boxes); i++)
109                 if (boxes[i] == box)
110                         return true;
111         return false;
112 }
113
114 #if 0
115 static void
116 next_box(void)
117 {
118         for (int n = box_number + 1; n <= max_box; n++)
119                 if (valid_box(n)) {
120                         box_number = n;
121                         return;
122                 }
123         box_number = 0;
124 }
125
126 static void
127 prev_box(void)
128 {
129         for (int n = box_number - 1; n >= 0; n--)
130                 if (valid_box(n)) {
131                         box_number = n;
132                         return;
133                 }
134         box_number = max_box;
135 }
136 #endif
137
138 static const struct ao_transform logo_transform = {
139         .x_scale = 48, .x_off = 2,
140         .y_scale = 48, .y_off = 0,
141 };
142
143 #define BIG_FONT BitstreamVeraSans_Roman_58_font
144 #define VOLT_FONT BitstreamVeraSans_Roman_58_font
145 #define SMALL_FONT BitstreamVeraSans_Roman_12_font
146 #define TINY_FONT BitstreamVeraSans_Roman_10_font
147 #define LOGO_FONT BenguiatGothicStd_Bold_26_font
148
149 #define LABEL_Y         (int16_t) (SMALL_FONT.ascent)
150 #define VALUE_Y         (int16_t) (LABEL_Y + BIG_FONT.ascent + 5)
151 #define BOX_X           2
152 #define PAD_X           90
153 #define BOX_LABEL_X     30
154 #define VOLT_LABEL_X    25
155 #define RSSI_LABEL_X    15
156 #define PAD_LABEL_X     95
157 #define SEP_X           (PAD_X - 8)
158 #define SCAN_X          (WIDTH - 100) / 2
159 #define SCAN_Y          50
160 #define SCAN_HEIGHT     3
161 #define FOUND_Y         63
162 #define FOUND_X         6
163 #define FOUND_WIDTH     17
164 #define MAX_VALID       (WIDTH / FOUND_WIDTH)
165
166 static int16_t  box_number = 88;
167 static int16_t  pad_number = 8;
168
169 static void
170 ao_st7565_poly(void)
171 {
172         int16_t scan_number;
173         char    str[8];
174         int     i;
175         int     v;
176         int     last_box;
177         int16_t b;
178
179         for (scan_number = 0; scan_number < 100; scan_number++) {
180                 ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
181                 ao_logo(&fb, &logo_transform, &LOGO_FONT, AO_BLACK, AO_COPY);
182                 if (scan_number) {
183                         ao_rect(&fb, SCAN_X, SCAN_Y, (int16_t) scan_number, SCAN_HEIGHT, AO_BLACK, AO_COPY);
184                         b = 0;
185                         v = 0;
186                         last_box = 0;
187                         for (i = scan_number; i > 1; i--) {
188                                 if (valid_box(i)) {
189                                         if (!last_box)
190                                                 last_box = i;
191                                         v++;
192                                         if (v == MAX_VALID)
193                                                 break;
194                                 }
195                         }
196                         for (; i <= scan_number; i++) {
197                                 if (valid_box(i)) {
198                                         sprintf(str, "%02d%s", i, i == last_box ? "" : ",");
199                                         ao_text(&fb, &TINY_FONT, (int16_t) (FOUND_X + FOUND_WIDTH * b),
200                                                 FOUND_Y, str, AO_BLACK, AO_COPY);
201                                         b++;
202                                 }
203                         }
204                 }
205                 ao_st7565_update(&fb);
206                 ao_delay(AO_MS_TO_TICKS(50));
207         }
208         ao_rect(&fb, 0, 0, WIDTH, HEIGHT, AO_WHITE, AO_COPY);
209         switch (box_number) {
210         case 0:
211                 sprintf(str, "%4.1f", lco_volts);
212                 ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
213                 ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "LCO Battery", AO_BLACK, AO_COPY);
214                 break;
215         default:
216                 switch (pad_number) {
217                 case -1:
218                         sprintf(str, "%4.1f", pad_volts);
219                         ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
220                         ao_text(&fb, &SMALL_FONT, VOLT_LABEL_X, LABEL_Y, "Pad Battery", AO_BLACK, AO_COPY);
221                         break;
222                 case 0:
223                         sprintf(str, "%4d", rssi);
224                         ao_text(&fb, &VOLT_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
225                         ao_text(&fb, &SMALL_FONT, RSSI_LABEL_X, LABEL_Y, "Signal Strength", AO_BLACK, AO_COPY);
226                         break;
227                 default:
228                         sprintf(str, "%02d", box_number);
229                         ao_text(&fb, &BIG_FONT, BOX_X, VALUE_Y, str, AO_BLACK, AO_COPY);
230                         ao_text(&fb, &SMALL_FONT, BOX_LABEL_X, LABEL_Y, "Box", AO_BLACK, AO_COPY);
231
232                         sprintf(str, "%d", pad_number);
233                         ao_text(&fb, &BIG_FONT, PAD_X, VALUE_Y, str, AO_BLACK, AO_COPY);
234                         ao_text(&fb, &SMALL_FONT, PAD_LABEL_X, LABEL_Y, "Pad", AO_BLACK, AO_COPY);
235
236                         ao_rect(&fb, SEP_X, 0, 2, HEIGHT, AO_BLACK, AO_COPY);
237                 }
238                 break;
239         }
240         ao_st7565_update(&fb);
241 }
242
243 const struct ao_cmds ao_st7565_cmds[] = {
244         { ao_st7565_test, "g\0Test ST7565 display" },
245         { ao_st7565_line, "l\0Draw lines" },
246         { ao_st7565_poly, "p\0Draw polygon" },
247         { 0, NULL },
248 };
249
250 int
251 main(void)
252 {
253         ao_clock_init();
254
255         ao_led_init();
256         ao_led_on(LEDS_AVAILABLE);
257         ao_task_init();
258
259         ao_timer_init();
260
261         ao_spi_init();
262         ao_dma_init();
263         ao_exti_init();
264         ao_adc_single_init();
265
266         ao_beep_init();
267         ao_cmd_init();
268
269         ao_quadrature_init();
270         ao_button_init();
271
272         ao_radio_init();
273
274         ao_usb_init();
275
276         ao_st7565_init();
277
278         ao_config_init();
279
280         ao_lco_init();
281         ao_lco_cmd_init();
282
283 //      ao_cmd_register(ao_st7565_cmds);
284
285         ao_led_off(LEDS_AVAILABLE);
286
287         ao_start_scheduler();
288         return 0;
289 }