/** * \brief Draw or delete indicator arrow in front of spinner * * \param *spinner initialized gfx_mono_spinctrl struct * \param draw true on draw, false on delete */ static void gfx_mono_spinctrl_draw_indicator(struct gfx_mono_spinctrl *spinner, bool draw) { if (draw) { gfx_mono_put_bitmap(&gfx_mono_spinctrl_bitmap_indicator, 0, spinner->y); } else { gfx_mono_draw_filled_rect(0, spinner->y, GFX_MONO_SPINCTRL_INDICATOR_WIDTH, GFX_MONO_SPINCTRL_INDICATOR_HEIGHT, GFX_PIXEL_CLR); } }
/** * *\brief Initialize the menu handling. Clear screen and draw menu. * * \param menu menu struct with menu options * */ void gfx_mono_menu_init(struct gfx_mono_menu *menu) { /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); /* Draw the menu title on the top of the screen */ gfx_mono_draw_progmem_string((char PROGMEM_PTR_T)menu->title, 0, 0, &sysfont); /* Draw menu options below */ menu_draw(menu, true); }
/** * \internal * \brief Test drawing a filled rectangle inside a page * * This test draws a filled rectangle inside a page and checks that this * is done. * * \param test Current test case. */ static void run_draw_filled_rectangle_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; uint8_t i; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill page buffer holding rectangle set_buffer(expected_page, 0x00); for (i = 0; i < 10; i++) { expected_page[i + 50] = 0x7C; } // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw a 10x5 filled rectangle at position 50, 10 gfx_mono_draw_filled_rect(50, 10, 10, 5, GFX_PIXEL_SET); // Get all pages from display and check that the rectangle is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page), "Page with rectangle %d not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \internal * \brief Test filling the display * * This test fills the entire display and checks that this is done. * * \param test Current test case. */ static void run_set_display_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_set[GFX_MONO_LCD_WIDTH]; uint8_t page; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Filled expected page buffer set_buffer(expected_set, 0xFF); // Fill entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_SET); // Get all pages from display and check that each matches the empty page for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); test_assert_true(test, is_page_correct(actual, expected_set), "Page %d not matching expected page", page); } }
/** * \internal * \brief Test drawing a line between to points * * This test draws a line between two points and checks that this is done. * * \param test Current test case. */ static void run_draw_diagonal_line_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page1[GFX_MONO_LCD_WIDTH]; uint8_t expected_page2[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill first page buffer holding the line set_buffer(expected_page1, 0x00); expected_page1[0] = 0x03; expected_page1[1] = 0x0C; expected_page1[2] = 0x30; expected_page1[3] = 0xC0; // Fill second page buffer holding the line set_buffer(expected_page2, 0x00); expected_page2[4] = 0x01; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw a line between 0,0 and 4, 8 gfx_mono_draw_line(0, 0, 4, 8, GFX_PIXEL_SET); // Get all pages from display and check that the line is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 0) { test_assert_true(test, is_page_correct(actual, expected_page1), "Page %d with line not matching expected page", page); } else if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page2), "Page %d with line not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \internal * \brief Test drawing a vertical line * * This test draws a vertical line and checks that this is done. * * \param test Current test case. */ static void run_draw_vertical_line_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page1[GFX_MONO_LCD_WIDTH]; uint8_t expected_page2[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill page buffer holding the top of the line set_buffer(expected_page1, 0x00); expected_page1[4] = 0xFC; // Fill page buffer holding the bottom of the line set_buffer(expected_page2, 0x00); expected_page2[4] = 0x1F; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw a vertical line at position 4, 2 with length 11 gfx_mono_draw_vertical_line(4, 2, 11, GFX_PIXEL_SET); // Get all pages from display and check that the line is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 0) { test_assert_true(test, is_page_correct(actual, expected_page1), "Page %d with line not matching expected page", page); } else if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page2), "Page %d with line not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \internal * \brief Test drawing the outline of a circle on a page * * This test draws the outline of a circle and checks that this is done. * * \param test Current test case. */ static void run_draw_circle_outline_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill page buffer holding the outlined circle set_buffer(expected_page, 0x00); expected_page[47] = 0x1C; expected_page[48] = 0x22; expected_page[49] = 0x41; expected_page[50] = 0x41; expected_page[51] = 0x41; expected_page[52] = 0x22; expected_page[53] = 0x1C; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw the outline of a circle with radius 3 and centre at position 50, 11 gfx_mono_draw_circle(50, 11, 3, GFX_PIXEL_SET, GFX_WHOLE); // Get all pages from display and check that the circle is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page), "Page %d with outlined circle not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \brief Draws a character to the display * * \param c Character to be drawn * \param x X coordinate on screen. * \param y Y coordinate on screen. * \param font Font to draw character in */ void gfx_mono_draw_char(const char c, const gfx_coord_t x, const gfx_coord_t y, const struct font *font) { gfx_mono_draw_filled_rect(x, y, font->width, font->height, GFX_PIXEL_CLR); switch (font->type) { case FONT_LOC_PROGMEM: gfx_mono_draw_char_progmem(c, x, y, font); break; #ifdef CONFIG_HUGEMEM case FONT_LOC_HUGEMEM: gfx_mono_draw_char_hugemem(c, x, y, font); break; #endif default: /* Unsupported mode, call assert */ Assert(false); break; } }
/** * \internal * \brief Test drawing a horizontal line * * This test draws a horizontal line and checks that this is done. * * \param test Current test case. */ static void run_draw_horizontal_line_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; uint8_t i; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill page buffer holding the line set_buffer(expected_page, 0x00); for (i = 0; i < 50; i++) { expected_page[i + 10] = 0x10; } // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw a horizontal line at postition 10, 20 with length 50 gfx_mono_draw_horizontal_line(10, 20, 50, GFX_PIXEL_SET); // Get all pages from display and check that the line is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 2) { test_assert_true(test, is_page_correct(actual, expected_page), "Page %d with line not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
void button_press(void){ if(gpio_pin_is_low(GPIO_PUSH_BUTTON_1)){ gfx_mono_draw_filled_rect(0,cursor_position,5,8,GFX_PIXEL_CLR); if(cursor_position==8) cursor_position = 24; else cursor_position-=8; gfx_mono_draw_char('>', 0, cursor_position, &sysfont); } if(gpio_pin_is_low(GPIO_PUSH_BUTTON_2)){ gfx_mono_draw_filled_rect(0,cursor_position,5,8,GFX_PIXEL_CLR); if(cursor_position==24) cursor_position = 8; else cursor_position+=8; gfx_mono_draw_char('>', 0, cursor_position, &sysfont); } if(gpio_pin_is_low(GPIO_PUSH_BUTTON_0)){ if(cursor_position==8){ if(plant[0]==false){ if(sun_value>=plant_cost){ sun_value -= plant_cost; plant[0] = true; gfx_mono_draw_char('P',6,cursor_position,&sysfont); } } else{ if(sun_value>=2){ sun_value -= 2; tembak_atas[0]='*'; } } }else if(cursor_position==16){ if(plant[1]==false){ if(sun_value>=plant_cost){ sun_value -= plant_cost; plant[1] = true; gfx_mono_draw_char('P',6,cursor_position,&sysfont); } } else{ if(sun_value>=2){ sun_value -= 2; tembak_tengah[0]='*'; } } }else{ if(plant[2]==false){ if(sun_value>=plant_cost){ sun_value -= plant_cost; plant[2] = true; gfx_mono_draw_char('P',6,cursor_position,&sysfont); } } else{ if(sun_value>=2){ sun_value -= 2; tembak_bawah[0]='*'; } } } } }
/** * \brief Production date application * * This application will display the time since the XMEGA-A3BU Xplained board * has been produced. During production the production time is stored in EEPROM * and the RTC is initialized to the same time. The RTC is then left running * from the battery backup. This application reads out the production date from * EEPROM and shows the difference between the current time and the production * date; in other words the time the RTC timer has been running on battery * since production. * * \note If the EEPROM is erased and no production date can be set, it will * default to time 01.01.1970, the start of the UNIX time epoch. */ void production_date_application(void) { struct keyboard_event input_key; uint32_t past_timestamp = 0xFFFFFFFF; uint32_t rtc_timestamp; struct calendar_date rtc_date; struct calendar_date date_diff; struct calendar_date production_date; uint32_t production_date_timestamp; uint16_t months; uint8_t width; uint8_t height; uint8_t offset; char string_buf[22]; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Draw application title gfx_mono_draw_string("Time since production", 0, 0, &sysfont); // Get production timestamp production_date_timestamp = production_date_get_timestamp(); // Convert timestamp to date struct calendar_timestamp_to_date(production_date_timestamp, &production_date); // Exit the application if "back" key is pressed while (true) { keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_BACK) && (input_key.type == KEYBOARD_RELEASE)) { break; } // Get current time from RTC32 rtc_timestamp = rtc_get_time(); if (rtc_timestamp == past_timestamp) { // Same time as last time, no need for update continue; } past_timestamp = rtc_timestamp; // Convert timestamp to date struct calendar_timestamp_to_date(rtc_timestamp, &rtc_date); // Find the difference between the current date and production date calendar_time_between_dates(&rtc_date, &production_date, &date_diff); // Use months + year*12 as we are a line short to have both year and month months = (date_diff.year * 12) + date_diff.month; // Center month string on screen. Align day string with month string snprintf(string_buf, sizeof(string_buf), "%2d Months", months); gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 8, &sysfont); snprintf(string_buf, sizeof(string_buf), "%2d Days", date_diff.date); gfx_mono_draw_string(string_buf, offset, 16, &sysfont); // Display hour, minute, second snprintf(string_buf, sizeof(string_buf),"%.2d:%.2d:%.2d", date_diff.hour, date_diff.minute, date_diff.second); gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 24, &sysfont); } }
void app_usb_task(void) { static bool sw0_released = true; static bool usb_running = false; static bool cdc_running = false; static bool toggle = true; if (sw0_released && ioport_pin_is_low(GPIO_PUSH_BUTTON_0)) { /* A new press has been done */ sw0_released = false; /* Switch USB state */ if (usb_running) { udc_stop(); gfx_mono_draw_filled_rect(DISPLAY_USB_STA_POS_X, DISPLAY_USB_STA_POS_Y, DISPLAY_USB_STA_SIZE_X, DISPLAY_USB_STA_SIZE_Y, GFX_PIXEL_CLR); app_microsd_start(); } else { /* Stop FatFS on uSD card if enabled */ app_microsd_stop(); stdio_usb_init(); /* Start USB */ gfx_mono_generic_put_bitmap(&bitmap_usb, DISPLAY_USB_STA_POS_X, DISPLAY_USB_STA_POS_Y); } usb_running = !usb_running; cdc_running = true; } else { /* Wait switch release */ sw0_released = ioport_pin_is_high(GPIO_PUSH_BUTTON_0); } if (!usb_running) { return; } /* USB MSC task */ while (udi_msc_process_trans()) { } if (app_usb_cdc_open && !cdc_running) { printf("\x0CSensor data logs:\r\n"); cdc_running = true; } if (!app_usb_cdc_open && cdc_running) { cdc_running = false; } /* Toggle USB icon */ if ((app_usb_cdc_open && app_usb_rec_toggle) || (toggle && app_usb_rec_toggle)) { app_usb_rec_toggle = false; toggle = !toggle; gfx_mono_draw_rect(DISPLAY_USB_STACDC_POS_X, DISPLAY_USB_STACDC_POS_Y, DISPLAY_USB_STACDC_SIZE_X, DISPLAY_USB_STACDC_SIZE_Y, toggle ? GFX_PIXEL_SET : GFX_PIXEL_CLR); } }
/** * \internal * \brief Test drawing a bitmap stored in RAM * * This test draws a bitmap to position x = 50, y = 5 and checks that * it is aligned with display pages and that it is drawn correctly. * * \param test Current test case. */ static void run_draw_ram_bitmap_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page1[GFX_MONO_LCD_WIDTH]; uint8_t expected_page2[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; struct gfx_mono_bitmap smiley; // Setup bitmap struct for bitmap stored in RAM smiley.type = GFX_MONO_BITMAP_RAM; smiley.width = 8; smiley.height = 16; smiley.data.pixmap = smiley_data; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill first page buffer holding smileys set_buffer(expected_page1, 0x00); expected_page1[50] = 0x3C; expected_page1[51] = 0x42; expected_page1[52] = 0x95; expected_page1[53] = 0xA1; expected_page1[54] = 0xA1; expected_page1[55] = 0x95; expected_page1[56] = 0x42; expected_page1[57] = 0x3C; // Fill second page buffer holding smileys set_buffer(expected_page2, 0x00); expected_page2[50] = 0x3C; expected_page2[51] = 0x42; expected_page2[52] = 0x95; expected_page2[53] = 0xA1; expected_page2[54] = 0xA1; expected_page2[55] = 0x95; expected_page2[56] = 0x42; expected_page2[57] = 0x3C; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Output bitmap gfx_mono_put_bitmap(&smiley, 50, 5); // Get all pages from display and check that the bitmap is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 0) { test_assert_true(test, is_page_correct(actual, expected_page1), "Page %d with smileys not matching expected page", page); } else if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page2), "Page %d with smileys not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \internal * \brief Test drawing a bitmap stored in FLASH * * This test draws a bitmap to position x = 60, y = 9 and checks that * it is aligned with display pages and that it is drawn correctly. * * \param test Current test case. */ static void run_draw_flash_bitmap_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page1[GFX_MONO_LCD_WIDTH]; uint8_t expected_page2[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; struct gfx_mono_bitmap smiley_flash; // Setup bitmap for bitmap stored in FLASH smiley_flash.type = GFX_MONO_BITMAP_PROGMEM; smiley_flash.width = 8; smiley_flash.height = 16; smiley_flash.data.progmem = flash_bitmap; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill first page buffer holding smileys set_buffer(expected_page1, 0x00); expected_page1[60] = 0x3C; expected_page1[61] = 0x42; expected_page1[62] = 0x95; expected_page1[63] = 0xA1; expected_page1[64] = 0xA1; expected_page1[65] = 0x95; expected_page1[66] = 0x42; expected_page1[67] = 0x3C; // Fill second page buffer holding smileys set_buffer(expected_page2, 0x00); expected_page2[60] = 0x3C; expected_page2[61] = 0x42; expected_page2[62] = 0x95; expected_page2[63] = 0xA1; expected_page2[64] = 0xA1; expected_page2[65] = 0x95; expected_page2[66] = 0x42; expected_page2[67] = 0x3C; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Output bitmap gfx_mono_put_bitmap(&smiley_flash, 60, 9); // Get all pages from display and check that the bitmap is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page1), "Page %d with smileys not matching expected page", page); } else if (page == 2) { test_assert_true(test, is_page_correct(actual, expected_page2), "Page %d with smileys not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
/** * \brief Display current date and time in the selected timezone */ static void display_date_time_application(void) { struct calendar_date date; struct keyboard_event input_key; uint8_t width; uint8_t height; uint8_t offset; int8_t tz_hours_temp; int8_t tz_minutes_temp; uint32_t past_timestamp = 0xFFFFFFFF; uint32_t rtc_timestamp = 0; char string_buf[32] = "Date & Time"; //clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Get current timestamp from the RTC32 rtc_timestamp = rtc_get_time(); // Get timezone settings tz_hours_temp = timezone_get_hours(); tz_minutes_temp = timezone_get_minutes(); // Print "Date & Time" at first line of the display gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 0, &sysfont); // Convert RTC time to a date struct containing the current date and time calendar_timestamp_to_date_tz(rtc_timestamp, tz_hours_temp, tz_minutes_temp, &date); while (true) { // Return from application if "back" key is pressed and released keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_BACK) && (input_key.type == KEYBOARD_RELEASE)) { break; } rtc_timestamp = rtc_get_time(); // Update printed time if the time has changed if(rtc_timestamp != past_timestamp) { calendar_add_second_to_date(&date); // Print current date centered on line 3 snprintf(string_buf, sizeof(string_buf),"%s %.2d.%.2d.%d", day[date.dayofweek], date.date + 1, date.month + 1, date.year); gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 12, &sysfont); snprintf(string_buf, sizeof(string_buf), "%.2d:%.2d:%.2d", date.hour, date.minute, date.second); // Center text gfx_mono_get_string_bounding_box(string_buf, &sysfont,&width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 20, &sysfont); past_timestamp = rtc_timestamp; } } }
/** * \brief Set the date using a spinner widget. * * This function will set show a spinner widget that lets the user select the * current date. This function will leave the clock unchanged, and only change * the date part of the RTC32 timestamp. */ static void set_date_application(void) { struct calendar_date date; struct calendar_date new_date; struct keyboard_event input; uint32_t current_timestamp; uint32_t new_timestamp; uint8_t tz_hours; uint8_t tz_minutes; struct gfx_mono_spinctrl year_spinner; struct gfx_mono_spinctrl month_spinner; struct gfx_mono_spinctrl day_spinner; struct gfx_mono_spinctrl_spincollection date_spinners; int16_t spinner_results[3]; uint8_t spinner_status; // Prepare the spinner widget for date selection gfx_mono_spinctrl_init(&year_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_year, NULL, 2011, 2105, 0); gfx_mono_spinctrl_init(&month_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_month, NULL, 1, 12, 0); gfx_mono_spinctrl_init(&day_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_day, NULL, 1, 31, 0); // Create date spincollector gfx_mono_spinctrl_spincollection_init(&date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&year_spinner, &date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&month_spinner, &date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&day_spinner, &date_spinners); // Get timezone settings tz_hours = timezone_get_hours(); tz_minutes = timezone_get_minutes(); // Get current time current_timestamp = rtc_get_time(); // Convert the current timestamp to a datestruct calendar_timestamp_to_date_tz(current_timestamp, tz_hours, tz_minutes, &date); // Set the spinner selection to the current date day_spinner.integer_data = date.date + 1; month_spinner.integer_data = date.month + 1; year_spinner.integer_data = date.year; // show the date selection spinner to get a new date gfx_mono_spinctrl_spincollection_show(&date_spinners); do { do { keyboard_get_key_state(&input); // Wait for key release } while (input.type != KEYBOARD_RELEASE); // Send key to spinnercollection spinner_status = gfx_mono_spinctrl_spincollection_process_key( &date_spinners, input.keycode, spinner_results); } while (spinner_status != GFX_MONO_SPINCTRL_EVENT_FINISH); /* The result are stored in the same order that they were added * we subtract one from month and day, as they are indexed from 0 in the * date struct but we present them as starting from 1 in the spinner. */ new_date.year = spinner_results[0]; new_date.month = spinner_results[1] - 1; new_date.date = spinner_results[2] - 1; // Verify date set new_date.hour = 0; new_date.minute = 0; new_date.second = 0; if (calendar_date_to_timestamp_tz(&new_date, tz_hours, tz_minutes) == 0) { //Notify the user that the date was invalid and wait for key gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); gfx_mono_draw_progmem_string( (char PROGMEM_PTR_T)datetime_invalid_date_string, 10, 12, &sysfont); while (true) { keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { break; } } return; } // Date OK, change. // Get current time current_timestamp = rtc_get_time(); // Convert the current timestamp to a datestruct calendar_timestamp_to_date_tz(current_timestamp, tz_hours, tz_minutes, &date); // Set new date in struct date.year = new_date.year; date.month = new_date.month; date.date = new_date.date; // Convert back to timestamp new_timestamp = calendar_date_to_timestamp_tz(&date, tz_hours, tz_minutes); // Set new timestamp rtc_set_time(new_timestamp); }
/** * \brief Terminal task * * This task prints the terminal text buffer to the display. * * \param params Parameters for the task. (Not used.) */ static void terminal_task(void *params) { gfx_coord_t x, y; char current_char; uint8_t current_column; uint8_t current_line; uint8_t printed_lines; EventBits_t event_bits; const TickType_t ticks_to_wait = 10 / portTICK_PERIOD_MS; for (;;) { /* Wait a maximum of 10ms for either bit 2 to be set within the event group. Not clear the bits before exiting. */ event_bits = xEventGroupWaitBits( event_group, /* The event group being tested. */ EVENT_DISPLAY_TERMINAL, /* The bits within the event group to wait for. */ pdFALSE, /* Bit should not be cleared before returning. */ pdFALSE, /* Don't wait for both bits, either bit will do. */ ticks_to_wait);/* Wait a maximum of 10ms for either bit to be set. */ if(event_bits & EVENT_DISPLAY_TERMINAL) { oled1_set_led_state(&oled1, OLED1_LED2_ID, true); // Grab both display and terminal mutexes before doing anything xSemaphoreTake(display_mutex, portMAX_DELAY); xSemaphoreTake(terminal_mutex, portMAX_DELAY); y = (TERMINAL_LINES - 1) * (SYSFONT_HEIGHT + 1); current_line = terminal_line_offset; for (printed_lines = 0; printed_lines < TERMINAL_LINES; printed_lines++) { x = 0; current_column = 0; // Print characters of string until zero terminator is encountered current_char = terminal_buffer[current_line][current_column]; while (current_char != '\0') { gfx_mono_draw_char(current_char, x, y, &sysfont); // Move to next character on display and in buffer x += SYSFONT_WIDTH; current_column++; current_char = terminal_buffer[current_line][current_column]; } // Erase remaining part of line on display if (current_column < TERMINAL_COLUMNS) { gfx_mono_draw_filled_rect(x, y, CANVAS_WIDTH - (current_column * SYSFONT_WIDTH), SYSFONT_HEIGHT, GFX_PIXEL_CLR); } // Move to previous line on display and in buffer y -= 1 + SYSFONT_HEIGHT; current_line += TERMINAL_BUFFER_LINES - 1; current_line %= TERMINAL_BUFFER_LINES; } xSemaphoreGive(terminal_mutex); xSemaphoreGive(display_mutex); oled1_set_led_state(&oled1, OLED1_LED2_ID, false); } vTaskDelay(TERMINAL_TASK_DELAY); } }
void app_sampling_init(void) { /* QDec configuration */ qdec_get_config_defaults(&qdec_config); qdec_config_phase_pins(&qdec_config, &PORTA, 6, false, 500); qdec_config_enable_rotary(&qdec_config); qdec_config_tc(&qdec_config, &TCC5); qdec_config_revolution(&qdec_config, 40); qdec_enabled(&qdec_config); /* ! ADC module configuration */ struct adc_config adc_conf; /* Configure the ADC module: * - signed, 12-bit results * - VCC reference * - 200 kHz maximum clock rate * - manual conversion triggering * - callback function */ adc_read_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_callback(&LIGHT_SENSOR_ADC_MODULE, &app_sampling_handler); adc_enable(&LIGHT_SENSOR_ADC_MODULE); /* Configure ADC A channel 0 for light and NTC sensors. * - differantial measurement (V- linked on internal GND) * - gain x0.5 * - interrupt flag set on completed conversion * - interrupts enabled */ adcch_read_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); adcch_set_input(&adcch_conf, LIGHT_SENSOR_ADC_INPUT, ADCCH_NEG_INTERNAL_GND, 0); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); fifo_init(&app_sampling_fifo_desc, app_sampling_fifo_buffer, APP_SAMPLING_FIFO_SIZE); rtc_set_callback(&app_sampling_start); /* Display background */ gfx_mono_draw_line(DISPLAY_SAMPLING_TEXT_POS_X - 3, 0, DISPLAY_SAMPLING_TEXT_POS_X - 3, 32, GFX_PIXEL_SET); app_sampling_display_rate(); gfx_mono_draw_string(DISPLAY_LIGHT_TEXT, DISPLAY_LIGHT_TEXT_POS_X, DISPLAY_LIGHT_TEXT_POS_Y, &sysfont); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_START_POS_X, DISPLAY_LIGHT_PROBAR_START_POS_Y, DISPLAY_LIGHT_PROBAR_START_SIZE_X, DISPLAY_LIGHT_PROBAR_START_SIZE_Y, GFX_PIXEL_SET); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_STOP_POS_X, DISPLAY_LIGHT_PROBAR_STOP_POS_Y, DISPLAY_LIGHT_PROBAR_STOP_SIZE_X, DISPLAY_LIGHT_PROBAR_STOP_SIZE_Y, GFX_PIXEL_SET); /* Start a RTC alarm immediatly */ rtc_set_alarm_relative(0); }
void tampilkanTembak(void){ for(i=0;i<19;++i){ if(i==18){ if(tembak_atas[i+1]=='*') gfx_mono_draw_filled_rect(i*6+12,8,10,7,GFX_PIXEL_CLR); if(tembak_tengah[i+1]=='*') gfx_mono_draw_filled_rect(i*6+12,16,10,7,GFX_PIXEL_CLR); if(tembak_bawah[i+1]=='*') gfx_mono_draw_filled_rect(i*6+12,24,10,7,GFX_PIXEL_CLR); } if(tembak_atas[i]=='*') { if(atas[i+j] =='@'){ tembak_atas[i]=' '; atas[i+j] = ' '; zombie--; score++; gfx_mono_draw_filled_rect(i*6+6,8,12,7,GFX_PIXEL_CLR); }else{ if(i>0){ gfx_mono_draw_filled_rect(i*6+6,8,6,7,GFX_PIXEL_CLR); } gfx_mono_draw_char(tembak_atas[i],i*6+12,8,&sysfont); } } if(tembak_tengah[i]=='*') { if(tengah[i+j] =='@'){ tembak_tengah[i]=' '; tengah[i+j] = ' '; zombie--; score++; gfx_mono_draw_filled_rect(i*6+6,16,12,7,GFX_PIXEL_CLR); }else { if(i>0){ gfx_mono_draw_filled_rect(i*6+6,16,6,7,GFX_PIXEL_CLR); } gfx_mono_draw_char(tembak_tengah[i],i*6+12,16,&sysfont); } } if(tembak_bawah[i]=='*') { if(bawah[i+j] =='@'){ tembak_bawah[i]=' '; bawah[i+j] = ' '; zombie--; score++; gfx_mono_draw_filled_rect(i*6+6,24,12,7,GFX_PIXEL_CLR); }else{ if(i>0){ gfx_mono_draw_filled_rect(i*6+6,24,6,7,GFX_PIXEL_CLR); } gfx_mono_draw_char(tembak_bawah[i],i*6+12,24,&sysfont); } } } for(i=19;i>0;i--){ tembak_atas[i] = tembak_atas[i-1]; tembak_tengah[i] = tembak_tengah[i-1]; tembak_bawah[i] = tembak_bawah[i-1]; } tembak_atas[0] = ' '; tembak_tengah[0] = ' '; tembak_bawah[0] = ' '; }
/** * \brief Main function. * * Initializes the board, displays splash screens, then launches application. * * If the application exits (fails), the error is written to display and an * infinite loop with watchdog resets is entered. */ int main(void) { /* Holds state of the QTouch button */ enum pot_t potstate = POT_OFF; /* Last state of the QTouch button for change detection */ enum pot_t last_potstate = POT_OFF; /* Holds user-selected power-setting */ uint8_t wattage = 0; /* Last power-setting for change detection */ uint8_t last_wattage = 0; /* Whether the plate element is/should be actuated */ bool power = false; /* Last power setting for change detection */ bool last_power = false; /* Last time a simulation step was executed */ uint32_t last_sim_step; /* Last time a control step was executed */ uint32_t last_ctl_step; /* The WDT was just reset by the WDT functional test*/ classb_last_wdt_reset = rtc_get_time(); last_sim_step = classb_last_wdt_reset; last_ctl_step = classb_last_wdt_reset; sysclk_init(); board_init(); pmic_init(); gfx_mono_init(); touch_init(); main_init_rtc32(); cpu_irq_enable(); /* Enable display backlight */ ioport_set_pin_level(LCD_BACKLIGHT_ENABLE_PIN, LCD_BACKLIGHT_ENABLE_LEVEL); /* If an error was detected, skip directly to displaying it */ if (classb_error) { goto display_error; } /* Check if required jumpers are mounted, show explanation if not */ if (!main_check_jumpers()) { show_explain_splash(); } /* Display a splash screen showing button functions */ show_button_splash(); /* Initialize the ADC, DAC and Timer/Counter modules that are used to * emulate real world objects. */ main_init_adc_dac(); main_init_tc(); /* Initialize subsystems used for Class B testing */ oven_classb_init_tests(); /* Reset the simulation states */ oven_plant_init(); /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); /* Draw the initial axis system */ oven_ui_draw_axis(); /* Draw the user interface */ oven_ui_update_graphics(potstate, wattage, power); /* Run simulation as long as no error is detected in class B tests */ while (!classb_error) { uint32_t current_time; oven_wdt_periodic_reset(); current_time = rtc_get_time(); /* Add power on SW1 press, wrap at 20 */ if (oven_ui_power_button_is_pressed()) { wattage = (wattage + 5) % 20; } /* Check QTouch sensor and map this to `potstate`. This is * needed both for simulation and for the control routine. */ potstate = (!touch_key_is_pressed()) ? POT_ON : POT_OFF; /* Execute control routine periodically */ if (current_time > (last_ctl_step + OVEN_CTL_STEP_TIME)) { ovenctl_execute_control_step(current_time, &wattage, &power, potstate); last_ctl_step = current_time; } /* Execute simulation step periodically */ if (current_time > (last_sim_step + OVEN_SIM_STEP_TIME)) { main_execute_simulation_step(current_time, potstate); last_sim_step = current_time; } /* Update graphics on wattage, power or pot on/off change */ if ((potstate != last_potstate) || (power != last_power) || (wattage != last_wattage)) { oven_ui_update_graphics(potstate, wattage, power); } /* Update variable states for change detection on next loop * iteration. */ last_power = power; last_wattage = wattage; last_potstate = potstate; /* If back/menu button is pressed, pause simulation and test * timers, and show menu. */ if (oven_ui_back_button_is_pressed()) { /* Disable interrupt monitoring, if enabled */ classb_intmon_set_state(TEMP_SANITY_TEST, M_DISABLE); classb_intmon_set_state(PER_CLASSB_TESTS, M_DISABLE); OVEN_PERIODIC_TEMPTEST_TC.CTRLA &= ~TC1_CLKSEL_gm; OVEN_PERIODIC_CLASSB_TC.CTRLA &= ~TC0_CLKSEL_gm; /* Show the error insertion menu */ oven_classb_error_insertion(); /* Re-enable timers upon return */ OVEN_PERIODIC_CLASSB_TC.CTRLA |= TC_CLKSEL_DIV1024_gc; /* If user did not induce an error in the temperature * test timing, re-enable it correctly. */ if ((OVEN_PERIODIC_TEMPTEST_TC.CTRLA & TC1_CLKSEL_gm) == TC_CLKSEL_OFF_gc) { OVEN_PERIODIC_TEMPTEST_TC.CTRLA |= TC_CLKSEL_DIV1024_gc; } /* Re-enable interrupt monitoring if the oven is * supposed to be on, i.e., they were enabled before. */ if (wattage > 0) { classb_intmon_set_state(TEMP_SANITY_TEST, M_ENABLE); classb_intmon_set_state(PER_CLASSB_TESTS, M_ENABLE); } /* Reset UI */ gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); oven_ui_draw_axis(); oven_ui_update_graphics(potstate, wattage, power); } } display_error: /* Show red status LED and write the error on display */ oven_ui_set_status_leds(S_RED); oven_classb_display_error(); /* Enter infinite loop of watchdog resets so user can read display */ while (true) { oven_wdt_periodic_reset(); } }
/** * \brief Main demo task * * This task keeps track of which screen the user has selected, which tasks * to resume/suspend to draw the selected screen, and also draws the menu bar. * * The menu bar shows which screens the user can select by clicking the * corresponding buttons on the OLED1 Xplained Pro: * - \ref graph_task() "graph" (selected at start-up) * - \ref terminal_task() "term." * - \ref about_task() "about" * * \param params Parameters for the task. (Not used.) */ static void main_task(void *params) { bool graph_buffer_initialized = false; bool selection_changed = true; bool select_graph_buffer; enum menu_items current_selection = MENU_ITEM_GRAPH; gfx_coord_t x, y, display_y_offset; xTaskHandle temp_task_handle = NULL; for(;;) { // Show that task is executing oled1_set_led_state(&oled1, OLED1_LED3_ID, true); // Check buttons to see if user changed the selection if (oled1_get_button_state(&oled1, OLED1_BUTTON1_ID) && (current_selection != MENU_ITEM_GRAPH)) { current_selection = MENU_ITEM_GRAPH; selection_changed = true; } else if (oled1_get_button_state(&oled1, OLED1_BUTTON2_ID) && (current_selection != MENU_ITEM_TERMINAL)) { current_selection = MENU_ITEM_TERMINAL; selection_changed = true; } else if (oled1_get_button_state(&oled1, OLED1_BUTTON3_ID) && (current_selection != MENU_ITEM_ABOUT)) { current_selection = MENU_ITEM_ABOUT; selection_changed = true; } // If selection changed, handle the selection if (selection_changed) { // Wait for and take the display semaphore before doing any changes. xSemaphoreTake(display_mutex, portMAX_DELAY); // We can now safely suspend the previously resumed task if (temp_task_handle) { vTaskSuspend(temp_task_handle); temp_task_handle = NULL; } // Select the new drawing task and corresponding display buffer switch (current_selection) { case MENU_ITEM_GRAPH: // Graph task runs continuously, no need to set task handle select_graph_buffer = true; break; case MENU_ITEM_TERMINAL: temp_task_handle = terminal_task_handle; select_graph_buffer = false; break; default: case MENU_ITEM_ABOUT: temp_task_handle = about_task_handle; select_graph_buffer = false; } // Select and initialize display buffer to use. display_y_offset = select_graph_buffer ? CANVAS_GRAPH_Y_OFFSET : 0; // Draw the menu bar (only needs to be done once for graph) if (!select_graph_buffer || !graph_buffer_initialized) { // Clear the selected display buffer first gfx_mono_draw_filled_rect(0, display_y_offset, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT / 2, GFX_PIXEL_CLR); // Draw menu lines, each item with height MENU_HEIGHT pixels y = display_y_offset + CANVAS_HEIGHT; gfx_mono_draw_horizontal_line(0, y, GFX_MONO_LCD_WIDTH, GFX_PIXEL_SET); x = MENU_ITEM_WIDTH; y++; for (uint8_t i = 0; i < (MENU_NUM_ITEMS - 1); i++) { gfx_mono_draw_vertical_line(x, y, MENU_HEIGHT, GFX_PIXEL_SET); x += 1 + MENU_ITEM_WIDTH; } // Highlight the current selection gfx_mono_draw_rect(current_selection * (1 + MENU_ITEM_WIDTH), y, MENU_ITEM_WIDTH, MENU_HEIGHT, GFX_PIXEL_SET); // Draw the menu item text x = (MENU_ITEM_WIDTH / 2) - ((5 * SYSFONT_WIDTH) / 2); y += (MENU_HEIGHT / 2) - (SYSFONT_HEIGHT / 2); for (uint8_t i = 0; i < MENU_NUM_ITEMS; i++) { gfx_mono_draw_string(menu_items_text[i], x, y, &sysfont); x += 1 + MENU_ITEM_WIDTH; } graph_buffer_initialized = true; } // Set display controller to output the new buffer ssd1306_set_display_start_line_address(display_y_offset); // We are done modifying the display, so give back the mutex xSemaphoreGive(display_mutex); selection_changed = false; // If a task handle was specified, resume it now if (temp_task_handle) { vTaskResume(temp_task_handle); } } // Show that task is done oled1_set_led_state(&oled1, OLED1_LED3_ID, false); vTaskDelay(MAIN_TASK_DELAY); } }
void adc_application(void) { struct keyboard_event input_key; char string_buf[10]; uint32_t adca0_val = 0; uint32_t adca1_val = 0; uint32_t adca2_val = 0; uint32_t adca3_val = 0; uint32_t adcb0_val = 0; uint32_t adcb1_val = 0; uint32_t adcb2_val = 0; uint32_t adcb3_val = 0; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Draw static strings outside the loop gfx_mono_draw_string("ADC0", 100, 0, &sysfont); gfx_mono_draw_string("ADC1", 100, 8, &sysfont); gfx_mono_draw_string("ADC2", 100, 16, &sysfont); gfx_mono_draw_string("ADC3", 100, 24, &sysfont); gfx_mono_draw_string("ADC4", 0, 0, &sysfont); gfx_mono_draw_string("ADC5", 0, 8, &sysfont); // gfx_mono_draw_string("ADC6", 0, 16, &sysfont); // gfx_mono_draw_string("ADC7", 0, 24, &sysfont); gfx_mono_draw_string("Light", 0, 16, &sysfont); gfx_mono_draw_string("NTC", 0, 24, &sysfont); while (true) { // Start an ADC conversion /*adc_start_conversion(&ADCA, ADC_CH0); adc_start_conversion(&ADCA, ADC_CH1); adc_start_conversion(&ADCA, ADC_CH2); adc_start_conversion(&ADCA, ADC_CH3);*/ lightsensor_measure(); ntc_measure(); adc_measure(); adc2_measure(); while (!adc_data_is_ready() && !adc2_data_is_ready() && !ntc_data_is_ready() && !lightsensor_data_is_ready()) { // Wait until the conversion is complete } //adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); /*adc0_val = adc_get_result(&ADCA, ADC_CH0); adc1_val = adc_get_result(&ADCA, ADC_CH1); adc2_val = adc_get_result(&ADCA, ADC_CH2); adc3_val = adc_get_result(&ADCA, ADC_CH3);*/ adca0_val = lightsensor_get_raw_value(); adca1_val = ntc_get_raw_value(); adca2_val = adc_get_raw_value(); adca3_val = adc2_get_raw_value(); snprintf(string_buf, sizeof(string_buf), "%4ld", adca0_val); gfx_mono_draw_string(string_buf, 30, 16, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca1_val); gfx_mono_draw_string(string_buf, 30, 24, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca2_val); gfx_mono_draw_string(string_buf, 30, 0, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca3_val); gfx_mono_draw_string(string_buf, 30, 8, &sysfont); // Start an ADCB conversion /*adc_start_conversion(&ADCB, ADC_CH0); adc_start_conversion(&ADCB, ADC_CH1); adc_start_conversion(&ADCB, ADC_CH2); adc_start_conversion(&ADCB, ADC_CH3);*/ adcb0_measure(); adcb1_measure(); adcb2_measure(); adcb3_measure(); while (!adcb0_data_is_ready() && !adcb1_data_is_ready() && !adcb2_data_is_ready() && !adcb3_data_is_ready()) { // Wait until the conversion is complete } //adc_wait_for_interrupt_flag(&ADCB, ADC_CH0); /*adc0_val = adc_get_result(&ADCA, ADC_CH0); adc1_val = adc_get_result(&ADCA, ADC_CH1); adc2_val = adc_get_result(&ADCA, ADC_CH2); adc3_val = adc_get_result(&ADCA, ADC_CH3);*/ adcb0_val = adcb0_get_raw_value(); adcb1_val = adcb1_get_raw_value(); adcb2_val = adcb2_get_raw_value(); adcb3_val = adcb3_get_raw_value(); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb0_val); gfx_mono_draw_string(string_buf, 60, 0, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb1_val); gfx_mono_draw_string(string_buf, 60, 8, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb2_val); gfx_mono_draw_string(string_buf, 60, 16, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb3_val); gfx_mono_draw_string(string_buf, 60, 24, &sysfont); keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_ENTER) && (input_key.type == KEYBOARD_RELEASE)) { break; } } }
int main (void) { sysclk_init(); board_init(); pmic_init(); gfx_mono_init(); adc_sensors_init(); // Enable display backlight gpio_set_pin_high(NHD_C12832A1Z_BACKLIGHT); cpu_irq_enable(); while(true){ if(state==1){ start_game(); }else if(state==2){ tc_enable(&TCC0); tc_set_overflow_interrupt_callback(&TCC0, sun_count); tc_set_wgm(&TCC0, TC_WG_NORMAL); tc_write_period(&TCC0, 13500); tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO); tc_write_clock_source(&TCC0, TC_CLKSEL_DIV256_gc); tc_enable(&TCC1); tc_set_overflow_interrupt_callback(&TCC1, button_press); tc_set_wgm(&TCC1, TC_WG_NORMAL); tc_write_period(&TCC1, 62500); tc_set_overflow_interrupt_level(&TCC1, TC_INT_LVL_LO); tc_write_clock_source(&TCC1, TC_CLKSEL_DIV8_gc); gfx_mono_draw_string("SUN: 0", 0, 0, &sysfont); gfx_mono_draw_string(">", 0, cursor_position, &sysfont); gfx_mono_draw_string("Score: 0", 63, 0, &sysfont); randomPeta(); char* score_string = NULL; uint16_t old_score = 0; for(j = 0; j <= 70; j++){ if(sun_value > 10){ lightsensor_measure(); while (!lightsensor_data_is_ready()) { // Wait until the conversion is complete } if(lightsensor_get_raw_value() > 250){ sun_value -= 10; sunBurst(); gfx_mono_draw_filled_rect(12,8,114,24,GFX_PIXEL_CLR); } } if(score > old_score){ sprintf(score_string, "%3d", score); gfx_mono_draw_string(score_string, 100, 0, &sysfont); old_score = score; } if(lose){ state=3; break; }else if(zombie==0){ state=4; break; } tampilkanPeta(); tampilkanTembak(); delay_ms(1000); } }else if(state==3){ cpu_irq_disable(); gfx_mono_draw_filled_rect(0,0,128,32,GFX_PIXEL_CLR); while(true){ gfx_mono_draw_string("GAME OVER",36,8,&sysfont) ; gfx_mono_draw_string("You Lose",39,20,&sysfont) ; } }else if(state==4){ cpu_irq_disable(); gfx_mono_draw_filled_rect(0,0,128,32,GFX_PIXEL_CLR); while(true){ gfx_mono_draw_string("GAME OVER",36,2,&sysfont) ; gfx_mono_draw_string("You Win",42,12,&sysfont) ; gfx_mono_draw_string("Score = ",30,22,&sysfont) ; char* score_string = NULL; sprintf(score_string, "%3d", score); gfx_mono_draw_string(score_string, 79, 22, &sysfont); } } } }
/** * \internal * \brief Test drawing a filled circle spanning two pages * * This test draws a filled circle spanning two pages and checks that this is * done. * * \param test Current test case. */ static void run_draw_filled_circle_test(const struct test_case *test) { uint8_t actual[GFX_MONO_LCD_WIDTH]; uint8_t expected_page1[GFX_MONO_LCD_WIDTH]; uint8_t expected_page2[GFX_MONO_LCD_WIDTH]; uint8_t expected_empty[GFX_MONO_LCD_WIDTH]; uint8_t page; // Clear entire display gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); // Fill first page buffer holding the top part of the circle set_buffer(expected_page1, 0x00); expected_page1[36] = 0x80; expected_page1[37] = 0xC0; expected_page1[38] = 0xE0; expected_page1[39] = 0xE0; expected_page1[40] = 0xE0; expected_page1[41] = 0xE0; expected_page1[42] = 0xE0; expected_page1[43] = 0xC0; expected_page1[44] = 0x80; // Fill second page buffer holding the lower part of the circle set_buffer(expected_page2, 0x00); expected_page2[35] = 0x1F; expected_page2[36] = 0x3F; expected_page2[37] = 0x7F; expected_page2[38] = 0xFF; expected_page2[39] = 0xFF; expected_page2[40] = 0xFF; expected_page2[41] = 0xFF; expected_page2[42] = 0xFF; expected_page2[43] = 0x7F; expected_page2[44] = 0x3F; expected_page2[45] = 0x1F; // Fill empty page buffer set_buffer(expected_empty, 0x00); // Draw a filled circle with radius 5 and centre at position 40, 18 gfx_mono_draw_filled_circle(40, 18, 5, GFX_PIXEL_SET, GFX_WHOLE); // Get all pages from display and check that the circle is drawn for (page = 0; page < GFX_MONO_LCD_PAGES; page++) { gfx_mono_get_page(actual, page, 0, GFX_MONO_LCD_WIDTH); if (page == 1) { test_assert_true(test, is_page_correct(actual, expected_page1), "Page %d with filled circle not matching expected page", page); } else if (page == 2) { test_assert_true(test, is_page_correct(actual, expected_page2), "Page %d with filled circle not matching expected page", page); } else { test_assert_true(test, is_page_correct(actual, expected_empty), "Empty page %d not matching expected page", page); } } }
void app_sampling_task(void) { static uint16_t time_stamp; static uint8_t time_last; uint8_t time_pos; adc_result_t light; char string[30]; uint8_t light_bar_pos; irqflags_t flags; static uint16_t qdec_position_last = 2; uint16_t qdec_position; /* Manage frequency sample through Quadrature encoder */ qdec_position = qdec_get_position(&qdec_config) / 2; if (qdec_position != qdec_position_last) { /* Quadrature encoder have changed */ qdec_position_last = qdec_position; app_sampling_rate = (qdec_position_last + 1) * 2; flags = cpu_irq_save(); if (app_sampling_rtc_run) { time_stamp = rtc_get_time(); rtc_set_alarm_relative(app_sampling_rate - 1); } cpu_irq_restore(flags); app_sampling_display_rate(); } /* Update sampling progress bar */ time_pos = ((rtc_get_time() - time_stamp) * 8) / app_sampling_rate; if (time_pos > 8) { time_pos = 8; } if (time_last > time_pos) { gfx_mono_draw_filled_circle( DISPLAY_SAMPLING_PROCIRCLE_POS_X, DISPLAY_SAMPLING_PROCIRCLE_POS_Y, DISPLAY_SAMPLING_PROCIRCLE_RADIUS, GFX_PIXEL_CLR, GFX_WHOLE); } if (time_last != time_pos) { gfx_mono_draw_filled_circle( DISPLAY_SAMPLING_PROCIRCLE_POS_X, DISPLAY_SAMPLING_PROCIRCLE_POS_Y, DISPLAY_SAMPLING_PROCIRCLE_RADIUS, GFX_PIXEL_SET, (1lu << time_pos) - 1); } time_last = time_pos; /* Manage FIFO about sensor data */ if (2 > fifo_get_used_size(&app_sampling_fifo_desc)) { return; /* Not enought data */ } /* Get values */ time_stamp = fifo_pull_uint16_nocheck(&app_sampling_fifo_desc); light = (adc_result_t)fifo_pull_uint16_nocheck(&app_sampling_fifo_desc); /* Display values through USART */ sprintf(string, "%4u,%02us - %3d light\r\n", time_stamp / 4, (time_stamp % 4) * 25, light); printf("%s", string); /* Update light progress bar */ light_bar_pos = ((uint32_t)light * DISPLAY_LIGHT_PROBAR_MAX_SIZE_X) / 2048lu; if (light_bar_pos > DISPLAY_LIGHT_PROBAR_MAX_SIZE_X) { light_bar_pos = DISPLAY_LIGHT_PROBAR_MAX_SIZE_X; } gfx_mono_draw_filled_rect(DISPLAY_LIGHT_PROBAR_POS_X, DISPLAY_LIGHT_PROBAR_POS_Y, light_bar_pos, DISPLAY_LIGHT_PROBAR_SIZE_Y, GFX_PIXEL_SET); gfx_mono_draw_filled_rect(DISPLAY_LIGHT_PROBAR_POS_X + light_bar_pos, DISPLAY_LIGHT_PROBAR_POS_Y, DISPLAY_LIGHT_PROBAR_MAX_SIZE_X - light_bar_pos, DISPLAY_LIGHT_PROBAR_SIZE_Y, GFX_PIXEL_CLR); }
void temp_disp_init() { /* TODO: Replaced for testing // Initiate a temperature sensor reading ntc_measure(); */ // Initiate a ADCB reading adcb_ch0_measure(); adcb_ch1_measure(); adcb_ch2_measure(); adcb_ch3_measure(); // Struct for holding the temperature scale background tempscale.type = GFX_MONO_BITMAP_RAM; tempscale.width = 6; tempscale.height = 32; tempscale.data.pixmap = tempscale_img; // Screen border gfx_mono_draw_rect(0, 0, 128, 32, GFX_PIXEL_SET); // Clear screen gfx_mono_draw_filled_rect(1, 1, 126, 30, GFX_PIXEL_CLR); // Paint thermometer on screen // gfx_mono_put_bitmap(&tempscale, 10, 0); // TODO: Can be removed. /* TODO: Simply replaced for testing // wait for NTC data to ready while (!ntc_data_is_ready()); // Read the temperature once the ADC reading is done temperature = ntc_get_temperature(); */ // Wait for ADCB date to ready while (!adcb_data_is_ready()); temperature0 = adcb_chX_get_temperature(0);//adcb_ch0_get_raw_value(); temperature1 = adcb_chX_get_temperature(1); temperature2 = adcb_chX_get_temperature(2); temperature3 = adcb_chX_get_temperature(3); // Convert the temperature into the thermometer scale /* temp_scale = -0.36 * temperature + 20.25; if (temp_scale <= 0) { temp_scale = 0; } */ // Draw the scale element on top of the background temperature image /*gfx_mono_draw_filled_rect(12, 3, 2, temp_scale, GFX_PIXEL_CLR); */ /*snprintf(temperature_string, sizeof(temperature_string), "%3i C", temperature); // Draw the Celsius string gfx_mono_draw_string(temperature_string, 22, 13, &sysfont); */ // ********************** START UPDATE SCREEN ************************ snprintf(temp1_string, sizeof(temp1_string), "TMP1:%3iC", temperature0); snprintf(temp2_string, sizeof(temp2_string), "TMP2:%3iC", temperature1); snprintf(temp3_string, sizeof(temp3_string), "TMP3:%3iC", temperature2); snprintf(pressure_string, sizeof(pressure_string), "BAR:%3i", temperature3); // TODO: Set up variables and call methods for reading all the values // Draw the Celsius string gfx_mono_draw_string(temp1_string, 1, 5, &sysfont); // Temp1 gfx_mono_draw_string(temp2_string, 64, 5, &sysfont); // Temp2 gfx_mono_draw_string(temp3_string, 1, 20, &sysfont); // Temp3 gfx_mono_draw_string(pressure_string, 64, 20, &sysfont); // Pressure }