proj
This commit is contained in:
parent
c59338aeea
commit
6693a1a831
1 changed files with 89 additions and 76 deletions
|
|
@ -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 B–F work directly
|
* BIN/BASE4/OCT/DEC: operators B–F direct
|
||||||
* HEX : Operators B–F require MODE pressed
|
* HEX: operators B–F only when MODE button held
|
||||||
|
* Arithmetic is performed modulo the current base
|
||||||
* ===================================================
|
* ===================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 7-Segment patterns for 0–F
|
/* 7-Segment patterns for 0–F */
|
||||||
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.15–P0.18 (Outputs)
|
|
||||||
* Rows: P0.19–P0.22 (Inputs, pull-ups)
|
|
||||||
*
|
|
||||||
* 7-Segment:
|
|
||||||
* Segments: P0.4–P0.11
|
|
||||||
* Digit Enable: P1.23
|
|
||||||
*
|
|
||||||
* LCD:
|
|
||||||
* Data: P0.23–P0.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: B–F (indices 11–15)
|
|
||||||
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)) {
|
} else if (is_valid_digit(key)) {
|
||||||
result_displayed = 0;
|
result_displayed = 0;
|
||||||
input_num = input_num * current_base + key;
|
input_num = input_num * current_base + key;
|
||||||
display_input();
|
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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue