#include "main.h"
#include "tm1637.h"
#include "keyboard.h"
volatile uint32_t tickCount;
uint32_t last_display_update;
uint16_t counter;
char lastKey;
uint32_t lastScanTime;
const PIN_TypeDef DEFAULT_PIN = { '1', '1', '1', '1' };
const PIN_TypeDef START_PIN = { '0', '0', '0', '0' };
PIN_TypeDef g_current_pin = DEFAULT_PIN;
void osSystickHandler(void) {
tickCount++;
}
void initGPIO() {
// Включаем тактирование GPIOA и GPIOB
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
GPIOA->ODR &= ~((1 << 5) | (1 << 9) | (1 << 15));
// Настраиваем PA5 как выход
GPIOA->MODER = (GPIOA->MODER & ~(3 << 10)) | (1 << 10);
GPIOA->OTYPER &= ~(1 << 5);
GPIOA->OSPEEDR |= (1 << 10);
// Настраиваем PA9 как выход
GPIOA->MODER = (GPIOA->MODER & ~(3 << 18)) | (1 << 18);
GPIOA->OTYPER &= ~(1 << 9);
GPIOA->OSPEEDR |= (1 << 18);
// Настраиваем PA15 как выход
GPIOA->MODER = (GPIOA->MODER & ~(3 << 30)) | (1 << 30);
GPIOA->OTYPER &= ~(1 << 15);
GPIOA->OSPEEDR |= (1 << 30);
}
void initUSART2() {
// Включаем тактирование USART2
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// Настраиваем PA2 и PA3 в альтернативный режим
GPIOA->MODER = (GPIOA->MODER & ~(0xF << 4)) | (0xA << 4);
GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(0xFF << 8)) | (1 << 8) | (1 << 12);
// Настраиваем USART2
USART2->BRR = 417; // 48MHz/115200
USART2->CR1 = USART_CR1_TE | USART_CR1_UE;
}
void initSysTick() {
SysTick->LOAD = 47999; // 1ms при 48MHz
SysTick->VAL = 0;
SysTick->CTRL = (1 << 2) | (1 << 1) | (1 << 0);
}
int _write(int file, uint8_t *ptr, int len) {
for (int i = 0; i < len; i++) {
while (!(USART2->ISR & USART_ISR_TXE));
USART2->TDR = ptr[i];
}
return len;
}
void checkTickCount() {
if ((tickCount % 2000) == 0) {
GPIOA->ODR ^= (1 << 5); // Toggle LED
}
}
Step processState(char input_digit, unsigned char *input_count) {
switch (input_digit) {
case ENTER_SYMBOL:
if (*input_count == 4) {
return LIGHT;
}
return SKIP;
default:
if (*input_count < 4) {
*input_count = *input_count + 1;
return FILL_DIGIT;
}
return SKIP;
}
}
void fillPinDigit(PIN_TypeDef *pin_to_fill, char input_digit, unsigned char *input_count){
switch(*input_count){
case 1:
pin_to_fill->first_digit = input_digit;
break;
case 2:
pin_to_fill->second_digit = input_digit;
break;
case 3:
pin_to_fill->third_digit = input_digit;
break;
default:
pin_to_fill->fourth_digit = input_digit;
break;
}
}
int checkPwd(PIN_TypeDef *input_pin) {
if (input_pin->first_digit == g_current_pin.first_digit &&
input_pin->second_digit == g_current_pin.second_digit &&
input_pin->third_digit == g_current_pin.third_digit &&
input_pin->fourth_digit == g_current_pin.fourth_digit) {
return 1;
}
return 0;
}
int checkClearSymbol(char input_digit){
if (input_digit == CLEAR_SYMBOL){
return 1;
}
return 0;
}
int checkEnterSymbol(char input_digit){
if (input_digit == ENTER_SYMBOL){
return 1;
}
return 0;
}
void changePwdLight() {
GPIOA->ODR |= (1 << 5);
uint32_t startTime = tickCount;
while ((tickCount - startTime) < 1500) {
__asm__("nop");
}
GPIOA->ODR &= ~(1 << 5);
}
void enterPwdAcceptLight() {
GPIOA->ODR |= (1 << 9);
uint32_t startTime = tickCount;
while ((tickCount - startTime) < 1500) {
__asm__("nop");
}
GPIOA->ODR &= ~(1 << 9);
}
void enterPwdFailLight() {
GPIOA->ODR |= (1 << 15);
uint32_t startTime = tickCount;
while ((tickCount - startTime) < 1500) {
__asm__("nop");
}
GPIOA->ODR &= ~(1 << 15);
}
void handleDigit(Action *action, PIN_TypeDef *input_pin, char input_digit, unsigned char *input_count){
if (input_digit == SKIP_SYMBOL){
return;
}
if (checkClearSymbol(input_digit) == 1){
*action = CHANGE_PWD;
*input_count = 0;
printf(SET_PIN_MSG);
tm1637_clear();
return;
}
Step next_step = processState(input_digit, input_count);
switch(*action){
case CHANGE_PWD:
switch(next_step){
case LIGHT:
changePwdLight();
*input_count = 0;
*action = ENTER_PWD;
tm1637_clear();
printf(PIN_SET_SUCCESS_MSG);
printf(SEPARATOR_MSG);
printf(ENTER_PIN_MSG);
return;
case FILL_DIGIT:
fillPinDigit(&g_current_pin, input_digit, input_count);
tm1637_display_pin_digit(input_digit, *input_count - 1);
return;
default:
return;
}
default:
switch(next_step){
case LIGHT:
if(checkPwd(input_pin)){
printf(ACCESS_ENTER_MSG);
enterPwdAcceptLight();
} else {
printf(FAIL_ENTER_MSG);
enterPwdFailLight();
}
*input_count = 0;
*input_pin = START_PIN;
tm1637_clear();
printf(ENTER_PIN_MSG);
return;
case FILL_DIGIT:
tm1637_display_pin_digit(input_digit, *input_count - 1);
fillPinDigit(input_pin, input_digit, input_count);
return;
default:
return;
}
}
}
int main(void) {
initGPIO();
initUSART2();
initSysTick();
initKeyboard();
tm1637_init();
tm1637_clear();
Action action = CHANGE_PWD;
PIN_TypeDef input_pin = START_PIN;
volatile unsigned char input_count = 0;
volatile char input_digit;
while (1) {
input_digit = scanKeyboard();
handleDigit(&action, &input_pin, input_digit, &input_count);
}
return 0;
}