- #include "asf.h"
- #include "stdio_serial.h"
- #include "conf_clock.h"
- #include "conf_board.h"
- /// [url=home.php?mod=space&uid=1302964]@cond[/url] 0
- /**INDENT-OFF**/
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**INDENT-ON**/
- /// @endcond
- /* Main menu is being displayed. */
- #define STATE_MENU 0
- /* Time is being edited. */
- #define STATE_SET_TIME 1
- /* Date is being edited. */
- #define STATE_SET_DATE 2
- /* Time alarm is being edited. */
- #define STATE_SET_TIME_ALARM 3
- /* Date alarm is being edited. */
- #define STATE_SET_DATE_ALARM 4
- /* Wave generating is being edited. */
- #define STATE_WAVEFORM 5
- /* Maximum size of edited string. */
- #define MAX_EDIT_SIZE 10
- /* Macro for converting char to digit. */
- #define char_to_digit(c) ((c) - '0')
- #define STRING_EOL "\r"
- #define STRING_HEADER "-- RTC Example --\r\n" \
- "-- "BOARD_NAME" --\r\n" \
- "-- Compiled: "__DATE__" "__TIME__" --"STRING_EOL
- /* Current state of application. */
- static uint32_t gs_ul_state = STATE_MENU;
- /* Edited hour. */
- static uint32_t gs_ul_new_hour;
- /* Edited minute. */
- static uint32_t gs_ul_new_minute;
- /* Edited second. */
- static uint32_t gs_ul_new_second;
- /* Edited year. */
- static uint32_t gs_ul_new_year;
- /* Edited month. */
- static uint32_t gs_ul_new_month;
- /* Edited day. */
- static uint32_t gs_ul_new_day;
- /* Edited day-of-the-week. */
- static uint32_t gs_ul_new_week;
- /* Indicate if alarm has been triggered and not yet cleared */
- static uint32_t gs_ul_alarm_triggered = 0;
- /* Time string */
- static uint8_t gs_uc_rtc_time[8 + 1] =
- { '0', '0', ':', '0', '0', ':', '0', '0', '\0' };
- /* Date string */
- static uint8_t gs_uc_date[10 + 1] =
- { '0', '0', '/', '0', '0', '/', '0', '0', '0', '0', '\0' };
- /* Week string */
- static uint8_t gs_uc_day_names[7][4] =
- { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
- /* Flag for refreshing menu */
- static uint32_t gs_ul_menu_shown = 0;
- /**
- * Configure UART console.
- */
- static void configure_console(void)
- {
- const usart_serial_options_t uart_serial_options = {
- .baudrate = CONF_UART_BAUDRATE,
- #ifdef CONF_UART_CHAR_LENGTH
- .charlength = CONF_UART_CHAR_LENGTH,
- #endif
- .paritytype = CONF_UART_PARITY,
- #ifdef CONF_UART_STOP_BITS
- .stopbits = CONF_UART_STOP_BITS,
- #endif
- };
- /* Configure console UART. */
- sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
- stdio_serial_init(CONF_UART, &uart_serial_options);
- }
- /**
- * \brief Get new time. Successful value is put in gs_ul_new_hour,
- * gs_ul_new_minute, gs_ul_new_second.
- */
- static uint32_t get_new_time(void)
- {
- uint8_t uc_key;
- uint32_t i = 0;
- /* Clear setting variable. */
- gs_ul_new_hour = 0xFFFFFFFF;
- gs_ul_new_minute = 0xFFFFFFFF;
- gs_ul_new_second = 0xFFFFFFFF;
- /* Use gs_uc_rtc_time[] as a format template. */
- while (1) {
- scanf("%c", (char *)&uc_key);
- /* End input */
- if (uc_key == 0x0d || uc_key == 0x0a) {
- puts("\r");
- break;
- }
- /* DEL or BACKSPACE */
- if (uc_key == 0x7f || uc_key == 0x08) {
- if (i > 0) {
- /* End of gs_uc_rtc_time[], then one more back of index */
- if (!gs_uc_rtc_time[i]) {
- --i;
- }
- puts("\b \b");
- --i;
- /* Delimiter ':' for time is uneditable */
- if (!((gs_uc_rtc_time[i]) >= '0' && (gs_uc_rtc_time[i]) <= '9')
- && i > 0) {
- puts("\b \b");
- --i;
- }
- }
- }
- /*
- * End of gs_uc_rtc_time[], no more input except the above DEL/BS,
- * or enter to end.
- */
- if (!gs_uc_rtc_time[i]) {
- continue;
- }
- printf("%c", uc_key);
- gs_uc_rtc_time[i++] = uc_key;
- }
- if (i == 0) {
- return 0;
- }
- if (i != 0 && gs_uc_rtc_time[i] != '\0') {
- /* Failure input */
- return 1;
- }
- gs_ul_new_hour = char_to_digit(gs_uc_rtc_time[0]) * 10 +
- char_to_digit(gs_uc_rtc_time[1]);
- gs_ul_new_minute = char_to_digit(gs_uc_rtc_time[3]) * 10 +
- char_to_digit(gs_uc_rtc_time[4]);
- gs_ul_new_second = char_to_digit(gs_uc_rtc_time[6]) * 10 +
- char_to_digit(gs_uc_rtc_time[7]);
- /* Success input. Verification of data is left to RTC internal Error Checking. */
- return 0;
- }
- /**
- * \brief Calculate week from year, month, day.
- */
- static uint32_t calculate_week(uint32_t ul_year, uint32_t ul_month,
- uint32_t ul_day)
- {
- uint32_t ul_week;
- if (ul_month == 1 || ul_month == 2) {
- ul_month += 12;
- --ul_year;
- }
- ul_week = (ul_day + 2 * ul_month + 3 * (ul_month + 1) / 5 + ul_year +
- ul_year / 4 - ul_year / 100 + ul_year / 400) % 7;
- ++ul_week;
- return ul_week;
- }
- /**
- * \brief Get new time. Successful value is put in gs_ul_new_year,
- * gs_ul_new_month, gs_ul_new_day, gs_ul_new_week.
- */
- static uint32_t get_new_date(void)
- {
- uint8_t uc_key;
- uint32_t i = 0;
- /* Clear setting variable */
- gs_ul_new_year = 0xFFFFFFFF;
- gs_ul_new_month = 0xFFFFFFFF;
- gs_ul_new_day = 0xFFFFFFFF;
- gs_ul_new_week = 0xFFFFFFFF;
- /* Use gs_uc_rtc_time[] as a format template */
- while (1) {
- scanf("%c", (char *)&uc_key);
- /* End input */
- if (uc_key == 0x0d || uc_key == 0x0a) {
- puts("\r");
- break;
- }
- /* DEL or BACKSPACE */
- if (uc_key == 0x7f || uc_key == 0x08) {
- if (i > 0) {
- /* End of date[], then one more back of index */
- if (!gs_uc_date[i]) {
- --i;
- }
- puts("\b \b");
- --i;
- /* Delimiter '/' for date is uneditable */
- if (!((gs_uc_date[i]) >= '0' && (gs_uc_date[i]) <='9')
- && i > 0) {
- puts("\b \b");
- --i;
- }
- }
- }
- /*
- * End of gs_uc_rtc_time[], no more input except the above DEL/BS,
- * or enter to end.
- */
- if (!gs_uc_date[i]) {
- continue;
- }
- printf("%c", uc_key);
- gs_uc_date[i++] = uc_key;
- }
- if (i == 0) {
- return 0;
- }
- if (i != 0 && gs_uc_date[i] != '\0' && i != 6) {
- /* Failure input */
- return 1;
- }
- /* MM-DD-YY */
- gs_ul_new_month = char_to_digit(gs_uc_date[0]) * 10
- + char_to_digit(gs_uc_date[1]);
- gs_ul_new_day = char_to_digit(gs_uc_date[3]) * 10
- + char_to_digit(gs_uc_date[4]);
- if (i != 6) {
- /* For 'Set Date' option, get the input new year and new week. */
- gs_ul_new_year = char_to_digit(gs_uc_date[6]) * 1000 +
- char_to_digit(gs_uc_date[7]) * 100 +
- char_to_digit(gs_uc_date[8]) * 10 +
- char_to_digit(gs_uc_date[9]);
- gs_ul_new_week = calculate_week(gs_ul_new_year, gs_ul_new_month,
- gs_ul_new_day);
- }
- /*
- * Success input. Verification of data is left to RTC internal Error
- * Checking.
- */
- return 0;
- }
- /**
- * \brief Display the user interface on the terminal.
- */
- static void refresh_display(void)
- {
- uint32_t ul_hour, ul_minute, ul_second;
- uint32_t ul_year, ul_month, ul_day, ul_week;
- if (gs_ul_state != STATE_MENU) {
- /* Not in menu display mode, in set mode. */
- } else {
- /* Retrieve date and time */
- rtc_get_time(RTC, &ul_hour, &ul_minute, &ul_second);
- rtc_get_date(RTC, &ul_year, &ul_month, &ul_day, &ul_week);
- /* Display */
- if (!gs_ul_menu_shown) {
- puts("\n\rMenu:\n\r"
- " t - Set time\n\r"
- " d - Set date\n\r"
- " i - Set time alarm\n\r"
- " m - Set date alarm\r");
- #if ((SAM3S8) || (SAM3SD8) || (SAM4S) || (SAM4C) || (SAM4CP) || (SAM4CM) || (SAMV71)|| (SAMV70) || (SAME70) || (SAMS70))
- puts(" w - Generate Waveform\r");
- #endif
- if (gs_ul_alarm_triggered) {
- puts(" c - Clear alarm notification\r");
- }
- printf("\n\r");
- gs_ul_menu_shown = 1;
- }
- /* Update current date and time */
- puts("\r");
- printf(" [Time/Date: %02u:%02u:%02u, %02u/%02u/%04u %s ][Alarm status:%s]",
- (unsigned int)ul_hour, (unsigned int)ul_minute, (unsigned int)ul_second,
- (unsigned int)ul_month, (unsigned int)ul_day, (unsigned int)ul_year,
- gs_uc_day_names[ul_week-1], gs_ul_alarm_triggered?"Triggered!":"");
- }
- }
- /**
- * \brief Interrupt handler for the RTC. Refresh the display.
- */
- void RTC_Handler(void)
- {
- uint32_t ul_status = rtc_get_status(RTC);
- /* Second increment interrupt */
- if ((ul_status & RTC_SR_SEC) == RTC_SR_SEC) {
- /* Disable RTC interrupt */
- rtc_disable_interrupt(RTC, RTC_IDR_SECDIS);
- refresh_display();
- rtc_clear_status(RTC, RTC_SCCR_SECCLR);
- rtc_enable_interrupt(RTC, RTC_IER_SECEN);
- } else {
- /* Time or date alarm */
- if ((ul_status & RTC_SR_ALARM) == RTC_SR_ALARM) {
- /* Disable RTC interrupt */
- rtc_disable_interrupt(RTC, RTC_IDR_ALRDIS);
- gs_ul_alarm_triggered = 1;
- refresh_display();
- /* Show additional menu item for clear notification */
- gs_ul_menu_shown = 0;
- rtc_clear_status(RTC, RTC_SCCR_ALRCLR);
- rtc_enable_interrupt(RTC, RTC_IER_ALREN);
- }
- }
- }
- /**
- * \brief Application entry point for RTC example.
- *
- * \return Unused (ANSI-C compatibility).
- */
- int main(void)
- {
- uint8_t uc_key;
- /* Initialize the SAM system */
- sysclk_init();
- board_init();
- /* Initialize the console uart */
- configure_console();
- /* Output example information */
- puts(STRING_HEADER);
- /* Default RTC configuration, 24-hour mode */
- rtc_set_hour_mode(RTC, 0);
- /* Configure RTC interrupts */
- NVIC_DisableIRQ(RTC_IRQn);
- NVIC_ClearPendingIRQ(RTC_IRQn);
- NVIC_SetPriority(RTC_IRQn, 0);
- NVIC_EnableIRQ(RTC_IRQn);
- rtc_enable_interrupt(RTC, RTC_IER_SECEN | RTC_IER_ALREN);
- /* Refresh display once */
- refresh_display();
- /* Handle keypresses */
- while (1) {
- scanf("%c", (char *)&uc_key);
- /* Set time */
- if (uc_key == 't') {
- gs_ul_state = STATE_SET_TIME;
- do {
- puts("\n\r\n\r Set time(hh:mm:ss): ");
- } while (get_new_time());
- /* If valid input, none of the variables for time is 0xff. */
- if (gs_ul_new_hour != 0xFFFFFFFF && (gs_uc_rtc_time[2] == ':')
- && (gs_uc_rtc_time[5] == ':')) {
- if (rtc_set_time(RTC, gs_ul_new_hour, gs_ul_new_minute,
- gs_ul_new_second)) {
- puts("\n\r Time not set, invalid input!\r");
- }
- } else {
- gs_uc_rtc_time[2] = ':';
- gs_uc_rtc_time[5] = ':';
- puts("\n\r Time not set, invalid input!\r");
- }
- gs_ul_state = STATE_MENU;
- gs_ul_menu_shown = 0;
- refresh_display();
- }
- /* Set date */
- if (uc_key == 'd') {
- gs_ul_state = STATE_SET_DATE;
- do {
- puts("\n\r\n\r Set date(mm/dd/yyyy): ");
- } while (get_new_date());
- /* If valid input, none of the variables for date is 0xff(ff). */
- if (gs_ul_new_year != 0xFFFFFFFF && (gs_uc_date[2] == '/')
- && (gs_uc_date[5] == '/')) {
- if (rtc_set_date(RTC, gs_ul_new_year, gs_ul_new_month,
- gs_ul_new_day, gs_ul_new_week)) {
- puts("\n\r Date not set, invalid input!\r");
- }
- } else {
- gs_uc_date[2] = '/';
- gs_uc_date[5] = '/';
- puts("\n\r Time not set, invalid input!\r");
- }
- /* Only 'mm/dd' is input. */
- if (gs_ul_new_month != 0xFFFFFFFF &&
- gs_ul_new_year == 0xFFFFFFFF) {
- puts("\n\r Not Set for no year field!\r");
- }
- gs_ul_state = STATE_MENU;
- gs_ul_menu_shown = 0;
- refresh_display();
- }
- /* Set time alarm */
- if (uc_key == 'i') {
- gs_ul_state = STATE_SET_TIME_ALARM;
- rtc_clear_date_alarm(RTC);
- do {
- puts("\n\r\n\r Set time alarm(hh:mm:ss): ");
- } while (get_new_time());
- if (gs_ul_new_hour != 0xFFFFFFFF && (gs_uc_rtc_time[2] == ':')
- && (gs_uc_rtc_time[5] == ':')) {
- if (rtc_set_time_alarm(RTC, 1, gs_ul_new_hour,
- 1, gs_ul_new_minute, 1, gs_ul_new_second)) {
- puts("\n\r Time alarm not set, invalid input!\r");
- } else {
- printf("\n\r Time alarm is set at %02u:%02u:%02u!",
- (unsigned int)gs_ul_new_hour, (unsigned int)gs_ul_new_minute,
- (unsigned int)gs_ul_new_second);
- }
- } else {
- gs_uc_rtc_time[2] = ':';
- gs_uc_rtc_time[5] = ':';
- puts("\n\r Time not set, invalid input!\r");
- }
- gs_ul_state = STATE_MENU;
- gs_ul_menu_shown = 0;
- gs_ul_alarm_triggered = 0;
- refresh_display();
- }
- /* Set date alarm */
- if (uc_key == 'm') {
- gs_ul_state = STATE_SET_DATE_ALARM;
- rtc_clear_time_alarm(RTC);
- do {
- puts("\n\r\n\r Set date alarm(mm/dd/yyyy): ");
- } while (get_new_date());
- if (gs_ul_new_year != 0xFFFFFFFF && (gs_uc_date[2] == '/')
- && (gs_uc_date[5] == '/')) {
- if (rtc_set_date_alarm(RTC, 1, gs_ul_new_month, 1,
- gs_ul_new_day)) {
- puts("\n\r Date alarm not set, invalid input!\r");
- } else {
- printf("\n\r Date alarm is set on %02u/%02u/%4u!",
- (unsigned int)gs_ul_new_month, (unsigned int)gs_ul_new_day,
- (unsigned int)gs_ul_new_year);
- }
- } else {
- gs_uc_date[2] = '/';
- gs_uc_date[5] = '/';
- puts("\n\r Date alarm not set, invalid input!\r");
- }
- gs_ul_state = STATE_MENU;
- gs_ul_menu_shown = 0;
- gs_ul_alarm_triggered = 0;
- refresh_display();
- }
- #if ((SAM3S8) || (SAM3SD8) || (SAM4S) || (SAM4C) || (SAM4CP) || (SAM4CM) || (SAMV71)|| (SAMV70) || (SAME70) || (SAMS70))
- /* Generate Waveform */
- if (uc_key == 'w') {
- gs_ul_state = STATE_WAVEFORM;
- puts("\n\rMenu:\n\r"
- " 0 - No Waveform\n\r"
- " 1 - 1 Hz square wave\n\r"
- " 2 - 32 Hz square wave\n\r"
- " 3 - 64 Hz square wave\n\r"
- " 4 - 512 Hz square wave\n\r"
- " 5 - Toggles when alarm flag rise\n\r"
- " 6 - Copy of the alarm flag\n\r"
- " 7 - Duty cycle programmable pulse\n\r"
- " 8 - Quit\r");
- while (1) {
- scanf("%c", (char *)&uc_key);
- if ((uc_key >= '0') && (uc_key <= '7')) {
- rtc_set_waveform(RTC, 0, char_to_digit(uc_key));
- }
- if (uc_key == '8') {
- gs_ul_state = STATE_MENU;
- gs_ul_menu_shown = 0;
- refresh_display();
- break;
- }
- }
- }
- #endif
- /* Clear trigger flag */
- if (uc_key == 'c') {
- gs_ul_alarm_triggered = 0;
- gs_ul_menu_shown = 0;
- refresh_display();
- }
- }
- }
- /// [url=home.php?mod=space&uid=1302964]@cond[/url] 0
- /**INDENT-OFF**/
- #ifdef __cplusplus
- }
- #endif
- /**INDENT-ON**/
- /// @endcond
运行结果: