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