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

Dependencies:   Skool_wkshp_lib2015 mbed

mbed_clock.cpp

Committer:
lvagasi
Date:
2015-09-15
Revision:
1:f76b625bd36e
Parent:
0:28b9efbdeffc
Child:
2:e084bab7bc1c

File content as of revision 1:f76b625bd36e:

#include "mbed.h"
#include "serial_lcd.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);
}

void HAL_GPIO_EXTI_Callback(uint16_t pin) {
    int col;
    int temp;

    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++;
}
void SysTick_Handler(void) {
    HAL_SYSTICK_Callback();
}

void HAL_SYSTICK_Callback(void) {
    Systck_cnt++;
    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;


    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];

    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);

    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_lcd(0xC0, false);     // set DDRAM addr to 0x40, beginning of 2nd line
    write_ser_text((unsigned char *)"Teszt",5);

    wait(2.0);

    write_ser_lcd(0x01, false);     // Clear display
    wait_us(30);
    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);

    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);
            }
            new_key = 0;
            Index = 0xFF;
            HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
        }


        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);
            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);
            }
        }
        
        if (Systck_cnt > 5) {
            switch (RGB_sel % 3) {
                case 0: 
                    R_LED = 0;
                    G_LED = 1;
                    B_LED = 1;
                    break;
                case 1: 
                    R_LED = 1;
                    G_LED = 0;
                    B_LED = 1;
                    break;
                case 2: 
                    R_LED = 1;
                    G_LED = 1;
                    B_LED = 0;
                    break;
                default: 
                    R_LED = 1;
                    G_LED = 1;
                    B_LED = 1;
                    break;
            }
            RGB_sel++;
            Systck_cnt = 0;
        }
        //HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
        //__WFI();
        while (Systck_evt == 0) {
            dummy++;
        }
        Systck_evt = 0;
    }
}