#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 * * KEY FUNCTIONS: * 0-9: Digit input (valid in all bases based on base) * A-F: Digit input (valid only in appropriate base) * Key A (10): Mode/Base selection (cycles: BIN->OCT->DEC->HEX) * Key B (11): Addition (+) * Key C (12): Clear (C) * Key D (13): Subtraction (-) * Key E (14): Multiplication (*) * Key F (15): Equals (=) */ // 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) // 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 unsigned int current_base = MODE_DEC; unsigned int input_num = 0; unsigned int stored_num = 0; unsigned int operation = OP_NONE; unsigned int result = 0; unsigned char lcd_flag = 0; 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(unsigned int num, unsigned int base){ char buffer[17]; int i = 0; if(num == 0){ lcd_data('0'); return; } while(num > 0 && i < 16){ unsigned int digit = num % base; if(digit < 10) buffer[i++] = '0' + digit; else buffer[i++] = 'A' + (digit - 10); num = num / base; } 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(" "); } 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; } 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; return 1; } int main(void){ unsigned int key, last_key = 0xFF; unsigned int stable = 0; // Configure pins LPC_PINCON->PINSEL0 = 0; LPC_PINCON->PINSEL1 = 0; LPC_PINCON->PINSEL3 = 0; // Keypad: Columns output, Rows input LPC_GPIO0->FIODIR |= COL_MASK; LPC_GPIO0->FIODIR &= ~ROW_MASK; LPC_GPIO0->FIOSET = COL_MASK; // 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(;;){ key = scan_keypad(); // Debounce if(key == last_key){ if(stable < 5) stable++; } else { last_key = key; stable = 0; } if(stable == 3 && key != 0xFF){ // Key pressed and stable // Handle digit input (0-9, A-F) if(is_valid_digit(key)){ input_num = input_num * current_base + key; if(input_num > 9999) input_num = input_num % 10000; display_input(); } // Mode selection (Key A / 10) else if(key == 10){ if(current_base == MODE_BIN) current_base = MODE_OCT; else if(current_base == MODE_OCT) current_base = MODE_DEC; else if(current_base == MODE_DEC) current_base = MODE_HEX; else current_base = MODE_BIN; display_mode(); } // Addition (Key B / 11) else if(key == 11){ stored_num = input_num; operation = OP_ADD; input_num = 0; display_input(); } // Clear (Key C / 12) else if(key == 12){ input_num = 0; stored_num = 0; operation = OP_NONE; result = 0; display_input(); } // Subtraction (Key D / 13) else if(key == 13){ stored_num = input_num; operation = OP_SUB; input_num = 0; display_input(); } // Multiplication (Key E / 14) else if(key == 14){ stored_num = input_num; operation = OP_MUL; input_num = 0; display_input(); } // Equals (Key F / 15) else if(key == 15){ 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; } stable = 5; } // Display result on 7-segment (last digit only) if(input_num < 16){ LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT); LPC_GPIO0->FIOSET = (seven_seg[input_num] << SEG_SHIFT); } else { unsigned int display_digit = input_num % 16; LPC_GPIO0->FIOCLR = (0xFF << SEG_SHIFT); LPC_GPIO0->FIOSET = (seven_seg[display_digit] << SEG_SHIFT); } LPC_GPIO1->FIOSET = DIGIT_EN; delay(3000); } }