embedded-systems-labs/calculator/Src/main.c
2025-12-25 11:09:27 +03:00

211 lines
5.7 KiB
C

#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "kb.h"
#include "sdk_uart.h"
#include "pca9538.h"
#include "oled.h"
#include "fonts.h"
#include <stdio.h>
#include <string.h>
void SystemClock_Config(void);
typedef enum { OP_NONE, OP_ADD, OP_SUB, OP_MUL } Operation;
typedef enum { STATE_INPUT_A, STATE_INPUT_B, STATE_RESULT } CalcState;
static int32_t num_a = 0;
static int32_t num_b = 0;
static int32_t result = 0;
static int32_t repeat_val = 0;
static Operation current_op = OP_NONE;
static Operation repeat_op = OP_NONE;
static CalcState state = STATE_INPUT_A;
static uint8_t has_input = 0;
static char buf[32];
static const char* op_str(Operation op) {
switch(op) {
case OP_ADD: return "+";
case OP_SUB: return "-";
case OP_MUL: return "*";
default: return "";
}
}
static int32_t calc(int32_t a, int32_t b, Operation op) {
switch(op) {
case OP_ADD: return a + b;
case OP_SUB: return a - b;
case OP_MUL: return a * b;
default: return a;
}
}
static void update_display(void) {
oled_Fill(Black);
oled_SetCursor(80, 0);
oled_WriteString("1 2 3", Font_7x10, White);
oled_SetCursor(80, 12);
oled_WriteString("4 5 6", Font_7x10, White);
oled_SetCursor(80, 24);
oled_WriteString("7 8 9", Font_7x10, White);
oled_SetCursor(80, 36);
oled_WriteString("* 0 #", Font_7x10, White);
oled_SetCursor(0, 0);
if (state == STATE_INPUT_A) {
sprintf(buf, "%ld", (long)num_a);
oled_WriteString(buf, Font_16x26, White);
oled_SetCursor(0, 28);
oled_WriteString("*:op #:clr", Font_7x10, White);
}
else if (state == STATE_INPUT_B) {
sprintf(buf, "%ld %s", (long)num_a, op_str(current_op));
oled_WriteString(buf, Font_11x18, White);
oled_SetCursor(0, 20);
sprintf(buf, "%ld", (long)num_b);
oled_WriteString(buf, Font_16x26, White);
oled_SetCursor(0, 48);
oled_WriteString("*:chg #:=", Font_7x10, White);
}
else {
sprintf(buf, "=%ld", (long)result);
oled_WriteString(buf, Font_16x26, White);
oled_SetCursor(0, 28);
oled_WriteString("*:use #:rpt", Font_7x10, White);
}
oled_UpdateScreen();
}
static int8_t get_key(void) {
uint8_t k;
k = Check_Row(ROW1);
if (k == 0x04) return 1;
if (k == 0x02) return 2;
if (k == 0x01) return 3;
k = Check_Row(ROW2);
if (k == 0x04) return 4;
if (k == 0x02) return 5;
if (k == 0x01) return 6;
k = Check_Row(ROW3);
if (k == 0x04) return 7;
if (k == 0x02) return 8;
if (k == 0x01) return 9;
k = Check_Row(ROW4);
if (k == 0x04) return -1;
if (k == 0x02) return 0;
if (k == 0x01) return -2;
return -100;
}
static void reset_all(void) {
num_a = num_b = result = 0;
current_op = OP_NONE;
state = STATE_INPUT_A;
has_input = 0;
}
static void on_star(void) {
if (state == STATE_INPUT_A && has_input) {
current_op = OP_ADD;
state = STATE_INPUT_B;
}
else if (state == STATE_INPUT_B) {
if (current_op == OP_ADD) current_op = OP_SUB;
else if (current_op == OP_SUB) current_op = OP_MUL;
else current_op = OP_ADD;
}
else if (state == STATE_RESULT) {
num_a = result;
num_b = 0;
current_op = OP_ADD;
state = STATE_INPUT_B;
}
}
static void on_hash(void) {
if (state == STATE_INPUT_A) {
reset_all();
}
else if (state == STATE_INPUT_B) {
repeat_val = num_b;
repeat_op = current_op;
result = calc(num_a, num_b, current_op);
state = STATE_RESULT;
}
else if (state == STATE_RESULT) {
result = calc(result, repeat_val, repeat_op);
}
}
static void on_digit(int8_t d) {
if (state == STATE_INPUT_A) {
if (num_a < 100000000) {
num_a = num_a * 10 + d;
has_input = 1;
}
}
else if (state == STATE_INPUT_B) {
if (num_b < 100000000)
num_b = num_b * 10 + d;
}
else {
reset_all();
num_a = d;
has_input = 1;
}
}
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART6_UART_Init();
oled_Init();
int8_t last = -100;
update_display();
while (1) {
int8_t key = get_key();
if (key != last && key != -100) {
if (key >= 0) on_digit(key);
else if (key == -1) on_star();
else if (key == -2) on_hash();
update_display();
}
last = key;
HAL_Delay(100);
}
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) Error_Handler();
}
void Error_Handler(void) { while(1) {} }