300 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# 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.
 |