diff --git a/ES/Project/code-with-7seg.c b/ES/Project/code-with-7seg.c new file mode 100644 index 0000000..1c833db --- /dev/null +++ b/ES/Project/code-with-7seg.c @@ -0,0 +1,458 @@ +#include + +/* PORT MAPPING: + * KEYPAD MATRIX (4x4): + * Columns: P0.15 - P0.18 (Output, pulled high, scan low) + * Rows: P0.19 - P0.22 (Input, pulled high internally) + * + * Layout: 0 1 2 3 + * 4 5 6 7 + * 8 9 A B + * C D E F + * + * 7-SEGMENT DISPLAY: + * Segments: P0.4 - P0.11 (a-g + dp) + * Digit Enable: P1.23 (active high) + * + * LCD (16x2): + * Data: P0.23 - P0.26 (D4-D7, 4-bit mode) + * RS: P0.27 + * EN: P0.28 + * + * MODE BUTTON: + * P2.12 (Input, internal pull-up) + * + * KEY FUNCTIONS: + * 0-9, A-F: Digit input (valid based on current base) + * + * OPERATOR MODE (Hold Key 0 + another key): + * Key 0 + B: Addition (+) + * Key 0 + C: Clear (C) + * Key 0 + D: Subtraction (-) + * Key 0 + E: Multiplication (*) + * Key 0 + F: Equals (=) + * + * P2.12 Button: Mode selection (cycles: DEC->BIN->OCT->HEX) + * + * 7-SEGMENT STATE DISPLAY: + * '0' - Cleared/Reset state + * '1' - Input mode (entering numbers) + * '2' with DP - Operation pending (waiting for 2nd number) + * '3' with DP - Result ready (showing calculation result) + */ + +// 7-Segment patterns +const unsigned char seven_seg[16] = { + 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, + 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71 +}; + +// Keypad defines +#define COL_BASE 15 +#define ROW_BASE 19 +#define COL_MASK (0x0F << COL_BASE) +#define ROW_MASK (0x0F << ROW_BASE) + +// 7-Segment defines +#define SEG_SHIFT 4 +#define DIGIT_EN (1<<23) + +// LCD defines +#define LCD_DATA_SHIFT 23 +#define LCD_DATA_MASK (0x0F << LCD_DATA_SHIFT) +#define LCD_RS (1<<27) +#define LCD_EN (1<<28) + +// Mode button defines +#define MODE_BUTTON (1<<12) + +// Calculator states +#define MODE_BIN 2 +#define MODE_OCT 8 +#define MODE_DEC 10 +#define MODE_HEX 16 + +#define OP_NONE 0 +#define OP_ADD 1 +#define OP_SUB 2 +#define OP_MUL 3 + +// Global variables +int input_num = 0; +int stored_num = 0; +int result = 0; +unsigned int current_base = MODE_DEC; +unsigned int operation = OP_NONE; +unsigned char lcd_flag = 0; +unsigned char result_displayed = 0; // NEW: Track if showing result + +void delay(volatile unsigned int d){ + while(d--) __NOP(); +} + +void lcd_delay(unsigned long r){ + unsigned long i; + for(i=0; iFIOPIN = (LPC_GPIO0->FIOPIN & ~LCD_DATA_MASK) | temp; + + if(is_data) + LPC_GPIO0->FIOSET = LCD_RS; + else + LPC_GPIO0->FIOCLR = LCD_RS; + + LPC_GPIO0->FIOSET = LCD_EN; + lcd_delay(100); + LPC_GPIO0->FIOCLR = LCD_EN; + lcd_delay(500000); +} + +void lcd_cmd(unsigned char cmd){ + lcd_write_nibble(cmd >> 4, 0); + lcd_write_nibble(cmd, 0); +} + +void lcd_data(unsigned char data){ + lcd_write_nibble(data >> 4, 1); + lcd_write_nibble(data, 1); +} + +void lcd_init(void){ + lcd_delay(5000000); + lcd_write_nibble(0x03, 0); + lcd_delay(500000); + lcd_write_nibble(0x03, 0); + lcd_delay(500000); + lcd_write_nibble(0x03, 0); + lcd_delay(500000); + lcd_write_nibble(0x02, 0); + lcd_delay(500000); + + lcd_cmd(0x28); + lcd_cmd(0x0C); + lcd_cmd(0x01); + lcd_delay(500000); + lcd_cmd(0x06); +} + +void lcd_print_str(const char* str){ + while(*str){ + lcd_data(*str++); + } +} + +void lcd_print_num(int num, unsigned int base){ + char buffer[17]; + int i = 0; + + // For non-decimal bases, show as unsigned (two's complement representation) + 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; + if(digit < 10) + buffer[i++] = '0' + digit; + else + buffer[i++] = 'A' + (digit - 10); + unum = unum / base; + } + } else { + // Decimal mode: handle negative with minus sign + 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 = num / 10; + } + } + + while(i > 0){ + lcd_data(buffer[--i]); + } +} + +void display_mode(void){ + lcd_cmd(0x80); + lcd_print_str("Mode: "); + if(current_base == MODE_BIN) + lcd_print_str("BIN "); + else if(current_base == MODE_OCT) + lcd_print_str("OCT "); + else if(current_base == MODE_DEC) + lcd_print_str("DEC "); + else + lcd_print_str("HEX "); +} + +void display_input(void){ + lcd_cmd(0xC0); + lcd_print_str("Inp: "); + lcd_print_num(input_num, current_base); + lcd_print_str(" "); +} + +void display_operator_feedback(const char* op_symbol){ + // Brief feedback on line 2 + lcd_cmd(0xC0); + lcd_print_str("Op: "); + lcd_print_str(op_symbol); + lcd_print_str(" "); + delay(100000); // Brief delay to show feedback + display_input(); // Return to showing input +} + +unsigned int scan_keypad(void){ + unsigned int col, row; + unsigned int row_bits; + + for(col=0; col<4; col++){ + LPC_GPIO0->FIOSET = COL_MASK; + delay(50); + LPC_GPIO0->FIOCLR = (1 << (COL_BASE + col)); + delay(200); + row_bits = (LPC_GPIO0->FIOPIN & ROW_MASK) >> ROW_BASE; + + if(row_bits != 0x0F){ + for(row=0; row<4; row++){ + if((row_bits & (1<FIOSET = COL_MASK; + return col*4 + row; + } + } + } + } + LPC_GPIO0->FIOSET = COL_MASK; + return 0xFF; +} + +// Check if Key 0 is currently pressed (shift key) +unsigned int is_key0_pressed(void){ + unsigned int col = 0; // Key 0 is at column 0, row 0 + unsigned int row_bits; + + LPC_GPIO0->FIOSET = COL_MASK; + delay(50); + LPC_GPIO0->FIOCLR = (1 << (COL_BASE + col)); + delay(200); + row_bits = (LPC_GPIO0->FIOPIN & ROW_MASK) >> ROW_BASE; + LPC_GPIO0->FIOSET = COL_MASK; + + // Check if row 0 is pressed (Key 0) + return ((row_bits & 0x01) == 0) ? 1 : 0; +} + +unsigned int scan_mode_button(void){ + // Return 1 if button is pressed (active low), 0 if not pressed + return ((LPC_GPIO2->FIOPIN & MODE_BUTTON) == 0) ? 1 : 0; +} + +unsigned int is_valid_digit(unsigned int key){ + if(key >= 16) return 0; + if(current_base == MODE_BIN && key >= 2) return 0; + if(current_base == MODE_OCT && key >= 8) return 0; + if(current_base == MODE_DEC && key >= 10) return 0; + // In HEX mode, all keys 0-15 are valid digits! + return 1; +} + +void change_mode(void){ + if(current_base == MODE_DEC) + current_base = MODE_BIN; + else if(current_base == MODE_BIN) + current_base = MODE_OCT; + else if(current_base == MODE_OCT) + current_base = MODE_HEX; + else + current_base = MODE_DEC; + display_mode(); +} + +int main(void){ + unsigned int key, last_key = 0xFF; + unsigned int stable = 0; + unsigned int button_state, last_button_state = 0; + unsigned int button_stable = 0; + unsigned int shift_active = 0; + + // Configure pins + LPC_PINCON->PINSEL0 = 0; + LPC_PINCON->PINSEL1 = 0; + LPC_PINCON->PINSEL3 = 0; + LPC_PINCON->PINSEL4 = 0; // Configure P2.12 + + // Keypad: Columns output, Rows input + LPC_GPIO0->FIODIR |= COL_MASK; + LPC_GPIO0->FIODIR &= ~ROW_MASK; + LPC_GPIO0->FIOSET = COL_MASK; + + // Mode button: Input with internal pull-up + LPC_GPIO2->FIODIR &= ~MODE_BUTTON; // Set as input + + // 7-Segment + LPC_GPIO0->FIODIR |= (0xFF << SEG_SHIFT); + LPC_GPIO1->FIODIR |= DIGIT_EN; + + // LCD + LPC_GPIO0->FIODIR |= LCD_DATA_MASK | LCD_RS | LCD_EN; + + lcd_init(); + display_mode(); + display_input(); + + for(;;){ + // Check if shift key (Key 0) is being held + shift_active = is_key0_pressed(); + + // Scan for other keys + key = scan_keypad(); + button_state = scan_mode_button(); + + // Debounce keypad + if(key == last_key){ + if(stable < 5) stable++; + } else { + last_key = key; + stable = 0; + } + + // Debounce mode button + if(button_state == last_button_state){ + if(button_stable < 5) button_stable++; + } else { + last_button_state = button_state; + button_stable = 0; + } + + // Handle mode button press + if(button_stable == 3 && button_state == 1){ + change_mode(); + button_stable = 5; // Prevent multiple triggers + } + + // Handle keypad input + if(stable == 3 && key != 0xFF){ + // Key pressed and stable + + // If Key 0 is also pressed, we're in operator mode + if(shift_active && key != 0){ + // OPERATOR MODE (Key 0 + another key) + + if(key == 11){ // Key 0 + B = Addition + stored_num = input_num; + operation = OP_ADD; + input_num = 0; + result_displayed = 0; // Clear result flag + display_operator_feedback("+"); + } + else if(key == 12){ // Key 0 + C = Clear + input_num = 0; + stored_num = 0; + operation = OP_NONE; + result = 0; + result_displayed = 0; // Clear result flag + display_operator_feedback("CLR"); + } + else if(key == 13){ // Key 0 + D = Subtraction + stored_num = input_num; + operation = OP_SUB; + input_num = 0; + result_displayed = 0; // Clear result flag + display_operator_feedback("-"); + } + else if(key == 14){ // Key 0 + E = Multiplication + stored_num = input_num; + operation = OP_MUL; + input_num = 0; + result_displayed = 0; // Clear result flag + display_operator_feedback("*"); + } + else if(key == 15){ // Key 0 + F = Equals + 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; + + lcd_cmd(0xC0); + lcd_print_str("Res: "); + lcd_print_num(result, current_base); + lcd_print_str(" "); + + input_num = result; + operation = OP_NONE; + result_displayed = 1; // Set result flag + } + } + else { + // NORMAL MODE - Digit input + if(is_valid_digit(key)){ + result_displayed = 0; // Clear result flag on new input + input_num = input_num * current_base + key; + // Handle overflow with wrap-around for signed int + if(input_num > 32767) input_num = input_num % 32768; + if(input_num < -32768) input_num = -32768; + display_input(); + } + } + + stable = 5; // Prevent repeated triggers + } + + // ===== STATE MACHINE DISPLAY ON 7-SEGMENT ===== + unsigned int seg_pattern; + + // State 1: INPUT MODE (Display '1') + // - No operation pending + // - Not showing a result + if(operation == OP_NONE && result_displayed == 0) { + seg_pattern = 0x06; // Display '1' + } + + // State 2: OPERATION PENDING (Display '2' with DP) + // - Operation selected + // - Waiting for second number + else if(operation != OP_NONE) { + seg_pattern = 0x5B | 0x80; // Display '2' with decimal point ON + } + + // State 3: RESULT READY (Display '3' with DP) + // - Result was just calculated + // - Showing the result + else if(result_displayed == 1) { + seg_pattern = 0x4F | 0x80; // Display '3' with decimal point ON + } + + // State 0: CLEARED/RESET (Display '0') + // - Everything is zero + // - Fallback state + else { + seg_pattern = 0x3F; // Display '0' + } + + // Update the 7-segment display + LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT); + LPC_GPIO0->FIOSET = (seg_pattern << SEG_SHIFT); + LPC_GPIO1->FIOSET = DIGIT_EN; + + delay(3000); + } +}