3 #include <drv/lcd_rit128x96.h>
6 #include <drv/flash_lm3s.h>
16 #include <gfx/gfx_p.h> /* BM_PLOT() */
24 #define KEY_MASK (K_UP | K_DOWN | K_LEFT | K_RIGHT | K_OK)
25 extern Font font_gohu;
26 static uint8_t raster[RAST_SIZE(LCD_WIDTH, LCD_HEIGHT)];
27 static Bitmap lcd_bitmap;
29 #define SCRSVR_TIME 60000
30 static ticks_t scrsvr_timestamp;
31 static bool is_lcd_off;
33 /* Serial and NMEA stuff */
34 static Serial ser_port;
35 static nmeap_context_t nmea;
39 static bool nmea_update;
43 static long target_lat, target_lon;
46 #define GPS_POS_MAGIC 0xdeadbeef
47 static FlashLM3S flash;
49 static void flash_load_target(void)
53 kfile_seek(&flash.fd, -FLASH_PAGE_SIZE_BYTES, KSM_SEEK_END);
54 kfile_read(&flash.fd, &magic, sizeof(magic));
55 if (magic == GPS_POS_MAGIC)
57 kfile_read(&flash.fd, &target_lat, sizeof(target_lat));
58 kfile_read(&flash.fd, &target_lon, sizeof(target_lon));
62 static void flash_save_target(void)
64 const uint32_t magic = GPS_POS_MAGIC;
66 kfile_seek(&flash.fd, -FLASH_PAGE_SIZE_BYTES, KSM_SEEK_END);
67 kfile_write(&flash.fd, &magic, sizeof(magic));
68 kfile_write(&flash.fd, &target_lat, sizeof(target_lat));
69 kfile_write(&flash.fd, &target_lon, sizeof(target_lon));
70 kfile_flush(&flash.fd);
73 /* Status LED management */
74 static void led_init(void)
76 SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOG;
78 GPIO_PORTG_DIR_R = 0x04;
79 GPIO_PORTG_DEN_R = 0x04;
82 INLINE void led_on(void)
84 GPIO_PORTG_DATA_R |= 0x04;
87 INLINE void led_off(void)
89 GPIO_PORTG_DATA_R &= ~0x04;
92 /* Display management */
93 INLINE void video_off(void)
96 (long)ticks_to_ms(timer_clock_unlocked()) -
97 (long)scrsvr_timestamp;
99 if (!is_lcd_off && delta > SCRSVR_TIME)
106 INLINE void video_on(void)
113 scrsvr_timestamp = ticks_to_ms(timer_clock_unlocked());
116 INLINE void repaint(Bitmap *bm)
118 rit128x96_blitBitmap(bm);
121 INLINE keymask_t keypad_peek(void)
123 keymask_t key = kbd_peek();
134 /* Status LED thread */
135 static void NORETURN led_process(void)
153 static void nmea_callback(nmeap_context_t *context, void *data, void *user_data)
159 lat = (long)gga.latitude;
160 lon = (long)gga.longitude;
165 static void NORETURN ser_process(void)
169 nmea_poll(&nmea, &ser_port.fd);
170 kfile_clearerr(&ser_port.fd);
174 /* Target position screen */
175 static void target(Bitmap *bm)
177 const long STEP = 10000000,
178 MAX_LAT = 90000000, MIN_LAT = -90000000,
179 MAX_LON = 180000000, MIN_LON = -180000000;
180 long step = STEP, target;
181 int row = 0, pos = 1;
186 text_xprintf(bm, 0, 0,
187 STYLEF_UNDERLINE | TEXT_CENTER | TEXT_FILL,
193 text_xprintf(bm, 3, 0, TEXT_FILL,
194 "Lat: %02ld.%06ld %c %s",
195 ABS(target_lat) / 1000000L,
196 ABS(target_lat) % 1000000,
197 target_lat >= 0 ? 'N' : 'S',
198 row == 0 ? "<-" : "");
199 text_xprintf(bm, row ? 4 : 6, 0,
200 TEXT_FILL | TEXT_CENTER, " ");
201 text_xprintf(bm, row ? 6 : 4, 0,
204 pos + 7 : pos + 6, '^');
205 text_xprintf(bm, 5, 0, TEXT_FILL,
206 "Lon: %03ld.%06ld %c %s",
207 ABS(target_lon) / 1000000L,
208 ABS(target_lon) % 1000000L,
209 target_lon >= 0 ? 'E' : 'W',
210 row == 1 ? "<-" : "");
218 target = target_lat + step;
219 if (target <= MAX_LAT)
221 if (target_lat < 0 && target > 0)
222 target_lat = ABS(target_lat) +
230 target = target_lon + step;
231 if (target <= MAX_LON)
233 if (target_lon < 0 && target > 0)
234 target_lon = ABS(target_lon) +
241 else if (key & K_DOWN)
245 target = target_lat - step;
246 if (target >= MIN_LAT)
248 if (target_lat > 0 && target < 0)
249 target_lat = -ABS(target_lat) -
257 target = target_lon - step;
258 if (target >= MIN_LON)
260 if (target_lon > 0 && target < 0)
261 target_lon = -ABS(target_lon) -
268 else if (key & K_LEFT)
276 else if (key & K_RIGHT)
288 /* Move to longigude */
295 /* Compass management */
296 static void draw_compass(Bitmap *bm)
298 const int R = LCD_HEIGHT / 3, R_SMALL = 10;
299 long x, y, x1, y1, x2, y2, d;
302 d = distance(lat / 1E6, lon / 1E6, target_lat / 1E6, target_lon / 1E6);
304 x = (long)((float)R * (1 + sin(deg2rad((float)prev_b))));
305 y = (long)((float)R * (1 - cos(deg2rad((float)prev_b))));
307 x1 = R - R_SMALL + (long)((float)R_SMALL *
308 (1 + sin(deg2rad((float)prev_b - 120.0))));
309 y1 = R - R_SMALL + (long)((float)R_SMALL *
310 (1 - cos(deg2rad((float)prev_b - 120.0))));
311 x2 = R - R_SMALL + (long)((float)R_SMALL *
312 (1 + sin(deg2rad((float)prev_b + 120.0))));
313 y2 = R - R_SMALL + (long)((float)R_SMALL *
314 (1 - cos(deg2rad((float)prev_b + 120.0))));
317 /* Print direction heading and degrees */
318 text_xprintf(bm, 0, 5, 0, "%s", "N");
319 text_xprintf(bm, 0, 0, TEXT_RIGHT, "%s", compass_heading(prev_b));
320 text_xprintf(bm, 1, 0, TEXT_RIGHT, "%ld deg.", prev_b);
322 text_xprintf(bm, 2, 0, TEXT_RIGHT, "%ld %s",
323 d >= 1000 ? d / 1000 : d,
324 d >= 1000 ? "Km" : "m");
325 /* Print current and target position */
326 text_xprintf(bm, 6, 0, TEXT_FILL, "%02ld.%06ld%c%03ld.%06ld%c",
329 lat >= 0 ? 'N' : 'S',
332 lon >= 0 ? 'E' : 'W');
333 text_xprintf(bm, 7, 0, TEXT_FILL, "%02ld.%06ld%c%03ld.%06ld%c",
334 ABS(target_lat) / 1000000L,
335 ABS(target_lat) % 1000000,
336 target_lat >= 0 ? 'N' : 'S',
337 ABS(target_lon) / 1000000L,
338 ABS(target_lon) % 1000000L,
339 target_lon >= 0 ? 'E' : 'W');
340 /* Draw the circle */
341 for (i = 0; i < 360; i++)
343 (long)((float)R * (1 + sin(deg2rad((float)i)))),
344 (long)((float)R * (1 - cos(deg2rad((float)i)))));
345 /* Draw the needle */
346 gfx_rectFill(bm, R - 2, R - 2, R + 2, R + 2);
347 gfx_line(bm, R, R, x1, y1);
348 gfx_line(bm, R, R, x2, y2);
349 gfx_line(bm, x1, y1, x, y);
350 gfx_line(bm, x2, y2, x, y);
355 static void compass(Bitmap *bm)
364 b = bearing(lat / 1E6, lon / 1E6,
365 target_lat / 1E6, target_lon / 1E6);
366 inc = ABS(b - prev_b) < 360 - ABS(b - prev_b) ? 1 : -1;
367 /* Compass animation */
372 prev_b = (prev_b + inc) % 360;
377 if (keypad_peek() & KEY_MASK)
383 if (keypad_peek() & KEY_MASK)
388 /* GPS receiver status */
389 static const char *gps_fix[] =
402 static void gps_data(Bitmap *bm)
415 text_xprintf(bm, 3, 0,
416 TEXT_CENTER | TEXT_FILL, "No GPS data");
420 gmtime_r(&rmc.time, &tm);
422 text_xprintf(bm, 0, 0, TEXT_FILL,
426 lat >= 0 ? 'N' : 'S');
427 text_xprintf(bm, 1, 0, TEXT_FILL,
431 lon >= 0 ? 'E' : 'W');
432 text_xprintf(bm, 2, 0, TEXT_FILL,
433 "Alt. %d", gga.altitude);
434 text_xprintf(bm, 3, 0, TEXT_FILL,
435 "Speed: %d", vtg.km_speed);
436 if (gga.quality < countof(gps_fix))
437 text_xprintf(bm, 4, 0, TEXT_FILL,
439 gps_fix[gga.quality]);
441 text_xprintf(bm, 4, 0, TEXT_FILL,
442 "Fix: %d", gga.quality);
443 text_xprintf(bm, 5, 0, TEXT_FILL,
446 strftime(buf, sizeof(buf),
447 "Date: %Y-%m-%d %a", &tm);
448 text_xprintf(bm, 6, 0, TEXT_FILL, "%s", buf);
449 strftime(buf, sizeof(buf),
450 "Time: %H:%M:%S (UTC)", &tm);
451 text_xprintf(bm, 7, 0, TEXT_FILL, "%s", buf);
455 if (keypad_peek() & KEY_MASK)
462 static void about(Bitmap *bm)
466 text_xprintf(bm, 7, 0,
467 STYLEF_UNDERLINE | TEXT_CENTER | TEXT_FILL,
468 "http://www.bertos.org");
472 const uint8_t *p = &logo[BITMAP_HEADER_SIZE];
473 uint8_t h = logo[BITMAP_HEIGHT_OFFSET];
474 uint8_t w = logo[BITMAP_WIDTH_OFFSET];
477 for (r = 0; r < h; r++)
480 (128 - w) / 2, 70 - r, w, 1);
484 while (!(keypad_peek() & KEY_MASK))
488 static struct MenuItem main_items[] =
490 {(const_iptr_t)"Target", 0, (MenuHook)target, (iptr_t)&lcd_bitmap},
491 {(const_iptr_t)"Compass", 0, (MenuHook)compass, (iptr_t)&lcd_bitmap},
492 {(const_iptr_t)"GPS data", 0, (MenuHook)gps_data, (iptr_t)&lcd_bitmap},
493 {(const_iptr_t)"About...", 0, (MenuHook)about, (iptr_t)&lcd_bitmap},
494 {(const_iptr_t)0, 0, NULL, (iptr_t)NULL}
497 static struct Menu main_menu =
499 main_items, "DevelGPS v0.1", MF_STICKY | MF_SAVESEL, &lcd_bitmap, 0
502 static void init(void)
510 scrsvr_timestamp = ticks_to_ms(timer_clock_unlocked());
513 flash_lm3sInit(&flash);
516 ser_init(&ser_port, SER_UART1);
517 ser_setbaudrate(&ser_port, 38400);
519 nmeap_init(&nmea, NULL);
520 nmeap_addParser(&nmea, "GPGGA", nmea_gpgga, nmea_callback, &gga);
521 nmeap_addParser(&nmea, "GPRMC", nmea_gprmc, nmea_callback, &rmc);
522 nmeap_addParser(&nmea, "GPVTG", nmea_gpvtg, nmea_callback, &vtg);
525 gfx_bitmapInit(&lcd_bitmap, raster, LCD_WIDTH, LCD_HEIGHT);
526 gfx_setFont(&lcd_bitmap, &font_gohu);
527 repaint(&lcd_bitmap);
536 proc_new(led_process, NULL, KERN_MINSTACKSIZE * 2, NULL);
537 proc_new(ser_process, NULL, KERN_MINSTACKSIZE * 2, NULL);
541 iptr_t res = menu_handle(&main_menu);
542 if (res != MENU_TIMEOUT)