|
@@ -0,0 +1,343 @@
|
|
|
|
+#include "main.h"
|
|
|
|
+#include "digits.h"
|
|
|
|
+#include "msg.h"
|
|
|
|
+#include "xprintf.h"
|
|
|
|
+
|
|
|
|
+/** Private macro, constatns */
|
|
|
|
+/* time constant in ms */
|
|
|
|
+#define BTN_SCAN_PERIOD 10
|
|
|
|
+#define BTN_SCAN_PAUSE 200
|
|
|
|
+#define BTN_TIME_PRESSED 30
|
|
|
|
+#define BTN_TIME_HOLDED 500
|
|
|
|
+#define BTN_TIME_REPEATED 50
|
|
|
|
+
|
|
|
|
+#define SW_SCAN_PERIOD 50
|
|
|
|
+#define SW_SCAN_PAUSE 100
|
|
|
|
+
|
|
|
|
+/* Display timeout, sec */
|
|
|
|
+#define DISP_WDT_TIME 15
|
|
|
|
+
|
|
|
|
+/** Privatetype defs */
|
|
|
|
+typedef struct t_btn {
|
|
|
|
+ int time;
|
|
|
|
+ es_event_t pressed;
|
|
|
|
+ es_event_t holded;
|
|
|
|
+ uint32_t pin;
|
|
|
|
+ GPIO_TypeDef * idr;
|
|
|
|
+} btn_t;
|
|
|
|
+
|
|
|
|
+typedef struct t_switch {
|
|
|
|
+ int time;
|
|
|
|
+ es_event_t ev_on;
|
|
|
|
+ es_event_t ev_off;
|
|
|
|
+ uint32_t pin;
|
|
|
|
+ GPIO_TypeDef * idr;
|
|
|
|
+} sw_t;
|
|
|
|
+
|
|
|
|
+/** Private variables */
|
|
|
|
+static rtc_t Clock;
|
|
|
|
+static i2c_status_t i2c_status;
|
|
|
|
+static btn_t Button[BTN_NUM] = {
|
|
|
|
+ {0, evBTN1Pressed, evBTN1Pressed, BTN1_PIN, BTN_PORT},
|
|
|
|
+ {0, evBTN2Pressed, evBTN2Pressed, BTN2_PIN, BTN_PORT},
|
|
|
|
+ {0, evBTN3Pressed, evBTN3Holded, BTN3_PIN, BTN_PORT}
|
|
|
|
+};
|
|
|
|
+static sw_t Switch[SWITCH_NUM] = {
|
|
|
|
+ {0, evSwitch1On, evSwitch1Off, SW1_PIN, SWITCH_PORT},
|
|
|
|
+ {0, evSwitch2On, evSwitch2Off, SW2_PIN, SWITCH_PORT},
|
|
|
|
+ {0, evSwitch3On, evSwitch3Off, SW3_PIN, SWITCH_PORT},
|
|
|
|
+ {0, evSwitch4On, evSwitch4Off, SW4_PIN, SWITCH_PORT},
|
|
|
|
+ {0, evSwitch5On, evSwitch5Off, SW5_PIN, SWITCH_PORT}
|
|
|
|
+};
|
|
|
|
+volatile static int dispWDT = 0;
|
|
|
|
+
|
|
|
|
+/** Privaate functions prototypes */
|
|
|
|
+static void buzer_On(void);
|
|
|
|
+static void buzer_Off(void);
|
|
|
|
+static void beep_Short(void);
|
|
|
|
+static void beep_Middle(void);
|
|
|
|
+static void beep_Long(void);
|
|
|
|
+static void beep_Repeated(void);
|
|
|
|
+static void btnProcess(void);
|
|
|
|
+static void switchProcess(void);
|
|
|
|
+static void dots_Off(void);
|
|
|
|
+
|
|
|
|
+/** Exported functions */
|
|
|
|
+
|
|
|
|
+void Clock_Init(void) {
|
|
|
|
+ beep_Short();
|
|
|
|
+ display_String(Msg_StartMsg, 1);
|
|
|
|
+
|
|
|
|
+ /* Real-Time clock */
|
|
|
|
+ i2c_status = RTC_Init();
|
|
|
|
+ if (i2c_status != I2C_Ret_OK) {
|
|
|
|
+ beep_Long();
|
|
|
|
+ display_String("RTC_Init Error\0", 1);
|
|
|
|
+ }
|
|
|
|
+ i2c_status = RTC_ReadTime(&Clock);
|
|
|
|
+ if (i2c_status != I2C_Ret_OK) {
|
|
|
|
+ beep_Long();
|
|
|
|
+ display_String("RTC_ReadTime Error\0", 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ show_Time();
|
|
|
|
+
|
|
|
|
+ /** Set tasks for Sheduler */
|
|
|
|
+ RTOS_SetTask(btnProcess, BTN_SCAN_PERIOD, BTN_SCAN_PERIOD);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void new_Second(void) {
|
|
|
|
+ ES_PlaceEvent(evNewSecond);
|
|
|
|
+
|
|
|
|
+ i2c_status = RTC_ReadAll(&Clock);
|
|
|
|
+ if (i2c_status != I2C_Ret_OK) {
|
|
|
|
+ display_String("RTC_ReadAll: I2C Error\0", 2);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // check display watch dog timer
|
|
|
|
+ if (dispWDT != 0) {
|
|
|
|
+ dispWDT--;
|
|
|
|
+ if (dispWDT == 0) {
|
|
|
|
+ ES_PlaceEvent(evDisplayWDT);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Process buttons.
|
|
|
|
+ */
|
|
|
|
+static void btnProcess(void) {
|
|
|
|
+ /* get pin state */
|
|
|
|
+ uint32_t pins = BTNS_STATE;
|
|
|
|
+
|
|
|
|
+ int i;
|
|
|
|
+ for (i=0; i<BTN_NUM; i++) {
|
|
|
|
+ if ((pins & Button[i].pin) == 0) {
|
|
|
|
+ /* button pressed */
|
|
|
|
+ beep_Short();
|
|
|
|
+ Button[i].time ++;
|
|
|
|
+ if (Button[i].time >= (BTN_TIME_HOLDED/BTN_SCAN_PERIOD)) {
|
|
|
|
+ Button[i].time -= (BTN_TIME_REPEATED/BTN_SCAN_PERIOD);
|
|
|
|
+ if (Button[i].holded == Button[i].pressed) {
|
|
|
|
+ /* if pressed and holded - same function, then button pressed auto repeat */
|
|
|
|
+ ES_PlaceEvent(Button[i].pressed);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (Button[i].time != 0) {
|
|
|
|
+ /* button released */
|
|
|
|
+ if (Button[i].time >= ((BTN_TIME_HOLDED - BTN_TIME_REPEATED)/BTN_SCAN_PERIOD)) {
|
|
|
|
+ /* process long press */
|
|
|
|
+ ES_PlaceEvent(Button[i].holded);
|
|
|
|
+ } else if (Button[i].time >= (BTN_TIME_PRESSED/BTN_SCAN_PERIOD)) {
|
|
|
|
+ /* process short press */
|
|
|
|
+ ES_PlaceEvent(Button[i].pressed);
|
|
|
|
+ }
|
|
|
|
+ Button[i].time = 0;
|
|
|
|
+ RTOS_SetTask(btnProcess, BTN_SCAN_PAUSE, BTN_SCAN_PERIOD);
|
|
|
|
+ }
|
|
|
|
+ } /* end FOR */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void switchProcess(void) {
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Show Time. Use 4x7 digits
|
|
|
|
+ */
|
|
|
|
+void show_Time(void) {
|
|
|
|
+ display_Wait4Display();
|
|
|
|
+
|
|
|
|
+ if (Clock.Sec == 0x0) {
|
|
|
|
+ char buf[16] = {0};
|
|
|
|
+ xsprintf(buf, "%x %s. %02x %s.\0", Clock.Hr, Msg_god, Clock.Min, Msg_hv);
|
|
|
|
+ display_String(buf, 2);
|
|
|
|
+ } else {
|
|
|
|
+ uint8_t t;
|
|
|
|
+ // dots blink
|
|
|
|
+ display_WriteData(&digit_4x7[10][0], 10, 4);
|
|
|
|
+ RTOS_SetTask(dots_Off, 500, 0);
|
|
|
|
+
|
|
|
|
+ t = Clock.Hr >> 4;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 1, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Hr & 0xf;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 6, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Min >> 4;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 14, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Min & 0xf;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 19, 4);
|
|
|
|
+
|
|
|
|
+ display_WriteBuffer();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Show MM:SS. Use 4x7 digits
|
|
|
|
+ */
|
|
|
|
+void show_MMSS(void) {
|
|
|
|
+ display_Wait4Display();
|
|
|
|
+
|
|
|
|
+ uint8_t t;
|
|
|
|
+ // dots on
|
|
|
|
+ display_WriteData(&digit_4x7[10][0], 10, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Min >> 4;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 1, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Min & 0xf;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 6, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Sec >> 4;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 14, 4);
|
|
|
|
+
|
|
|
|
+ t = Clock.Sec & 0xf;
|
|
|
|
+ display_WriteData(&digit_4x7[t][0], 19, 4);
|
|
|
|
+
|
|
|
|
+ display_WriteBuffer();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void show_Date(void) {
|
|
|
|
+ dispWDT = DISP_WDT_TIME;
|
|
|
|
+ display_Wait4Display();
|
|
|
|
+
|
|
|
|
+ char buf[26] = {0};
|
|
|
|
+ xsprintf(buf, "%s, %d %s, 20%02d %s.\0", Msg_WD_Full[Clock.WD], Clock.Day, Msg_Mon_Full[Clock.Mon], Clock.Year, Msg_rik);
|
|
|
|
+ display_String(buf, 3);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void setTimeShow(void) {}
|
|
|
|
+void setTimeBegin(void) {}
|
|
|
|
+void setHHBegin(void) {}
|
|
|
|
+void setHHInc(void) {}
|
|
|
|
+void setHHDec(void) {}
|
|
|
|
+void setMMBegin(void) {}
|
|
|
|
+void setMMInc(void) {}
|
|
|
|
+void setMMDec(void) {}
|
|
|
|
+void setTimeEnd(void) {}
|
|
|
|
+
|
|
|
|
+void setDateBegin(void) {}
|
|
|
|
+void setDateEnd(void) {}
|
|
|
|
+void setWDBegin(void) {}
|
|
|
|
+void setMDBegin(void) {}
|
|
|
|
+void setMonthBegin(void) {}
|
|
|
|
+void setYearBegin(void) {}
|
|
|
|
+void setWDShow(void) {}
|
|
|
|
+void setDMShow(void) {}
|
|
|
|
+void setYearShow(void) {}
|
|
|
|
+void setIncWDay(void) {}
|
|
|
|
+void setIncMDay(void) {}
|
|
|
|
+void setIncMonth(void) {}
|
|
|
|
+void setIncYear(void) {}
|
|
|
|
+void setDecWDay(void) {}
|
|
|
|
+void setDecMDay(void) {}
|
|
|
|
+void setDecMonth(void) {}
|
|
|
|
+void setDecYear(void) {}
|
|
|
|
+
|
|
|
|
+/** Private functions */
|
|
|
|
+
|
|
|
|
+static void dots_Off(void) {
|
|
|
|
+ display_Wait4Display();
|
|
|
|
+
|
|
|
|
+ display_Buffer[11] = 0x0;
|
|
|
|
+ display_Buffer[12] = 0x0;
|
|
|
|
+ display_WriteBuffer();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Buzzer control: On.
|
|
|
|
+ */
|
|
|
|
+static void buzer_On(void) {
|
|
|
|
+ BUZER_ON;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Buzzer control: Off.
|
|
|
|
+ */
|
|
|
|
+static void buzer_Off(void) {
|
|
|
|
+ BUZER_OFF;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Short beep
|
|
|
|
+ */
|
|
|
|
+static void beep_Short(void) {
|
|
|
|
+ BUZER_ON;
|
|
|
|
+ RTOS_SetTask(buzer_Off, 50, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Middle beep
|
|
|
|
+ */
|
|
|
|
+static void beep_Middle(void) {
|
|
|
|
+ BUZER_ON;
|
|
|
|
+ RTOS_SetTask(buzer_Off, 250, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Long beep
|
|
|
|
+ */
|
|
|
|
+static void beep_Long(void) {
|
|
|
|
+ BUZER_ON;
|
|
|
|
+ RTOS_SetTask(buzer_Off, 1000, 0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief Repeated beep-beep
|
|
|
|
+ * Звук "пи-пи...пи-пи...":
|
|
|
|
+ * - две посылки по 125 мс,
|
|
|
|
+ * - пауза внутри посылки 63 мс,
|
|
|
|
+ * - пауза между посылками 689 мс,
|
|
|
|
+ * - частота заполнения 4 кГц,
|
|
|
|
+ * - период 1 секунда.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+static void beep_Repeated(void) {
|
|
|
|
+ static int stat = 0;
|
|
|
|
+
|
|
|
|
+ switch (stat) {
|
|
|
|
+ case 0:
|
|
|
|
+ stat = 1;
|
|
|
|
+ BUZER_ON;
|
|
|
|
+ RTOS_SetTask(beep_Repeated, 125, 0);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 1:
|
|
|
|
+ stat = 2;
|
|
|
|
+ BUZER_OFF;
|
|
|
|
+ RTOS_SetTask(beep_Repeated, 63, 0);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 2:
|
|
|
|
+ stat = 3;
|
|
|
|
+ BUZER_ON;
|
|
|
|
+ RTOS_SetTask(beep_Repeated, 125, 0);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 3:
|
|
|
|
+ stat = 0;
|
|
|
|
+ BUZER_OFF;
|
|
|
|
+ RTOS_SetTask(beep_Repeated, 687, 0);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ BUZER_OFF;
|
|
|
|
+ stat = 0;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @brief This function handles EXTI line 4 to 15 interrupts.
|
|
|
|
+ */
|
|
|
|
+void EXTI4_15_IRQHandler(void)
|
|
|
|
+{
|
|
|
|
+ if ((EXTI->PR & EXTI_IMR_IM12) != 0)
|
|
|
|
+ {
|
|
|
|
+ EXTI->PR = EXTI_IMR_IM12;
|
|
|
|
+ //Flag.RTC_IRQ = 1;
|
|
|
|
+ RTOS_SetTask(new_Second, 0, 0);
|
|
|
|
+ }
|
|
|
|
+}
|