MIT-Curricular/ES/Project/report.md
2025-10-24 09:48:16 +05:30

300 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.