From f710e8879341d4ceb41552d72244978dd1f491fb Mon Sep 17 00:00:00 2001 From: sherlock Date: Wed, 29 Oct 2025 14:22:21 +0530 Subject: [PATCH] proj --- ES/Project/code.c | 347 ++++++++++++++++++++++------------------------ 1 file changed, 169 insertions(+), 178 deletions(-) diff --git a/ES/Project/code.c b/ES/Project/code.c index 6dfee71..03947eb 100644 --- a/ES/Project/code.c +++ b/ES/Project/code.c @@ -1,13 +1,15 @@ #include +#include /* =================================================== - * SMART CALCULATOR - LPC176x + * SMART CALCULATOR - LPC1768 (Final v2) * Supports BIN, BASE4, OCT, DEC, and HEX - * with 4x4 keypad, LCD, and 7-seg status. + * with 4x4 keypad, LCD, and 7-seg status display. * - * BIN/BASE4/OCT/DEC: operators B–F direct - * HEX: operators B–F only when MODE button held - * Arithmetic is performed modulo the current base + * Features: + * - Base-aware arithmetic and I/O + * - HEX: double MODE button press within 2s = operator mode + * - Hardware 1ms timing via SysTick * =================================================== */ @@ -45,20 +47,27 @@ const unsigned char seven_seg[16] = { #define OP_ADD 1 #define OP_SUB 2 #define OP_MUL 3 +#define OP_CLR 4 +#define OP_RES 5 -/* ===== Global Variables (predeclared) ===== */ -int input_num; -int stored_num; -int result; +/* ===== Global Variables ===== */ unsigned int current_base; +unsigned int input_num; +unsigned int stored_num; +unsigned int result; unsigned int operation; -unsigned char lcd_flag; unsigned char result_displayed; unsigned int key, last_key, stable; unsigned int button_state, last_button_state, button_stable; -/* ===== Function Prototypes ===== */ +unsigned char hex_operator_mode; +unsigned long last_mode_press_time; + +/* Millisecond counter via SysTick */ +volatile unsigned long sys_millis = 0; + +/* ===== Function Declarations ===== */ void delay(volatile unsigned int d); void lcd_delay(unsigned long r); void lcd_write_nibble(unsigned char nibble, unsigned char is_data); @@ -66,36 +75,47 @@ void lcd_cmd(unsigned char cmd); void lcd_data(unsigned char data); void lcd_init(void); void lcd_print_str(const char *str); -void lcd_print_num(int num, unsigned int base); +void lcd_print_num(unsigned int num, unsigned int base); void display_mode(void); void display_input(void); -void display_operator_feedback(const char *op_symbol); +void display_result(void); unsigned int scan_keypad(void); unsigned int scan_mode_button(void); unsigned int is_valid_digit(unsigned int key); void change_mode(void); +void handle_mode_button(void); void operate(unsigned int op); void perform_operation(void); -unsigned char is_operator_active(unsigned int key, unsigned int mode_button); +unsigned char is_operator_active(unsigned int key); +unsigned int base_arith(unsigned int a, unsigned int b, + unsigned int op, unsigned int base); +unsigned long millis(void); -/* ====== Utility ====== */ +/* ===== Utility ===== */ void delay(volatile unsigned int d) { - while (d--) - __NOP(); + while (d--) __NOP(); } void lcd_delay(unsigned long r) { - unsigned long i; + volatile unsigned long i; for (i = 0; i < r; i++) ; } -/* ===== LCD ==== */ +/* ===== SysTick Millisecond Tracker ===== */ +void SysTick_Handler(void) { + sys_millis++; +} + +unsigned long millis(void) { + return sys_millis; +} + +/* ===== LCD Control ===== */ void lcd_write_nibble(unsigned char nibble, unsigned char is_data) { unsigned long temp; temp = (nibble & 0x0F) << LCD_DATA_SHIFT; - LPC_GPIO0->FIOPIN = - (LPC_GPIO0->FIOPIN & ~LCD_DATA_MASK) | temp; + LPC_GPIO0->FIOPIN = (LPC_GPIO0->FIOPIN & ~LCD_DATA_MASK) | temp; if (is_data) LPC_GPIO0->FIOSET = LCD_RS; @@ -105,7 +125,7 @@ void lcd_write_nibble(unsigned char nibble, unsigned char is_data) { LPC_GPIO0->FIOSET = LCD_EN; lcd_delay(100); LPC_GPIO0->FIOCLR = LCD_EN; - lcd_delay(500000); + lcd_delay(250000); } void lcd_cmd(unsigned char cmd) { @@ -141,90 +161,62 @@ void lcd_print_str(const char *str) { lcd_data(*str++); } -/* ===== Print number in base ===== */ -void lcd_print_num(int num, unsigned int base) { +void lcd_print_num(unsigned int num, unsigned int base) { char buffer[17]; int i = 0; - if (base != MODE_DEC) { - unsigned int unum = (unsigned int)num; - if (unum == 0) { - lcd_data('0'); - return; - } - while (unum > 0 && i < 16) { - unsigned int digit = unum % base; - buffer[i++] = (digit < 10) ? ('0' + digit) - : ('A' + (digit - 10)); - unum /= base; - } - } else { - if (num < 0) { - lcd_data('-'); - num = -num; - } - if (num == 0) { - lcd_data('0'); - return; - } - while (num > 0 && i < 16) { - buffer[i++] = '0' + (num % 10); - num /= 10; - } + if (num == 0) { + lcd_data('0'); + return; } + while (num > 0 && i < 16) { + unsigned int d = num % base; + buffer[i++] = (d < 10) ? ('0' + d) : ('A' + d - 10); + num /= base; + } while (i > 0) lcd_data(buffer[--i]); } -/* ===== Display handlers ===== */ +/* ===== Display Helpers ===== */ void display_mode(void) { lcd_cmd(0x80); lcd_print_str("Mode: "); if (current_base == MODE_BIN) - lcd_print_str("BIN "); + lcd_print_str("BIN "); else if (current_base == MODE_BASE4) - lcd_print_str("BASE4 "); + lcd_print_str("BASE4 "); else if (current_base == MODE_OCT) - lcd_print_str("OCT "); + lcd_print_str("OCT "); else if (current_base == MODE_DEC) - lcd_print_str("DEC "); - else - lcd_print_str("HEX "); + lcd_print_str("DEC "); + else { + lcd_print_str("HEX"); + if (hex_operator_mode) + lcd_print_str("[OPS]"); + else + lcd_print_str(" "); + } } void display_input(void) { lcd_cmd(0xC0); - lcd_print_str("Inp("); - if (current_base == MODE_BIN) - lcd_print_str("2"); - else if (current_base == MODE_BASE4) - lcd_print_str("4"); - else if (current_base == MODE_OCT) - lcd_print_str("8"); - else if (current_base == MODE_DEC) - lcd_print_str("10"); - else - lcd_print_str("16"); - lcd_print_str("): "); + lcd_print_str("Input: "); lcd_print_num(input_num, current_base); - lcd_print_str(" "); + lcd_print_str(" "); } -void display_operator_feedback(const char *op_symbol) { +void display_result(void) { lcd_cmd(0xC0); - lcd_print_str("Op: "); - lcd_print_str(op_symbol); - lcd_print_str(" "); - delay(100000); - display_input(); + lcd_print_str("Result: "); + lcd_print_num(result, current_base); + lcd_print_str(" "); } -/* ====== Scan Keypad ====== */ +/* ===== Keypad and Button ===== */ unsigned int scan_keypad(void) { - unsigned int col, row; - unsigned int row_bits; - + unsigned int col, row, row_bits; for (col = 0; col < 4; col++) { LPC_GPIO0->FIOSET = COL_MASK; delay(50); @@ -234,9 +226,9 @@ unsigned int scan_keypad(void) { if (row_bits != 0x0F) { for (row = 0; row < 4; row++) { - if ((row_bits & (1 << row)) == 0) { + if (!(row_bits & (1 << row))) { LPC_GPIO0->FIOSET = COL_MASK; - return (col * 4 + row); + return col * 4 + row; } } } @@ -245,12 +237,11 @@ unsigned int scan_keypad(void) { return 0xFF; } -/* ===== Mode button ===== */ unsigned int scan_mode_button(void) { return ((LPC_GPIO2->FIOPIN & MODE_BUTTON) == 0) ? 1 : 0; } -/* ===== Modes and Validation ===== */ +/* ===== Mode and Button ===== */ void change_mode(void) { if (current_base == MODE_DEC) current_base = MODE_BIN; @@ -264,8 +255,31 @@ void change_mode(void) { current_base = MODE_DEC; display_mode(); + input_num = stored_num = result = 0; + operation = OP_NONE; + result_displayed = 0; + display_input(); } +void handle_mode_button(void) { + unsigned long now = millis(); + + if (button_stable == 3 && button_state == 1) { + if (current_base == MODE_HEX) { + if ((now - last_mode_press_time) < 2000) { + hex_operator_mode = !hex_operator_mode; + display_mode(); + last_mode_press_time = 0; + } else { + last_mode_press_time = now; + } + } else { + change_mode(); + } + } +} + +/* ===== Validation ===== */ unsigned int is_valid_digit(unsigned int key) { if (key >= 16) return 0; @@ -280,73 +294,72 @@ unsigned int is_valid_digit(unsigned int key) { return 1; } -/* ===== Operator Handling ===== */ +/* ===== Arithmetic ===== */ +unsigned int base_arith(unsigned int a, unsigned int b, + unsigned int op, unsigned int base) { + unsigned int r; + switch (op) { + case OP_ADD: + r = a + b; + break; + case OP_SUB: + r = (a >= b) ? (a - b) : 0; + break; + case OP_MUL: + r = a * b; + break; + default: + r = a; + break; + } + return r; +} + +/* ===== Operation/Arithmetic Handling ===== */ void operate(unsigned int op) { stored_num = input_num; - operation = op; input_num = 0; + operation = op; result_displayed = 0; } -/* perform_operation: arithmetic within the active base */ void perform_operation(void) { - if (operation == OP_ADD) - result = stored_num + input_num; - else if (operation == OP_SUB) - result = stored_num - input_num; - else if (operation == OP_MUL) - result = stored_num * input_num; - else - result = input_num; - - /* Base-aware modular arithmetic for non-DEC modes */ - if (current_base != MODE_DEC) { - if (result < 0) - result = (result % current_base + current_base) % current_base; - else - result %= current_base; - } - - lcd_cmd(0xC0); - lcd_print_str("Res("); - if (current_base == MODE_BIN) - lcd_print_str("2"); - else if (current_base == MODE_BASE4) - lcd_print_str("4"); - else if (current_base == MODE_OCT) - lcd_print_str("8"); - else if (current_base == MODE_DEC) - lcd_print_str("10"); - else - lcd_print_str("16"); - lcd_print_str("): "); - lcd_print_num(result, current_base); - lcd_print_str(" "); - + result = base_arith(stored_num, input_num, operation, current_base); + display_result(); input_num = result; operation = OP_NONE; result_displayed = 1; } -unsigned char is_operator_active(unsigned int key, unsigned int mode_button) { - if (current_base == MODE_HEX) - return (mode_button && key >= 11 && key <= 15); - else - return (key >= 11 && key <= 15); +/* ===== Key Classifier ===== */ +unsigned char is_operator_active(unsigned int key) { + if (key >= 11 && key <= 15) { + if (current_base == MODE_HEX) + return hex_operator_mode; + else + return 1; + } + return 0; } /* ===== MAIN ===== */ int main(void) { - input_num = stored_num = result = 0; current_base = MODE_DEC; + input_num = stored_num = result = 0; operation = OP_NONE; - lcd_flag = 0; result_displayed = 0; key = last_key = 0xFF; - stable = button_stable = 0; + stable = 0; + button_stable = 0; button_state = last_button_state = 0; + hex_operator_mode = 0; + last_mode_press_time = 0; - /* Configure pins */ + /* ===== SystemClock & SysTick Setup ===== */ + SystemCoreClockUpdate(); + SysTick_Config(SystemCoreClock / 1000); // 1ms tick + + /* ===== Peripheral Init ===== */ LPC_PINCON->PINSEL0 = 0; LPC_PINCON->PINSEL1 = 0; LPC_PINCON->PINSEL3 = 0; @@ -360,85 +373,63 @@ int main(void) { LPC_GPIO0->FIODIR |= (0xFF << SEG_SHIFT); LPC_GPIO1->FIODIR |= DIGIT_EN; - LPC_GPIO0->FIODIR |= LCD_DATA_MASK | LCD_RS | LCD_EN; lcd_init(); display_mode(); display_input(); - for (;;) { + /* ===== Main Loop ===== */ + while (1) { key = scan_keypad(); button_state = scan_mode_button(); - /* Debounce keypad */ - if (key == last_key) { - if (stable < 5) - stable++; - } else { + // Debounce keypad + if (key == last_key) + stable = (stable < 5) ? stable + 1 : stable; + else { last_key = key; stable = 0; } - /* Debounce mode button */ - if (button_state == last_button_state) { - if (button_stable < 5) - button_stable++; - } else { + // Debounce button + if (button_state == last_button_state) + button_stable = (button_stable < 5) ? button_stable + 1 : button_stable; + else { last_button_state = button_state; button_stable = 0; } - /* Handle mode change */ - if (button_stable == 3 && button_state == 1) { - change_mode(); - button_stable = 5; - } + handle_mode_button(); - /* Handle key event */ if (stable == 3 && key != 0xFF) { - unsigned char op_allowed = is_operator_active(key, button_state); - - if (op_allowed) { - if (key == 11) { - operate(OP_ADD); - display_operator_feedback("+"); - } else if (key == 12) { - input_num = stored_num = result = 0; - operation = OP_NONE; - result_displayed = 0; - display_operator_feedback("CLR"); - } else if (key == 13) { - operate(OP_SUB); - display_operator_feedback("-"); - } else if (key == 14) { - operate(OP_MUL); - display_operator_feedback("*"); - } else if (key == 15) { - perform_operation(); + if (is_operator_active(key)) { + switch (key) { + case 11: operate(OP_ADD); display_input(); break; + case 12: input_num = stored_num = result = 0; + operation = OP_NONE; display_input(); break; + case 13: operate(OP_SUB); display_input(); break; + case 14: operate(OP_MUL); display_input(); break; + case 15: perform_operation(); break; } } else if (is_valid_digit(key)) { result_displayed = 0; input_num = input_num * current_base + key; display_input(); } - stable = 5; } - /* Update 7-seg state display */ - unsigned int seg_pattern; - if (operation == OP_NONE && result_displayed == 0) - seg_pattern = 0x06; // '1' - else if (operation != OP_NONE) - seg_pattern = 0x5B | 0x80; // '2' + dp - else if (result_displayed == 1) - seg_pattern = 0x4F | 0x80; // '3' + dp - else - seg_pattern = 0x3F; // '0' - + // Simple 7-seg base display LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT); - LPC_GPIO0->FIOSET = (seg_pattern << SEG_SHIFT); + unsigned int segval = 0x3F; // default '0' + if (current_base == MODE_BIN) segval = seven_seg[2]; + else if (current_base == MODE_BASE4) segval = seven_seg[4]; + else if (current_base == MODE_OCT) segval = seven_seg[8]; + else if (current_base == MODE_DEC) segval = seven_seg[0]; + else if (current_base == MODE_HEX) segval = seven_seg[0xA]; // 'A' for HEX + + LPC_GPIO0->FIOSET = (segval << SEG_SHIFT); LPC_GPIO1->FIOSET = DIGIT_EN; delay(3000);