This commit is contained in:
sherlock 2025-10-29 12:43:01 +05:30
parent c59338aeea
commit 6693a1a831

View file

@ -2,36 +2,22 @@
/* =================================================== /* ===================================================
* SMART CALCULATOR - LPC176x * SMART CALCULATOR - LPC176x
* Supports BIN, BASE4, OCT, DEC, and HEX modes with * Supports BIN, BASE4, OCT, DEC, and HEX
* 4x4 keypad, LCD, and 7-segment display. * with 4x4 keypad, LCD, and 7-seg status.
* --------------------------------------------------- *
* DEC/BIN/BASE4/OCT : Operators BF work directly * BIN/BASE4/OCT/DEC: operators BF direct
* HEX : Operators BF require MODE pressed * HEX: operators BF only when MODE button held
* Arithmetic is performed modulo the current base
* =================================================== * ===================================================
*/ */
// 7-Segment patterns for 0F /* 7-Segment patterns for 0F */
const unsigned char seven_seg[16] = { const unsigned char seven_seg[16] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71
}; };
/* ===== Pin Mapping ===== /* ===== Pin & Mode Definitions ===== */
* Keypad (4x4):
* Columns: P0.15P0.18 (Outputs)
* Rows: P0.19P0.22 (Inputs, pull-ups)
*
* 7-Segment:
* Segments: P0.4P0.11
* Digit Enable: P1.23
*
* LCD:
* Data: P0.23P0.26, RS: P0.27, EN: P0.28
*
* Mode Button: P2.12 (active low)
*/
/* ===== MACROS ===== */
#define COL_BASE 15 #define COL_BASE 15
#define ROW_BASE 19 #define ROW_BASE 19
#define COL_MASK (0x0F << COL_BASE) #define COL_MASK (0x0F << COL_BASE)
@ -47,20 +33,21 @@ const unsigned char seven_seg[16] = {
#define MODE_BUTTON (1 << 12) #define MODE_BUTTON (1 << 12)
/* Supported Bases */
#define MODE_BIN 2 #define MODE_BIN 2
#define MODE_BASE4 4 #define MODE_BASE4 4
#define MODE_OCT 8 #define MODE_OCT 8
#define MODE_DEC 10 #define MODE_DEC 10
#define MODE_HEX 16 #define MODE_HEX 16
/* Operators */
#define OP_NONE 0 #define OP_NONE 0
#define OP_ADD 1 #define OP_ADD 1
#define OP_SUB 2 #define OP_SUB 2
#define OP_MUL 3 #define OP_MUL 3
/* ===== Global Variables (Predeclared) ===== */ /* ===== Global Variables (predeclared) ===== */
int input_num; int input_num;
unsigned int seg_pattern;
int stored_num; int stored_num;
int result; int result;
unsigned int current_base; unsigned int current_base;
@ -71,7 +58,7 @@ unsigned char result_displayed;
unsigned int key, last_key, stable; unsigned int key, last_key, stable;
unsigned int button_state, last_button_state, button_stable; unsigned int button_state, last_button_state, button_stable;
/* ===== Function Declarations ===== */ /* ===== Function Prototypes ===== */
void delay(volatile unsigned int d); void delay(volatile unsigned int d);
void lcd_delay(unsigned long r); void lcd_delay(unsigned long r);
void lcd_write_nibble(unsigned char nibble, unsigned char is_data); void lcd_write_nibble(unsigned char nibble, unsigned char is_data);
@ -89,8 +76,9 @@ unsigned int is_valid_digit(unsigned int key);
void change_mode(void); void change_mode(void);
void operate(unsigned int op); void operate(unsigned int op);
void perform_operation(void); void perform_operation(void);
unsigned char is_operator_active(unsigned int key, unsigned int mode_button);
/* ===== Delays ===== */ /* ====== Utility ====== */
void delay(volatile unsigned int d) { void delay(volatile unsigned int d) {
while (d--) while (d--)
__NOP(); __NOP();
@ -102,7 +90,7 @@ void lcd_delay(unsigned long r) {
; ;
} }
/* ===== LCD ===== */ /* ===== LCD ==== */
void lcd_write_nibble(unsigned char nibble, unsigned char is_data) { void lcd_write_nibble(unsigned char nibble, unsigned char is_data) {
unsigned long temp; unsigned long temp;
temp = (nibble & 0x0F) << LCD_DATA_SHIFT; temp = (nibble & 0x0F) << LCD_DATA_SHIFT;
@ -149,11 +137,11 @@ void lcd_init(void) {
} }
void lcd_print_str(const char *str) { void lcd_print_str(const char *str) {
while (*str) { while (*str)
lcd_data(*str++); lcd_data(*str++);
}
} }
/* ===== Print number in base ===== */
void lcd_print_num(int num, unsigned int base) { void lcd_print_num(int num, unsigned int base) {
char buffer[17]; char buffer[17];
int i = 0; int i = 0;
@ -184,11 +172,12 @@ void lcd_print_num(int num, unsigned int base) {
num /= 10; num /= 10;
} }
} }
while (i > 0) while (i > 0)
lcd_data(buffer[--i]); lcd_data(buffer[--i]);
} }
/* ===== Display Handling ===== */ /* ===== Display handlers ===== */
void display_mode(void) { void display_mode(void) {
lcd_cmd(0x80); lcd_cmd(0x80);
lcd_print_str("Mode: "); lcd_print_str("Mode: ");
@ -206,7 +195,18 @@ void display_mode(void) {
void display_input(void) { void display_input(void) {
lcd_cmd(0xC0); lcd_cmd(0xC0);
lcd_print_str("Inp: "); 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_num(input_num, current_base); lcd_print_num(input_num, current_base);
lcd_print_str(" "); lcd_print_str(" ");
} }
@ -220,7 +220,7 @@ void display_operator_feedback(const char *op_symbol) {
display_input(); display_input();
} }
/* ===== Input Handling ===== */ /* ====== Scan Keypad ====== */
unsigned int scan_keypad(void) { unsigned int scan_keypad(void) {
unsigned int col, row; unsigned int col, row;
unsigned int row_bits; unsigned int row_bits;
@ -236,7 +236,7 @@ unsigned int scan_keypad(void) {
for (row = 0; row < 4; row++) { for (row = 0; row < 4; row++) {
if ((row_bits & (1 << row)) == 0) { if ((row_bits & (1 << row)) == 0) {
LPC_GPIO0->FIOSET = COL_MASK; LPC_GPIO0->FIOSET = COL_MASK;
return col * 4 + row; return (col * 4 + row);
} }
} }
} }
@ -245,11 +245,12 @@ unsigned int scan_keypad(void) {
return 0xFF; return 0xFF;
} }
/* ===== Mode button ===== */
unsigned int scan_mode_button(void) { unsigned int scan_mode_button(void) {
return ((LPC_GPIO2->FIOPIN & MODE_BUTTON) == 0) ? 1 : 0; return ((LPC_GPIO2->FIOPIN & MODE_BUTTON) == 0) ? 1 : 0;
} }
/* ===== Mode Switching ===== */ /* ===== Modes and Validation ===== */
void change_mode(void) { void change_mode(void) {
if (current_base == MODE_DEC) if (current_base == MODE_DEC)
current_base = MODE_BIN; current_base = MODE_BIN;
@ -261,6 +262,7 @@ void change_mode(void) {
current_base = MODE_HEX; current_base = MODE_HEX;
else else
current_base = MODE_DEC; current_base = MODE_DEC;
display_mode(); display_mode();
} }
@ -275,10 +277,10 @@ unsigned int is_valid_digit(unsigned int key) {
return 0; return 0;
if (current_base == MODE_DEC && key >= 10) if (current_base == MODE_DEC && key >= 10)
return 0; return 0;
return 1; // HEX accepts all 0-F return 1;
} }
/* ===== Operations ===== */ /* ===== Operator Handling ===== */
void operate(unsigned int op) { void operate(unsigned int op) {
stored_num = input_num; stored_num = input_num;
operation = op; operation = op;
@ -286,6 +288,7 @@ void operate(unsigned int op) {
result_displayed = 0; result_displayed = 0;
} }
/* perform_operation: arithmetic within the active base */
void perform_operation(void) { void perform_operation(void) {
if (operation == OP_ADD) if (operation == OP_ADD)
result = stored_num + input_num; result = stored_num + input_num;
@ -296,8 +299,27 @@ void perform_operation(void) {
else else
result = input_num; 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_cmd(0xC0);
lcd_print_str("Res: "); 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_num(result, current_base);
lcd_print_str(" "); lcd_print_str(" ");
@ -306,9 +328,15 @@ void perform_operation(void) {
result_displayed = 1; 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);
}
/* ===== MAIN ===== */ /* ===== MAIN ===== */
int main(void) { int main(void) {
// Initialize globals
input_num = stored_num = result = 0; input_num = stored_num = result = 0;
current_base = MODE_DEC; current_base = MODE_DEC;
operation = OP_NONE; operation = OP_NONE;
@ -318,25 +346,21 @@ int main(void) {
stable = button_stable = 0; stable = button_stable = 0;
button_state = last_button_state = 0; button_state = last_button_state = 0;
// Configure Pins /* Configure pins */
LPC_PINCON->PINSEL0 = 0; LPC_PINCON->PINSEL0 = 0;
LPC_PINCON->PINSEL1 = 0; LPC_PINCON->PINSEL1 = 0;
LPC_PINCON->PINSEL3 = 0; LPC_PINCON->PINSEL3 = 0;
LPC_PINCON->PINSEL4 = 0; LPC_PINCON->PINSEL4 = 0;
// Keypad setup
LPC_GPIO0->FIODIR |= COL_MASK; LPC_GPIO0->FIODIR |= COL_MASK;
LPC_GPIO0->FIODIR &= ~ROW_MASK; LPC_GPIO0->FIODIR &= ~ROW_MASK;
LPC_GPIO0->FIOSET = COL_MASK; LPC_GPIO0->FIOSET = COL_MASK;
// Mode button setup
LPC_GPIO2->FIODIR &= ~MODE_BUTTON; LPC_GPIO2->FIODIR &= ~MODE_BUTTON;
// 7-Segment setup
LPC_GPIO0->FIODIR |= (0xFF << SEG_SHIFT); LPC_GPIO0->FIODIR |= (0xFF << SEG_SHIFT);
LPC_GPIO1->FIODIR |= DIGIT_EN; LPC_GPIO1->FIODIR |= DIGIT_EN;
// LCD setup
LPC_GPIO0->FIODIR |= LCD_DATA_MASK | LCD_RS | LCD_EN; LPC_GPIO0->FIODIR |= LCD_DATA_MASK | LCD_RS | LCD_EN;
lcd_init(); lcd_init();
@ -347,7 +371,7 @@ int main(void) {
key = scan_keypad(); key = scan_keypad();
button_state = scan_mode_button(); button_state = scan_mode_button();
// Debounce keypad /* Debounce keypad */
if (key == last_key) { if (key == last_key) {
if (stable < 5) if (stable < 5)
stable++; stable++;
@ -356,7 +380,7 @@ int main(void) {
stable = 0; stable = 0;
} }
// Debounce mode button /* Debounce mode button */
if (button_state == last_button_state) { if (button_state == last_button_state) {
if (button_stable < 5) if (button_stable < 5)
button_stable++; button_stable++;
@ -365,64 +389,53 @@ int main(void) {
button_stable = 0; button_stable = 0;
} }
// Cycle through modes /* Handle mode change */
if (button_stable == 3 && button_state == 1) { if (button_stable == 3 && button_state == 1) {
change_mode(); change_mode();
button_stable = 5; button_stable = 5;
} }
// Handle keypad press /* Handle key event */
if (stable == 3 && key != 0xFF) { if (stable == 3 && key != 0xFF) {
unsigned char allow_operator = 0; unsigned char op_allowed = is_operator_active(key, button_state);
// Operators allowed directly for all modes except HEX (must hold mode) if (op_allowed) {
if (current_base == MODE_HEX && button_state == 1) if (key == 11) {
allow_operator = 1;
else if (current_base != MODE_HEX)
allow_operator = 1;
// Operator Keys: BF (indices 1115)
if (allow_operator) {
if (key == 11) { // B = +
operate(OP_ADD); operate(OP_ADD);
display_operator_feedback("+"); display_operator_feedback("+");
} else if (key == 12) { // C = CLR } else if (key == 12) {
input_num = stored_num = result = 0; input_num = stored_num = result = 0;
operation = OP_NONE; operation = OP_NONE;
result_displayed = 0; result_displayed = 0;
display_operator_feedback("CLR"); display_operator_feedback("CLR");
} else if (key == 13) { // D = - } else if (key == 13) {
operate(OP_SUB); operate(OP_SUB);
display_operator_feedback("-"); display_operator_feedback("-");
} else if (key == 14) { // E = * } else if (key == 14) {
operate(OP_MUL); operate(OP_MUL);
display_operator_feedback("*"); display_operator_feedback("*");
} else if (key == 15) { // F = = } else if (key == 15) {
perform_operation(); perform_operation();
} else if (is_valid_digit(key)) {
result_displayed = 0;
input_num = input_num * current_base + key;
display_input();
}
} else {
if (is_valid_digit(key)) {
result_displayed = 0;
input_num = input_num * current_base + key;
display_input();
} }
} else if (is_valid_digit(key)) {
result_displayed = 0;
input_num = input_num * current_base + key;
display_input();
} }
stable = 5; stable = 5;
} }
// ===== STATE DISPLAY on 7-Segment ===== /* Update 7-seg state display */
unsigned int seg_pattern;
if (operation == OP_NONE && result_displayed == 0) if (operation == OP_NONE && result_displayed == 0)
seg_pattern = 0x06; // '1' - Input mode seg_pattern = 0x06; // '1'
else if (operation != OP_NONE) else if (operation != OP_NONE)
seg_pattern = 0x5B | 0x80; // '2' + DP - Waiting for 2nd operand seg_pattern = 0x5B | 0x80; // '2' + dp
else if (result_displayed == 1) else if (result_displayed == 1)
seg_pattern = 0x4F | 0x80; // '3' + DP - Result shown seg_pattern = 0x4F | 0x80; // '3' + dp
else else
seg_pattern = 0x3F; // '0' - Reset seg_pattern = 0x3F; // '0'
LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT); LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT);
LPC_GPIO0->FIOSET = (seg_pattern << SEG_SHIFT); LPC_GPIO0->FIOSET = (seg_pattern << SEG_SHIFT);