A simple alarm clock for the 1 day workshop presented by Skool and ARM Hungary in 2015.

Dependencies:   Skool_wkshp_lib2015 mbed

Revision:
2:e084bab7bc1c
Parent:
1:f76b625bd36e
Child:
4:2c4154aae49e
diff -r f76b625bd36e -r e084bab7bc1c mbed_clock.cpp
--- a/mbed_clock.cpp	Tue Sep 15 21:53:26 2015 +0000
+++ b/mbed_clock.cpp	Thu Sep 24 15:49:20 2015 +0000
@@ -1,110 +1,41 @@
 #include "mbed.h"
 #include "serial_lcd.h"
+#include "pc_uart.h"
+#include "rtc.h"
+#include "keypad.h"
+#include "menu.h"
 
-DigitalOut myled(LED1);             // On-board LED
-Serial pc(SERIAL_TX, SERIAL_RX);    // UART to communicate with PC
 DigitalOut R_LED(PA_10);            // RED part of the RGB LED
 DigitalOut G_LED(PB_5);             // GREEN part of the RGB LED
 DigitalOut B_LED(PA_9);             // BLUE part of the RGB LED
-DigitalOut LCD_RST(PB_10);          // LCD RST
-DigitalOut LCD_BL(PA_8);            // LCD BackLight
 PwmOut speaker(PB_4);               // Speaker
 
-I2C i2c1(I2C_SDA, I2C_SCL);         // I2C interface for LCD display
-
-
-// Define your own keypad values
-const char Keytable[] = { '1', '2', '3', 'A',   // r0
-                          '4', '5', '6', 'B',   // r1
-                          '7', '8', '9', 'C',   // r2
-                          '*', '0', '#', 'D'    // r3
-                        };
-                        // c0   c1   c2   c3
-const uint16_t rows[4] = {GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_8, GPIO_PIN_9};
-const uint16_t cols[4] = {GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12, 0xFFFF};
-//const int nrows = 4;
-const int ncols = 3;
-const char BCD2HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
-const char DOW[7][3] = { {'H',' ',' '}, {'K',' ',' '}, {'S','z','e'}, {'C','s',' '}, {'P',' ',' '}, {'S','z','o'}, {'V',' ',' '} };
-
-uint32_t Index = 0xFF;
-uint32_t new_key = 0;
 uint32_t Systck_cnt = 0;
 uint32_t Systck_evt = 0;
-GPIO_InitTypeDef keypadInit;
-
-void Error(int err) {
-    switch (err) {
-        case 0: pc.printf("\033[44m\033[37mI2C communication error!\033[00m\r\n");
-        break;
-        case 1: pc.printf("\033[44m\033[37mIncorrect calibration data error!\033[00m\r\n");
-        break;
-        default: pc.printf("\033[44m\033[37mUnknown error!\033[00m\r\n");
-        break;
-    }
-    while (1) {
-        myled = 1;
-        wait(0.1);
-        myled = !myled;
-        wait(0.1);
-        myled = !myled;
-        wait(0.1);
-        myled = !myled;
-        wait(2);
-    }
-}
 
-void EXTI9_5_IRQHandler(void) {
-    HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
-    if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_5) != 0) {
-        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_5);
-        HAL_GPIO_EXTI_Callback(0);
-    } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_6) != 0) {
-        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6);
-        HAL_GPIO_EXTI_Callback(1);
-    } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_7) != 0) {
-        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_7);
-        HAL_GPIO_EXTI_Callback(4);
-    } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_8) != 0) {
-        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8);
-        HAL_GPIO_EXTI_Callback(2);
-    } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_9) != 0) {
-        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_9);
-        HAL_GPIO_EXTI_Callback(3);
-    }
-    HAL_GPIO_WritePin(GPIOC, cols[0] | cols[1] | cols[2], GPIO_PIN_RESET);  // All cols are driven Low for resume IRQ operation
-    //NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
-    HAL_NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
-}
+extern uint32_t Index;
+extern uint32_t new_key;
+extern Serial pc;                   // UART to communicate with PC
+extern DigitalOut myled;            // On-board LED
+extern FSM_State Main_FSM_States;
+extern RTC_HandleTypeDef rtch;
+extern RTC_TimeTypeDef rtc_time;
+extern RTC_DateTypeDef rtc_date;
+extern RTC_AlarmTypeDef rtc_alarm;
+extern int tmp_date, tmp_sec;
+extern int AlarmA_Enabled;
+extern int AlarmA_triggered;
 
-void HAL_GPIO_EXTI_Callback(uint16_t pin) {
-    int col;
-    int temp;
+const float scala[38] = { 0.0f, 108.0f, 112.5f, 121.5f, 129.6f, 135.0f, 144.0f, 150.0f, 162.0f, 172.8f, 180.0f, 194.4f, 202.5f,
+                                216.0f, 225.0f, 243.0f, 259.2f, 270.0f, 288.0f, 300.0f, 324.0f, 345.6f, 360.0f, 388.8f, 405.0f,
+                                432.0f, 450.0f, 486.0f, 518.4f, 540.0f, 576.0f, 600.0f, 648.0f, 691.2f, 720.0f, 777.6f, 810.0f,
+                                864.0f };
 
-    for (col = 0; col < ncols; col++) {
-        HAL_GPIO_WritePin(GPIOC, cols[0] | cols[1] | cols[2], GPIO_PIN_SET);  // All cols are driven High
-        HAL_GPIO_WritePin(GPIOC, cols[col], GPIO_PIN_RESET);                  // 1 col is driven Low
-        wait_ms(50);
-        temp = GPIOC->IDR;
-        temp = (temp & 0x0360);
-        switch (temp) {
-            case 0x0340: Index = col;
-                         break;
-            case 0x0320: Index = 4 + col;
-                         break;
-            case 0x0260: Index = 8 + col;
-                         break;
-            case 0x0160: Index = 12 + col;
-                         break;
-            default:     Index = 0xFF;
-                         break;
-        }
-        if (Index != 0xFF) {
-            break;
-        }
-    }
-    new_key++;
-}
+const uint32_t song[54][2] = { {16, 4}, {18, 4}, {20, 4}, {18, 4}, {16, 2}, { 0, 2}, {16, 4}, {18, 4}, {20, 4}, {18, 4}, {16, 2}, { 0, 2}, {20, 4}, {20, 4}, {21, 4}, {21, 4},
+                               {20, 4}, {20, 4}, {18, 2}, {20, 4}, {20, 4}, {21, 4}, {21, 4}, {20, 4}, {20, 4}, {18, 2}, {20, 4}, {18, 4}, {20, 4}, {21, 4}, {23, 4}, {21, 4},
+                               {20, 4}, {18, 4}, {20, 4}, {18, 4}, {20, 4}, {21, 4}, {23, 4}, {21, 4}, {20, 4}, {18, 4}, {16, 4}, {18, 4}, {20, 4}, {18, 4}, {16, 2}, { 0, 2},
+                               {16, 4}, {18, 4}, {20, 4}, {18, 4}, {16, 2}, { 0, 2} };
+
 void SysTick_Handler(void) {
     HAL_SYSTICK_Callback();
 }
@@ -114,226 +45,45 @@
     Systck_evt++;
 }
 
-int write_ser_lcd(unsigned char data, bool mode) {
-    char wd[2];
-    int status;
-
-    wd[0] = ((mode) ? 0x40 : 0x00);
-    wd[1] = (char)data;
-    status = i2c1.write(ST7032I_ADDR, wd, 2, false);
-    return status;
-}
-
-void write_ser_text(unsigned char *text, uint32_t len) {
-    int i;
-    char wd[41];
-    int status;
-
-    wd[0] = 0x40;
-    for (i = 0; i < len; i++) {
-        wd[i + 1] = (char)text[i];
-    }
-    status = i2c1.write(ST7032I_ADDR, wd, len + 1, false);
-    if (status != 0) {
-        Error(0);
-    }
-}
-
-int init_ser_lcd(void) {
-    int status;
-
-    LCD_RST = 0x0;                  // Generating Reset pulse
-    LCD_BL = 0x0;                   // BackLight off
-//    BL_LCD = 0.0;
-    wait_us(200);
-    LCD_RST = 0x1;
-    wait_ms(40);
-    status = write_ser_lcd(0x38, false);     // Function set with IS = 0
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x39, false);     // Function set with IS = 1
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x14, false);     // Internal OSC frequency adjustment
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x79, false);     // Contrast set
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x5C, false);     // Power/Icon/Contrast control
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x6E, false);     // Follower control
-    if (status != 0) {
-        Error(0);
-    }
-    wait_ms(200);
-//    wait_us(30);
-    status = write_ser_lcd(0x0C, false);     // Display ON
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x01, false);     // Clear display
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x06, false);     // Entry mode set
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    status = write_ser_lcd(0x02, false);     // Home
-    if (status != 0) {
-        Error(0);
-    }
-    wait_us(30);
-    LCD_BL = 0x1;                   // BackLight ON
-//    BL_LCD = 0.5;
-    return 0;
-}
-
 int main() {
     uint32_t RGB_sel = 0;
-    uint32_t currentHclk;
     uint32_t dummy;
-
+    int i;
+    float tone;
 
-    HAL_StatusTypeDef HAL_status;
-    HAL_LockTypeDef HAL_lock;
-    RTC_HandleTypeDef rtch;
-    HAL_RTCStateTypeDef rtc_state;
-    RTC_InitTypeDef rtc_init;
-    RTC_TimeTypeDef rtc_time;
-    RTC_DateTypeDef rtc_date;
-    RTC_AlarmTypeDef rtc_alarm;
-    int tmp_date, tmp_sec;
-    
-    char tt[16];
-
+    speaker = 0;
     R_LED = 1;
     G_LED = 1;
     B_LED = 1;
 
-    rtc_init.AsynchPrediv = 0x7F;
-    rtc_init.SynchPrediv = 0xFF;
-    rtc_init.HourFormat = RTC_HOURFORMAT_24;
-    rtc_init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
-    rtc_init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
-    rtc_init.OutPut = RTC_OUTPUT_DISABLE;
-
-    rtc_date.Date = 13;
-    rtc_date.Month = 9;
-    rtc_date.WeekDay = 7;
-    rtc_date.Year = 15;
-    tmp_date = 13;
-
-    rtc_time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
-    rtc_time.Hours = 23;
-    rtc_time.Minutes = 58;
-    rtc_time.Seconds = 46;
-    rtc_time.StoreOperation =RTC_STOREOPERATION_SET;
-    tmp_sec = 0;
-
-    rtch.Instance = RTC;
-    rtch.Init = rtc_init;
-    rtch.Lock = HAL_lock;
-    rtch.State = rtc_state;
-
-
-    __PWR_CLK_ENABLE();
-    HAL_PWR_EnableBkUpAccess();
-//    __HAL_RTC_WRITEPROTECTION_DISABLE(&rtch);
-    __HAL_RCC_LSE_CONFIG(RCC_LSE_ON);
-    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
-    dummy = RCC->BDCR;
-    dummy |= RCC_BDCR_RTCEN;
-    RCC->BDCR = dummy;
-//    __HAL_RCC_RTC_ENABLE();
-    HAL_status = HAL_RTC_Init(&rtch);
-    pc.printf("HAL_Status: %d\r\n",HAL_status);
-    HAL_status = HAL_RTC_SetDate(&rtch, &rtc_date, FORMAT_BIN);
-    pc.printf("HAL_Status: %d\r\n",HAL_status);
-    HAL_status = HAL_RTC_SetTime(&rtch, &rtc_time, FORMAT_BIN);
-    pc.printf("HAL_Status: %d\r\n",HAL_status);
-
-    __GPIOC_CLK_ENABLE();
-    keypadInit.Pin = cols[0] | cols[1] | cols[2];
-    keypadInit.Mode = GPIO_MODE_OUTPUT_OD;
-    keypadInit.Pull = GPIO_NOPULL;
-    keypadInit.Speed = GPIO_SPEED_MEDIUM;
-    HAL_GPIO_Init(GPIOC, &keypadInit);
-
-    HAL_GPIO_WritePin(GPIOC, cols[0] | cols[1] | cols[2], GPIO_PIN_SET);
-    HAL_GPIO_WritePin(GPIOC, cols[2], GPIO_PIN_RESET);
-
-    keypadInit.Pin = rows[0] | rows[1] | rows[2] | rows[3];
-    keypadInit.Mode = GPIO_MODE_INPUT;
-    keypadInit.Pull = GPIO_PULLUP;
-    HAL_GPIO_Init(GPIOC, &keypadInit);
-    keypadInit.Pin = rows[3];
-    keypadInit.Mode = GPIO_MODE_IT_FALLING;
-    keypadInit.Pull = GPIO_PULLUP;
-    HAL_GPIO_Init(GPIOC, &keypadInit);
-    NVIC_SetVector(EXTI9_5_IRQn, (uint32_t)EXTI9_5_IRQHandler);
-    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
+    InitRTC();
+    Init_keypad();
 
     NVIC_SetVector(SysTick_IRQn, (uint32_t)SysTick_Handler);
     HAL_SYSTICK_Config(14400000);
 
     __enable_irq();
 
-    pc.printf("\f\033[00m\033[33mmbed Clock with STM32F303RE NUCLEO board\033[00m\r\n");
-    currentHclk = HAL_RCC_GetHCLKFreq();
-    pc.printf("Current HCLK is: %d\r\n",currentHclk);
-/*    speaker.period(1.0/864.0);
-    speaker = 0.5;
-    wait(0.1);
-    speaker = 0.0;
-*/
-
     init_ser_lcd();
     write_ser_lcd(0x80, false);     // set DDRAM addr to 0x00
-    write_ser_text((unsigned char *)"Hello", 5);
+    write_ser_text((char *)"  Alarm  clock  ", 16);
     write_ser_lcd(0xC0, false);     // set DDRAM addr to 0x40, beginning of 2nd line
-    write_ser_text((unsigned char *)"Teszt",5);
+    write_ser_text((char *)"ARM        SKOOL",16);
 
-    wait(2.0);
+    wait(3.0);
 
     write_ser_lcd(0x01, false);     // Clear display
-    wait_us(30);
+    wait_us(1100);
     write_ser_lcd(0x06, false);     // Entry mode set
     wait_us(30);
-    write_ser_lcd(0x80, false);     // set DDRAM addr to 0x00, beginning of 1st line
-    wait_us(30);
-    write_ser_text((unsigned char *)"2015.09.12. Szo", 15);
-    write_ser_lcd(0xC0, false);     // set DDRAM addr to 0x40, beginning of 2nd line
-    wait_us(30);
-    write_ser_text((unsigned char *)"23:24:56 23.2", 13);
-    write_ser_lcd(0xDF, true);
+    ShowTime();
+    ShowDate();
 
     while (1) {
         if (new_key != 0) {
-            if (Index < 0xFF) {
-                pc.printf("Key pressed: %c\r\n",Keytable[Index]);
-                write_ser_lcd(0xCF, false);     // set DDRAM addr to 0x4F, end of 2nd line
-                write_ser_lcd(Keytable[Index], true);
-            } else {
-                pc.printf("Incorrect Index value!\r\n");
-            }
-            if (new_key > 1) {
-                pc.printf("There were missed keys: %d\r\n",new_key);
+            if ((Index < 0xFF) & (Keytable[Index] == '#')) {
+                Main_FSM_States = IN_MENU;
+                MainMenu_Handler();
             }
             new_key = 0;
             Index = 0xFF;
@@ -344,47 +94,41 @@
         HAL_RTC_GetTime(&rtch, &rtc_time, FORMAT_BCD);
         HAL_RTC_GetDate(&rtch, &rtc_date, FORMAT_BCD);
         if (rtc_time.Seconds != tmp_sec) {
-            tt[0] = BCD2HEX[((rtc_time.Hours & 0xF0) >> 4)];
-            tt[1] = BCD2HEX[(rtc_time.Hours & 0x0F)];
-            tt[2] = ':';
-            tt[3] = BCD2HEX[((rtc_time.Minutes & 0xF0) >> 4)];
-            tt[4] = BCD2HEX[(rtc_time.Minutes & 0x0F)];
-            tt[5] = ':';
-            tt[6] = BCD2HEX[((rtc_time.Seconds & 0xF0) >> 4)];
-            tt[7] = BCD2HEX[(rtc_time.Seconds & 0x0F)];
-            tt[8] = 0x00;       // For printf
-            tmp_sec = rtc_time.Seconds;
-            write_ser_lcd(0xC0, false);
-            pc.printf("\033[3;0H"); // Move the cursur to the beginning of the 3rd line.
-            pc.printf(tt);
-            write_ser_text((unsigned char *)tt, 8);
+            ShowTime();
             dummy = 0;
 
             if (rtc_date.Date != tmp_date) {
-                tt[0] = BCD2HEX[2];
-                tt[1] = BCD2HEX[0];
-                tt[2] = BCD2HEX[((rtc_date.Year & 0xF0) >> 4)];
-                tt[3] = BCD2HEX[(rtc_date.Year & 0x0F)];
-                tt[4] = '.';
-                tt[5] = BCD2HEX[((rtc_date.Month & 0xF0) >> 4)];
-                tt[6] = BCD2HEX[(rtc_date.Month & 0x0F)];
-                tt[7] = '.';
-                tt[8] = BCD2HEX[((rtc_date.Date & 0xF0) >> 4)];
-                tt[9] = BCD2HEX[(rtc_date.Date & 0x0F)];
-                tt[10] = '.';
-                tmp_date = rtc_date.Date;
-                tt[11] = ' ';
-                tt[12] = DOW[rtc_date.WeekDay - 1][0];
-                tt[13] = DOW[rtc_date.WeekDay - 1][1];
-                tt[14] = DOW[rtc_date.WeekDay - 1][2];
-                tt[15] = 0x00;       // For printf
-                write_ser_lcd(0x80, false);
-                pc.printf("\033[4;0H"); // Move the cursur to the beginning of the 4th line.
-                pc.printf(tt);
-                write_ser_text((unsigned char *)tt,15);
+                ShowDate();
             }
         }
-        
+
+        if (AlarmA_triggered) {
+            AlarmA_triggered = 0;
+            ShowAlarmText();
+            for (i = 0; i < 54; i++) {
+                if (song[i][0] > 0.0f) {
+                    tone = float(1.0f/scala[song[i][0]]);
+                    speaker.period(tone);
+                    speaker = 0.5;
+                } else {
+                    speaker = 0;
+                }
+                wait(float(1.0f/song[i][1]));
+                if ((new_key != 0) & (Index < 0xFF) & (Keytable[Index] == '#')) {
+                    i = 54;
+                    new_key = 0;
+                    Index = 0xFF;
+                    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
+                }
+            }
+            write_ser_lcd(0x01, false);     // Clear display
+            wait_us(1100);
+            write_ser_lcd(0x06, false);     // Entry mode set
+            wait_us(30);
+            ShowTime();
+            ShowDate();
+        }
+
         if (Systck_cnt > 5) {
             switch (RGB_sel % 3) {
                 case 0: 
@@ -419,6 +163,3 @@
         Systck_evt = 0;
     }
 }
-
-
-