# LPC1768 Multi-Base Calculator - Code Explainer & Hardware Mapping Report ## Overview This code implements a **multi-base calculator** for the LPC1768 microcontroller with support for Binary, Octal, Decimal, and Hexadecimal number systems. It features a 4x4 matrix keypad for input, a 16x2 LCD for display, and a single 7-segment display for quick output visualization. --- ## Core Functionality ### 1. **Number Base Modes** The calculator supports four number bases: - **Binary (BIN)** - Base 2 (digits 0-1) - **Octal (OCT)** - Base 8 (digits 0-7) - **Decimal (DEC)** - Base 10 (digits 0-9) - *Default mode* - **Hexadecimal (HEX)** - Base 16 (digits 0-9, A-F) Mode switching is done via the **P2.12 button** in the cycle: DEC → BIN → OCT → HEX → DEC... ### 2. **Keypad Operation** #### Standard Digit Input (Keys 0-F) - Keys 0-9 and A-F enter digits - Only valid digits for the current base are accepted - Numbers are built up by multiplying the current value by the base and adding the new digit #### Operator Mode (Hold Key 0 + Another Key) The code uses **Key 0 as a "shift" key** for operator access: | Combination | Function | Operation | |-------------|----------|-----------| | Key 0 + B | Addition | Stores current number, sets + operation | | Key 0 + C | Clear | Resets all values | | Key 0 + D | Subtraction | Stores current number, sets - operation | | Key 0 + E | Multiplication | Stores current number, sets × operation | | Key 0 + F | Equals | Calculates result based on stored operation | ### 3. **Signed Integer Handling** The code uses **signed 32-bit integers** (`int` type) with special display logic: - **Decimal mode**: Negative numbers shown with "-" sign - **Other bases**: Numbers displayed as unsigned (two's complement representation) - **7-segment display**: Decimal point illuminates to indicate negative numbers ### 4. **Display Outputs** #### LCD Display (16x2) - **Line 1**: Current mode ("Mode: BIN/OCT/DEC/HEX") - **Line 2**: Input number ("Inp: [number]") or Result ("Res: [number]") - Brief operator feedback shown when operations are selected #### 7-Segment Display - Shows the **last digit** (rightmost) of the current input in base-16 - **Decimal point lights up** when the number is negative --- ## Hardware Mapping to FRC Connectors ### **CNA Connector (P0.4 to P0.11)** **Usage: 7-Segment Display** | Pin CNA | LPC1768 Pin | Function | Code Reference | |---------|-------------|----------|----------------| | 1 | P0.4 | Segment a | `SEG_SHIFT = 4` | | 2 | P0.5 | Segment b | Bits 4-11 control segments | | 3 | P0.6 | Segment c | `seven_seg[]` array patterns | | 4 | P0.7 | Segment d | | | 5 | P0.8 | Segment e | | | 6 | P0.9 | Segment f | | | 7 | P0.10 | Segment g | | | 8 | P0.11 | Decimal point | Bit 7 of pattern (0x80) | | 10 | GND | Ground | | **Code Configuration:** ```c #define SEG_SHIFT 4 LPC_GPIO0->FIODIR |= (0xFF << SEG_SHIFT); // Configure as output LPC_GPIO0->FIOSET = (seg_pattern << SEG_SHIFT); // Set segments ``` --- ### **CNB Connector (P1.23-P1.26, P2.10-P2.13)** **Usage: 7-Segment Digit Enable & Mode Button** | Pin CNB | LPC1768 Pin | Function | Code Reference | |---------|-------------|----------|----------------| | 1 | P1.23 | 7-Seg Digit Enable | `DIGIT_EN (1<<23)` | | 7 | P2.12 | Mode Button (Input) | `MODE_BUTTON (1<<12)` | | 2-6, 8 | P1.24-26, P2.10-11, P2.13 | *Unused* | | | 10 | GND | Ground | | **Code Configuration:** ```c #define DIGIT_EN (1<<23) LPC_GPIO1->FIODIR |= DIGIT_EN; // P1.23 as output LPC_GPIO1->FIOSET = DIGIT_EN; // Enable digit #define MODE_BUTTON (1<<12) LPC_GPIO2->FIODIR &= ~MODE_BUTTON; // P2.12 as input (pull-up) ``` **Mode Button Behavior:** - Active LOW (reads 0 when pressed) - Debounced with 5-sample stability check - Cycles through number bases --- ### **CNC Connector (P0.15-P0.22, P2.13)** **Usage: 4×4 Matrix Keypad** | Pin CNC | LPC1768 Pin | Function | Keypad Role | |---------|-------------|----------|-------------| | 1 | P0.15 | Column 0 | Output (scan low) | | 2 | P0.16 | Column 1 | Output (scan low) | | 3 | P0.17 | Column 2 | Output (scan low) | | 4 | P0.18 | Column 3 | Output (scan low) | | 5 | P0.19 | Row 0 | Input (pull-high) | | 6 | P0.20 | Row 1 | Input (pull-high) | | 7 | P0.21 | Row 2 | Input (pull-high) | | 8 | P0.22 | Row 3 | Input (pull-high) | | 10 | GND | Ground | | **Keypad Matrix Layout:** ``` Col0 Col1 Col2 Col3 (15) (16) (17) (18) Row0 (19) 0 1 2 3 Row1 (20) 4 5 6 7 Row2 (21) 8 9 A B Row3 (22) C D E F ``` **Scanning Algorithm:** 1. Set all columns HIGH 2. Pull one column LOW 3. Read row pins 4. If a row is LOW, a key at that (column, row) is pressed 5. Key number = `col × 4 + row` **Code Configuration:** ```c #define COL_BASE 15 #define ROW_BASE 19 #define COL_MASK (0x0F << COL_BASE) // P0.15-18 #define ROW_MASK (0x0F << ROW_BASE) // P0.19-22 LPC_GPIO0->FIODIR |= COL_MASK; // Columns as output LPC_GPIO0->FIODIR &= ~ROW_MASK; // Rows as input ``` --- ### **CND Connector (P0.23-P0.28, P2.0-P2.1)** **Usage: 16×2 LCD Display (4-bit mode)** | Pin CND | LPC1768 Pin | Function | LCD Pin | |---------|-------------|----------|---------| | 1 | P0.23 | Data bit 4 (D4) | LCD D4 | | 2 | P0.24 | Data bit 5 (D5) | LCD D5 | | 3 | P0.25 | Data bit 6 (D6) | LCD D6 | | 4 | P0.26 | Data bit 7 (D7) | LCD D7 | | 5 | P0.27 | Register Select (RS) | LCD RS | | 6 | P0.28 | Enable (EN) | LCD EN | | 7-8 | P2.0-1 | *Unused* | | | 10 | GND | Ground | | **LCD Communication (4-bit Mode):** - Each byte sent as two 4-bit nibbles (high nibble first) - **RS = 0**: Command mode - **RS = 1**: Data mode - **EN pulse**: Latches data into LCD **Code Configuration:** ```c #define LCD_DATA_SHIFT 23 #define LCD_DATA_MASK (0x0F << LCD_DATA_SHIFT) // P0.23-26 #define LCD_RS (1<<27) // P0.27 #define LCD_EN (1<<28) // P0.28 LPC_GPIO0->FIODIR |= LCD_DATA_MASK | LCD_RS | LCD_EN; // All outputs ``` **LCD Initialization Sequence:** 1. Wait 5ms after power-on 2. Send 0x03 three times (8-bit mode reset) 3. Send 0x02 (switch to 4-bit mode) 4. Configure: 4-bit, 2-line, 5×8 font (0x28) 5. Display ON, cursor OFF (0x0C) 6. Clear display (0x01) 7. Entry mode: increment, no shift (0x06) --- ## Key Code Functions ### Keypad Scanning ```c unsigned int scan_keypad(void) ``` - Scans 4×4 matrix by pulling columns low sequentially - Returns key number (0-15) or 0xFF if no key pressed - Includes debouncing delay ### Shift Key Detection ```c unsigned int is_key0_pressed(void) ``` - Specifically checks if Key 0 is being held down - Enables "operator mode" when Key 0 + another key pressed ### Digit Validation ```c unsigned int is_valid_digit(unsigned int key) ``` - Ensures entered digit is valid for current base - BIN: 0-1, OCT: 0-7, DEC: 0-9, HEX: 0-F ### LCD Number Display ```c void lcd_print_num(int num, unsigned int base) ``` - Handles negative numbers in decimal mode (shows "-") - For other bases, displays unsigned representation - Converts number to string in specified base --- ## Operation Flow Example **Example: Calculate 5 + 3 in Decimal Mode** 1. **Power on** → Mode: DEC, Input: 0 2. **Press Key 5** → Input: 5 (displayed on LCD and 7-seg) 3. **Hold Key 0 + Press B** → "Op: +" feedback, stored = 5, input = 0 4. **Press Key 3** → Input: 3 5. **Hold Key 0 + Press F** → "Res: 8" displayed, input = 8 6. Result can be used for next calculation **Example: Switch to Binary Mode** 1. **Press P2.12 button** → Mode cycles DEC → BIN 2. LCD shows "Mode: BIN" 3. Only keys 0 and 1 are now valid 4. Display shows binary representation --- ## Debouncing Strategy Both keypad and mode button use **count-based debouncing**: ```c if(key == last_key){ if(stable < 5) stable++; } ``` - Requires **3 consecutive stable reads** before acting (`stable == 3`) - After action, sets `stable = 5` to prevent repeat triggers - Prevents false triggers from mechanical switch bounce --- ## Safety & Overflow Handling ```c if(input_num > 32767) input_num = input_num % 32768; if(input_num < -32768) input_num = -32768; ``` - Wraps overflow for signed 32-bit integers - Prevents display issues with very large numbers --- ## Pin Configuration Summary Table | GPIO Port | Pins Used | Direction | Function | FRC Connector | |-----------|-----------|-----------|----------|---------------| | P0.4-11 | 8 bits | Output | 7-seg segments | **CNA 1-8** | | P0.15-18 | 4 bits | Output | Keypad columns | **CNC 1-4** | | P0.19-22 | 4 bits | Input | Keypad rows | **CNC 5-8** | | P0.23-26 | 4 bits | Output | LCD data D4-D7 | **CND 1-4** | | P0.27 | 1 bit | Output | LCD RS | **CND 5** | | P0.28 | 1 bit | Output | LCD EN | **CND 6** | | P1.23 | 1 bit | Output | 7-seg digit enable | **CNB 1** | | P2.12 | 1 bit | Input | Mode button | **CNB 7** | --- ## Conclusion This calculator demonstrates effective use of the LPC1768's GPIO capabilities across multiple peripherals: - Efficient matrix keypad scanning minimizes pin usage - 4-bit LCD mode reduces wiring complexity - Single 7-segment provides instant visual feedback - Clever "shift key" mechanism provides operator access without dedicated buttons The hardware mapping efficiently utilizes all four FRC connectors to create a fully functional multi-base calculator with a clean user interface.