Jelajahi Sumber

Added: Event system, Clock module.

Vladimir N. Shilov 2 tahun lalu
induk
melakukan
cf5adf6d96
12 mengubah file dengan 841 tambahan dan 251 penghapusan
  1. 110 94
      Makefile
  2. 25 3
      inc/board.h
  3. 37 0
      inc/clock.h
  4. 28 0
      inc/event-system.h
  5. 8 8
      inc/font.h
  6. 50 0
      inc/list_event.h
  7. 2 3
      inc/main.h
  8. 18 1
      inc/msg.h
  9. 0 27
      src/board.c
  10. 343 0
      src/clock.c
  11. 209 0
      src/event-system.c
  12. 11 115
      src/main.c

+ 110 - 94
Makefile

@@ -1,99 +1,127 @@
-######################################
-# STM32F0xx Makefile
-######################################
+##########################################################################################################################
+# File automatically-generated by tool: [projectgenerator] version: [3.11.2] date: [Fri Feb 05 08:10:39 EET 2021] 
+##########################################################################################################################
+
+# ------------------------------------------------
+# Generic Makefile (based on gcc)
+#
+# ChangeLog :
+#	2017-02-10 - Several enhancements + project update mode
+#	2015-07-22 - first version
+# ------------------------------------------------
 
 ######################################
 # target
 ######################################
 TARGET = El12
 
-######################################
-# programmator
-######################################
-PROGRAMMATOR = "C:/ARM/STMicroelectronics/STM32 ST-LINK Utility/ST-LINK Utility/ST-LINK_CLI.exe"
 
 ######################################
 # building variables
 ######################################
 # debug build?
 DEBUG = 0
+# optimization
+OPT = -O2
+OPT += -ffunction-sections -fdata-sections
+OPT += -fno-strict-aliasing -funsigned-char
+OPT += -ffast-math -msoft-float -mfloat-abi=soft
+OPT += -fomit-frame-pointer -falign-functions=16
 
 #######################################
 # paths
 #######################################
-# source path
-VPATH = src MCU
-# firmware library path
-PERIPHLIBPATH = MCU
-VPATH += $(PERIPHLIBPATH)/CMSIS/Device/ST/STM32F0xx/Source
 # Build path
 BUILD_DIR = build
 
-# #####################################
+######################################
 # source
-# #####################################
-SRCS = \
-  main.c \
-  board.c \
-  rtos.c \
-  i2c.c \
-  ds3231.c \
-  display.c \
-  xprintf.c \
-  system_stm32f0xx.c
- 
-SRCSASM = startup_stm32f030x6.s
+######################################
+# C sources
+C_SOURCES = \
+src/main.c \
+src/board.c \
+src/rtos.c \
+src/i2c.c \
+src/ds3231.c \
+src/display.c \
+src/xprintf.c \
+src/event-system.c \
+src/clock.c \
+MCU/system_stm32f0xx.c
+
+# ASM sources
+ASM_SOURCES =  \
+MCU/startup_stm32f030x6.s
 
-# #####################################
-# firmware library
-# #####################################
-PERIPHLIB_SOURCES = 
 
 #######################################
 # binaries
 #######################################
-CC = arm-none-eabi-gcc
-AS = arm-none-eabi-gcc -x assembler-with-cpp
-CP = arm-none-eabi-objcopy
-AR = arm-none-eabi-ar
-SZ = arm-none-eabi-size
+PREFIX = arm-none-eabi-
+# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
+# either it can be added to the PATH environment variable.
+#GCC_PATH = "C:/ChibiStudio/tools/GNU Tools ARM Embedded/7.0 2017q4/bin"
+ifdef GCC_PATH
+CC = $(GCC_PATH)/$(PREFIX)gcc
+AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
+CP = $(GCC_PATH)/$(PREFIX)objcopy
+SZ = $(GCC_PATH)/$(PREFIX)size
+else
+CC = $(PREFIX)gcc
+AS = $(PREFIX)gcc -x assembler-with-cpp
+CP = $(PREFIX)objcopy
+SZ = $(PREFIX)size
+endif
 HEX = $(CP) -O ihex
 BIN = $(CP) -O binary -S
  
 #######################################
 # CFLAGS
 #######################################
+# cpu
+CPU = -mcpu=cortex-m0
+
+# fpu
+# NONE for Cortex-M0/M0+/M3
+
+# float-abi
+
+
+# mcu
+MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
+
 # macros for gcc
-DEFS = -DSTM32F030 -DSTM32F030x6
+# AS defines
+AS_DEFS = 
 
-ifeq ($(DEBUG), 1)
-DEFS += -DDEBUG -D_DEBUG
-endif
+# C defines
+C_DEFS = -DSTM32F030x6
 
-# includes for gcc
-INCLUDES = -I./inc
-INCLUDES += -I$(PERIPHLIBPATH)/CMSIS/Include
-INCLUDES += -I$(PERIPHLIBPATH)/CMSIS/Device/ST/STM32F0xx/Include
 
-# optimization
-ifeq ($(DEBUG), 1)
-OPT = -O0 -ggdb
-else
-OPT = -O2
-endif
-OPT += -ffunction-sections -fdata-sections -funsigned-char
-OPT += -fomit-frame-pointer -falign-functions=16
-OPT += -fno-strict-aliasing -ffast-math -msoft-float -mfloat-abi=soft
+# AS includes
+AS_INCLUDES = 
+
+# C includes
+C_INCLUDES = -I./inc
+C_INCLUDES += -IMCU/CMSIS/Include
+C_INCLUDES += -IMCU/CMSIS/Device/ST/STM32F0xx/Include
+
 
 # compile gcc flags
-CFLAGS = -mthumb -mcpu=cortex-m0 -mtune=cortex-m0 $(DEFS) $(INCLUDES) $(OPT)
+ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall
+
+CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall
+
 ifeq ($(DEBUG), 1)
 CFLAGS += -g -gdwarf-2
 endif
 
+
 # Generate dependency information
-CFLAGS += -MD -MP -MF .dep/$(@F).d
-CFLAGS += -std=gnu99 -Wall -pedantic
+CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
+CFLAGS += -std=gnu11 -pedantic -Wall
+
 
 #######################################
 # LDFLAGS
@@ -102,67 +130,55 @@ CFLAGS += -std=gnu99 -Wall -pedantic
 LDSCRIPT = MCU/STM32F030K6_FLASH.ld
 
 # libraries
-LIBS = -lc -lm -lnosys
-LIBDIR =
-LDFLAGS = -mthumb -mcpu=cortex-m0 -specs=nano.specs -T$(LDSCRIPT) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
-
+LIBS = -lc -lm -lnosys 
+LIBDIR = 
+LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
 
 # default action: build all
 all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex
-load: $(BUILD_DIR)/$(TARGET).hex mcu_prog
+
 
 #######################################
 # build the application
 #######################################
-# list of firmware library objects
-PERIPHLIB_OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(PERIPHLIB_SOURCES:.c=.o)))
-
-# list of C program objects
-OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(SRCS:.c=.o)))
-
+# list of objects
+OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
+vpath %.c $(sort $(dir $(C_SOURCES)))
 # list of ASM program objects
-OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(SRCSASM:.s=.o)))
+OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
+vpath %.s $(sort $(dir $(ASM_SOURCES)))
 
 $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
 	@echo Compiling: $<
-	@$(CC) -c $(CFLAGS) $< -o $@
+	@$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
 
 $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
-	@echo Compiling asm: $<
+	@echo Compiling: $<
 	@$(AS) -c $(CFLAGS) $< -o $@
 
-$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(PERIPHLIB_OBJECTS) Makefile
+$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
+	@echo 
 	@echo Linking: $@
-	@$(CC) $(OBJECTS) $(PERIPHLIB_OBJECTS) $(LDFLAGS) -o $@
-	@echo '--------------------------------------------------------------------'
+	@$(CC) $(OBJECTS) $(LDFLAGS) -o $@
+#	@echo ------------------------------------------------------------
 	@$(SZ) $@
-	@rm -f $(BUILD_DIR)/*.o
-	
+
 $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
+	@echo 
+	@echo Makeing HEX: $@
 	@$(HEX) $< $@
 	
+#$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
+#	$(BIN) $< $@	
+	
 $(BUILD_DIR):
-	@mkdir -p $@
-
+	mkdir $@		
 
 #######################################
-# Load firmware
-#######################################
-mcu_prog:
-	@$(PROGRAMMATOR) -c SWD -ME
-	@$(PROGRAMMATOR) -c SWD -P "$(BUILD_DIR)/$(TARGET).hex" -V "$(BUILD_DIR)/$(TARGET).hex" -Q -Rst -Run
- 
-#######################################
-# reset mcu
-#######################################
-mcu_reset:
-	@$(PROGRAMMATOR) -c SWD -Rst -Run
-
-#######################################
-# delete all user application files
+# clean up
 #######################################
 clean:
-	@-rm -fR .dep $(BUILD_DIR)
+	-rm -fR $(BUILD_DIR)
   
 #######################################
 # custom
@@ -172,9 +188,9 @@ flash: all
 
 default: all
 
-#
-# Include the dependency files, should be the last of the makefile
-#
--include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+#######################################
+# dependencies
+#######################################
+-include $(wildcard $(BUILD_DIR)/*.d)
 
 # *** EOF ***

+ 25 - 3
inc/board.h

@@ -13,10 +13,35 @@ typedef enum {
 
 
 /* Defines */
+#define BTN_NUM     3
+#define SWITCH_NUM  5
+#define BTN_PORT    GPIOA
+#define SWITCH_PORT GPIOA
+#define BTN1_PIN    GPIO_IDR_0
+#define BTN2_PIN    GPIO_IDR_1
+#define BTN3_PIN    GPIO_IDR_4
+#define SW1_PIN     GPIO_IDR_2
+#define SW2_PIN     GPIO_IDR_3
+#define SW3_PIN     GPIO_IDR_5
+#define SW4_PIN     GPIO_IDR_7
+#define SW5_PIN     GPIO_IDR_6
+
 /* Exported macros */
 #define BUZER_ON    TIM1->CR1 |= TIM_CR1_CEN
 #define BUZER_OFF   TIM1->CR1 &= ~TIM_CR1_CEN
 
+#define BTN1_STATE  (BTN_PORT->IDR & BTN1_PIN)
+#define BTN2_STATE  (BTN_PORT->IDR & BTN2_PIN)
+#define BTN3_STATE  (BTN_PORT->IDR & BTN3_PIN)
+#define SW1_STATE   (SWITCH_PORT->IDR & SW1_PIN)
+#define SW2_STATE   (SWITCH_PORT->IDR & SW2_PIN)
+#define SW3_STATE   (SWITCH_PORT->IDR & SW3_PIN)
+#define SW4_STATE   (SWITCH_PORT->IDR & SW4_PIN)
+#define SW5_STATE   (SWITCH_PORT->IDR & SW5_PIN)
+#define BTNS_STATE  (BTN_PORT->IDR & (BTN1_PIN | BTN2_PIN | BTN3_PIN))
+#define SWS_STATE   (SWITCH_PORT->IDR & (SW1_PIN | SW2_PIN | SW3_PIN | SW4_PIN | SW5_PIN))
+
+
 /* Display macros */
 #define HT1632C_CS_ON     GPIOA->BRR = (1<<15)
 #define HT1632C_CS_OFF    GPIOA->BSRR = (1<<15)
@@ -27,11 +52,8 @@ typedef enum {
 
 /* Exported funcions */
 void Board_Init(void);
-void EXTI4_15_IRQHandler(void);
 void DMA1_Channel2_3_IRQHandler(void);
 void I2C1_IRQHandler(void);
-void buzer_On(void);
-void buzer_Off(void);
 void GPIO_SPI_SW(void);
 void GPIO_SPI_HW(void);
 

+ 37 - 0
inc/clock.h

@@ -0,0 +1,37 @@
+#pragma once
+
+void Clock_Init(void);
+void new_Second(void);
+void EXTI4_15_IRQHandler(void);
+
+void show_Time(void);
+void show_MMSS(void);
+void show_Date(void);
+
+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);

+ 28 - 0
inc/event-system.h

@@ -0,0 +1,28 @@
+/**
+ *
+ *  Author(s)...: Pashgan    http://ChipEnable.Ru
+ *  Target(s)...: any MCU
+ *  Compiler....: IAR 5.11A
+ *  Description.: Template for tables based event system
+ *  Data........: 30.09.12
+ *
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#pragma once
+#ifndef EVENT_SYSTEM_H
+#define EVENT_SYSTEM_H
+
+#include "main.h"
+#include "list_event.h"
+
+#define SIZE_BUF 50
+
+void ES_Init(es_state_t init_state);
+es_state_t ES_GetState(void);
+void ES_SetState(es_state_t new_state);
+es_event_t ES_GetEvent(void);
+void ES_PlaceEvent(es_event_t event);
+void ES_Dispatch(es_event_t event);
+
+#endif /* EVENT_SYSTEM_H */

+ 8 - 8
inc/font.h

@@ -547,8 +547,8 @@ static const uint8_t Font_6x8[256][6] =
   // 0xae - псевдографика - закрашенная левая половина знакоместа.
   {0xff, 0xff, 0xff, 0x00, 0x00, 0x00},
 
-  // 0xaf - псевдографика - закрашенная правая половина знакоместа.
-  {0x00, 0x00, 0x00, 0xff, 0xff, 0xff},
+  // 0xaf - 'I' с двумя точками вверху.
+  {0x00, 0x01, 0x40, 0x7e, 0x40, 0x01},
 
   // 0xb0 - псевдографика - закрашенная верхняя половина знакоместа.
   {0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
@@ -559,11 +559,11 @@ static const uint8_t Font_6x8[256][6] =
   // 0xb2 - зеркальная 'э'.
   {0x00, 0x38, 0x54, 0x54, 0x44, 0x28},
 
-  // 0xb3 - 'I' с двумя точками вверху.
-  {0x00, 0x01, 0x40, 0x7e, 0x40, 0x01},
+  // 0xb3 - ukrainian 'i'
+  {0x00, 0x00, 0x00, 0x7d, 0x40, 0x00},
 
-  // 0xb4 - 'i' с двумя точками вверху.
-  {0x00, 0x00, 0x01, 0x7c, 0x41, 0x00},
+  // 0xb4 - пустое знакоместо.
+  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
 
   // 0xb5 - 'Y' с тильдой вверху ('~').
   {0x00, 0x27, 0x48, 0x4b, 0x48, 0x3f},
@@ -595,8 +595,8 @@ static const uint8_t Font_6x8[256][6] =
   // 0xbe - закрашенный квадрат по центру.
   {0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00},
 
-  // 0xbf - пустое знакоместо.
-  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+  // 0xb4 - 'i' с двумя точками вверху.
+  {0x00, 0x00, 0x01, 0x7c, 0x41, 0x00},
 
   // 0xc0 - 'А'.
   {0x00, 0x7e, 0x11, 0x11, 0x11, 0x7e},

+ 50 - 0
inc/list_event.h

@@ -0,0 +1,50 @@
+#pragma once
+#ifndef EVENT_LIST_H
+#define EVENT_LIST_H
+
+/* Event codes */
+typedef enum {
+  eventNull = 0x00,
+  evNewSecond,
+  evBTN1Pressed,
+  evBTN2Pressed,
+  evBTN3Pressed,
+  evBTN1Holded,
+  evBTN2Holded,
+  evBTN3Holded,
+  evSwitch1On,
+  evSwitch1Off,
+  evSwitch2On,
+  evSwitch2Off,
+  evSwitch3On,
+  evSwitch3Off,
+  evSwitch4On,
+  evSwitch4Off,
+  evSwitch5On,
+  evSwitch5Off,
+  evRefreshCal,
+  evDisplayWDT,
+  evLastEvent
+} es_event_t;
+
+/* State codes */
+typedef enum {
+  stNoChange = 0x00,
+  stShowTime,
+  stShowMMSS,
+  stShowDate,
+  stSetHH,
+  stSetMM,
+  stSetWD,
+  stSetMD,
+  stSetMon,
+  stSetYear,
+  /* end */
+  stLastState
+} es_state_t;
+
+#ifndef NULL
+  #define NULL ((void*)0)
+#endif
+
+#endif

+ 2 - 3
inc/main.h

@@ -25,9 +25,8 @@ extern "C" {
 #include "i2c.h"
 #include "ds3231.h"
 #include "display.h"
-//#include "event-system.h"
-//#include "list_event.h"
-//#include "clock.h"
+#include "event-system.h"
+#include "clock.h"
 
 /* Exported types ------------------------------------------------------------*/
 typedef enum {

+ 18 - 1
inc/msg.h

@@ -2,10 +2,27 @@
 #ifndef _MSG_H_
 #define _MSG_H_
 
-static const char Msg_StartMsg[] = "Ýëåêòðîíèêà Àëüôà 12-41\0";
+static const char Msg_StartMsg[] = "Ýëåêòðîíèêà Àëüôà 12-41¯\0";
 
 static const char Msg_god[] = "ãîä\0";
 static const char Msg_hv[] = "õâ\0";
+static const char Msg_rik[] = "ð³ê\0";
+
+static const char Msg_WD_Short[7][4] = { 
+"Íåä\0", "Ïíä\0", "Âòð\0", "Ñðä\0", "×òâ\0", "Ïòí\0", "Ñáò\0"
+};
+static const char Msg_WD_Full[7][10] = { 
+"Íåä³ëÿ\0   ", "Ïîíåä³ëîê\0", "³âòîðîê\0 ", "Ñåðåäà\0   ", "×åòâåð\0   ", "Ï'ÿòíèöÿ\0 ", "Ñóáîòà\0   "
+};
+
+static const char Msg_Mon_Short[12][4] = { 
+"ѳ÷\0", "Ëþò\0", "Áåð\0", "Êâò\0", "Òðâ\0", "×ðâ\0",
+"Ëïí\0", "Ñðï\0", "Âðñ\0", "Æâò\0", "Ëñò\0", "Ãðä\0"
+};
+static const char Msg_Mon_Full[12][9] = { 
+"ѳ÷åíü\0  ", "Ëþòèé\0   ", "Áåðåçåíü\0", "Êâ³òåíü\0 ", "Òðàâåíü\0 ", "×åðâåíü\0 ",
+"Ëèïåíü\0  ", "Ñåðïåíü\0 ", "Âåðåñåíü\0", "Æîâòåíü\0 ", "Ëèñòîïàä\0", "Ãðóäåíü\0 "
+};
 
 static const char Msg_Null[] = "\0";
 

+ 0 - 27
src/board.c

@@ -237,33 +237,6 @@ static void TIM17_Init(void)
   TIM17->EGR = TIM_EGR_UG; // force timer update
 }
 
-/**
- * @brief Buzzer control: On.
- */
-void buzer_On(void) {
-  BUZER_ON;
-}
-
-/**
- * @brief Buzzer control: Off.
- */
-void buzer_Off(void) {
-  BUZER_OFF;
-}
-
-/**
-  * @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;
-    //ES_PlaceEvent(evNewSecond);
-  }
-}
-
 /**
   * @brief This function handles DMA1 channel 2 and 3 interrupts.
   */

+ 343 - 0
src/clock.c

@@ -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);
+  }
+}

+ 209 - 0
src/event-system.c

@@ -0,0 +1,209 @@
+/**
+ *  Author(s)...: Pashgan    http://ChipEnable.Ru
+ *  Target(s)...: any MCU
+ *  Compiler....: IAR 5.11A
+ *  Description.: Template for tables based event system
+ *  Data........: 30.09.12
+*/
+
+#include "event-system.h"
+
+static void EmptyFunc(void);
+
+/* ring buffer */
+static volatile es_event_t cycleBuf[SIZE_BUF];
+static volatile int tailBuf = 0;
+static volatile int headBuf = 0;
+static volatile int countBuf = 0;
+
+static volatile es_state_t _State;
+
+typedef struct {
+  es_state_t state;
+  es_event_t event;
+  es_state_t nextState;
+  void (*pStateFunc1)(void);
+  void (*pStateFunc2)(void);
+} table_state_t;
+
+/**
+  * Sate Table - heart of state machine
+  */
+const table_state_t stateTable[] = {
+  /* STATE    EVENT   NEXT STATE  STATE_FUNC1 STATE_FUNC2 */
+  /* show date, time, ... */
+  // 'Hour+' Button pressed
+  {stShowTime, evBTN1Pressed, stShowDate, show_Date, NULL},
+  {stShowMMSS, evBTN1Pressed, stShowDate, show_Date, NULL},
+  // 'Min+' Button pressed
+  {stShowTime, evBTN2Pressed, stShowMMSS, show_MMSS,   NULL},
+  {stShowMMSS, evBTN2Pressed, stShowTime, show_Time,   NULL},
+
+  /* display wdt events */
+  {stShowDate,  evDisplayWDT, stShowTime, show_Time, NULL},
+
+  /* refresh output */
+  {stShowTime, evNewSecond,  stNoChange, show_Time,   NULL},
+  {stShowMMSS, evNewSecond,  stNoChange, show_MMSS,   NULL},
+
+  /* set time */
+  {stShowTime, evBTN1Holded,  stSetHH,    setTimeBegin, setHHBegin},
+  {stSetHH,    evBTN1Holded,  stShowTime, setTimeEnd,   show_Time},
+  {stSetMM,    evBTN1Holded,  stShowTime, setTimeEnd,   show_Time},
+
+  {stSetHH,    evBTN1Pressed, stSetMM,    setMMBegin,   NULL},
+  {stSetMM,    evBTN1Pressed, stSetHH,    setHHBegin,   NULL},
+
+  {stSetHH,    evBTN2Pressed, stNoChange, setHHInc,     setTimeShow},
+  {stSetHH,    evBTN3Pressed, stNoChange, setHHDec,     setTimeShow},
+  {stSetMM,    evBTN2Pressed, stNoChange, setMMInc,     setTimeShow},
+  {stSetMM,    evBTN3Pressed, stNoChange, setMMDec,     setTimeShow},
+
+  {stSetHH,    evDisplayWDT,  stShowTime, show_Time,     NULL},
+  {stSetMM,    evDisplayWDT,  stShowTime, show_Time,     NULL},
+
+  /* set calendar */
+  // begin
+  {stShowDate, evBTN1Holded, stSetWD,   setDateBegin, setWDBegin},
+  // end
+  {stSetWD,   evBTN1Holded, stShowDate, setDateEnd, show_Date},
+  // next
+  {stSetWD,   evBTN1Pressed, stSetMD,   setMDBegin,    NULL},
+  {stSetMD,   evBTN1Pressed, stSetMon,  setMonthBegin, NULL},
+  {stSetMon,  evBTN1Pressed, stSetYear, setYearBegin,  NULL},
+  {stSetYear, evBTN1Pressed, stSetWD,   setWDBegin,    NULL},
+  // change
+  {stSetWD,   evBTN2Pressed, stNoChange, setIncWDay,  setWDShow},
+  {stSetWD,   evBTN3Pressed, stNoChange, setDecWDay,  setWDShow},
+  {stSetMD,   evBTN2Pressed, stNoChange, setIncMDay,  setDMShow},
+  {stSetMD,   evBTN3Pressed, stNoChange, setDecMDay,  setDMShow},
+  {stSetMon,  evBTN2Pressed, stNoChange, setIncMonth, setDMShow},
+  {stSetMon,  evBTN3Pressed, stNoChange, setDecMonth, setDMShow},
+  {stSetYear, evBTN2Pressed, stNoChange, setIncYear,  setYearShow},
+  {stSetYear, evBTN3Pressed, stNoChange, setDecYear,  setYearShow},
+  // WDT
+  {stSetWD,   evDisplayWDT, stShowTime, show_Time, NULL},
+  {stSetMD,   evDisplayWDT, stShowTime, show_Time, NULL},
+  {stSetMon,  evDisplayWDT, stShowTime, show_Time, NULL},
+  {stSetYear, evDisplayWDT, stShowTime, show_Time, NULL},
+
+  /* mandatory empty table row */
+  {stNoChange, eventNull, stNoChange, EmptyFunc, EmptyFunc}
+};
+
+/**
+  * @brief  Take event.
+  * @param  None
+  * @retval Event code
+  */
+es_event_t ES_GetEvent(void)
+{
+  es_event_t event;
+
+  if (countBuf > 0) {
+    event = cycleBuf[headBuf];
+    countBuf --;
+    headBuf = (headBuf + 1) & (SIZE_BUF - 1);
+    return event;
+  }
+
+  return eventNull;
+}
+
+/**
+  * @brief  Place event.
+  * @param  Event
+  * @retval None
+  */
+void ES_PlaceEvent(es_event_t event)
+{
+  if (countBuf < SIZE_BUF) {
+    cycleBuf[tailBuf] = event;
+    tailBuf = (tailBuf + 1) & (SIZE_BUF - 1);
+    countBuf ++;
+  } else {
+    /* event buffer overflow alarm */
+    display_String("ES Error: No space for Events!\0", 3);
+    while(1);
+  }
+}
+
+/**
+  * @brief  Initialize event system.
+  * @param  Start Event
+  * @retval None
+  */
+void ES_Init(es_state_t init_state)
+{
+  tailBuf = 0;
+  headBuf = 0;
+  countBuf = 0;
+  _State = init_state;
+}
+
+/**
+  * @brief  Fake function.
+  * @param  None
+  * @retval None
+  */
+static void EmptyFunc(void)
+{
+}
+
+/**
+  * @brief  Dispatcher of event system.
+  * @param  Event
+  * @retval None
+  */
+void ES_Dispatch(es_event_t event)
+{
+  int i;
+  void (*pStateFunc1)(void);
+  void (*pStateFunc2)(void);
+
+  pStateFunc1 = NULL;
+  pStateFunc2 = NULL;
+
+  /* get next state */
+  for (i=0; stateTable[i].state; i++) {
+    /* if the current state and the received event match */
+    if (stateTable[i].state == _State && stateTable[i].event == event) {
+      /* change current state if needed */
+      if (stateTable[i].nextState != stNoChange) {
+        _State = stateTable[i].nextState;
+      }
+      /* get functions */
+      pStateFunc1 = stateTable[i].pStateFunc1;
+      pStateFunc2 = stateTable[i].pStateFunc2;
+      break;
+    }
+  }
+
+  if (pStateFunc1) {
+    pStateFunc1();
+  }
+
+  if (pStateFunc2) {
+    pStateFunc2();
+  }
+}
+
+/**
+  * @brief  Return current state code.
+  * @param  None
+  * @retval State code
+  */
+es_state_t ES_GetState(void)
+{
+  return _State;
+}
+
+/**
+  * @brief  Set current state to given code .
+  * @param  State
+  * @retval None
+  */
+void ES_SetState(es_state_t new_state)
+{
+  _State = new_state;
+}

+ 11 - 115
src/main.c

@@ -10,21 +10,14 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "main.h"
-#include "digits.h"
-#include "xprintf.h"
-#include "msg.h"
 
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
 volatile flag_t Flag = {0};
-static rtc_t Clock;
 
 /* Private function prototypes -----------------------------------------------*/
-void bip_Bip(void);
-static void dots_Off(void);
-static void Show_MMSS(void);
 
 /**
   * @brief  Main program.
@@ -33,43 +26,31 @@ static void Show_MMSS(void);
   */
 int main(void)
 {
-  i2c_status_t i2c_status;
-
   /* Initialize onBoard Hardware */
   Board_Init();
 
   /* Initialize Scheduler */
   RTOS_Init();
 
+  /* Initialize Event State Machine */
+  ES_Init(stShowTime);
+
   display_Init();
-  bip_Bip();
-  display_String(Msg_StartMsg, 1);
-
-  /* Real-Time clock */
-  i2c_status = RTC_Init();
-  if (i2c_status != I2C_Ret_OK) {
-    bip_Bip();
-    display_String("RTC_Init Error\0", 1);
-  }
-  i2c_status = RTC_ReadTime(&Clock);
-  if (i2c_status != I2C_Ret_OK) {
-    bip_Bip();
-    display_String("RTC_ReadTime Error\0", 1);
-  }
 
-  Show_MMSS();
+  Clock_Init();
 
   /* Infinite loop */
   while (1)
   {
+    /*
     if (Flag.RTC_IRQ != 0) {
       Flag.RTC_IRQ = 0;
-      i2c_status = RTC_ReadTime(&Clock);
-      if (i2c_status == I2C_Ret_OK) {
-        Show_MMSS();
-      } else {
-        display_String("I2C Err\0", 1);
-      }
+    }
+    */
+
+    es_event_t event = ES_GetEvent();
+    if (event) {
+      ES_Dispatch(event);
     }
 
     RTOS_DispatchTask();
@@ -80,91 +61,6 @@ int main(void)
 
 /* Private functions ---------------------------------------------------------*/
 
-/**
- * @brief 
- * Звук "пи-пи...пи-пи...":
- *  - две посылки по 125 мс,
- *  - пауза внутри посылки 63 мс,
- *  - пауза между посылками 689 мс,
- *  - частота заполнения 4 кГц,
- *  - период 1 секунда.
- * 
- */
-void bip_Bip(void) {
-  static int stat = 0;
-
-  switch (stat) {
-  case 0:
-    stat = 1;
-    BUZER_ON;
-    RTOS_SetTask(bip_Bip, 100, 0);
-    break;
-
-  case 1:
-    stat = 2;
-    BUZER_OFF;
-    RTOS_SetTask(bip_Bip, 75, 0);
-    break;
-
-  case 2:
-    stat = 3;
-    BUZER_ON;
-    RTOS_SetTask(bip_Bip, 150, 0);
-    break;
-
-  case 3:
-    stat = 0;
-    BUZER_OFF;
-    //RTOS_SetTask(bip_Bip, 675, 0);
-    break;
-
-  default:
-    BUZER_OFF;
-    stat = 0;
-    break;
-  }
-}
-
-/**
- * @brief Show MM:SS use 4x7 digits
- */
-static void Show_MMSS(void) {
-  display_Wait4Display();
-
-  if (Clock.Sec == 0x0) {
-    char buf[16] = {0};
-    xsprintf(buf, "%02x %s. %02x %s.\0", Clock.Hr, Msg_god, Clock.Min, Msg_hv);
-    display_String(buf, 2);
-  } else {
-    uint8_t t;
-    // dots on
-    display_WriteData(&digit_4x7[10][0], 10, 4);
-    RTOS_SetTask(dots_Off, 500, 0);
-
-    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();
-  }
-}
-
-static void dots_Off(void) {
-  display_Wait4Display();
-
-  display_Buffer[11] = 0x0;
-  display_Buffer[12] = 0x0;
-  display_WriteBuffer();
-}
-
 /******************************************************************************/
 /*            Cortex-M0 Processor Exceptions Handlers                         */
 /******************************************************************************/