diff --git a/ES/Lab/Lab10/ADC_Display.c b/ES/Lab/Lab10/ADC_Display.c index d8ec614..d23954a 100644 --- a/ES/Lab/Lab10/ADC_Display.c +++ b/ES/Lab/Lab10/ADC_Display.c @@ -6,28 +6,31 @@ unsigned long int temp1 = 0, temp2 = 0, i, j; unsigned char flag1 = 0, flag2 = 0; -unsigned long result, y; // ADC variables -unsigned char adc_string[10]; // Buffer for ADC result string +unsigned long result, y; // ADC result void lcd_write(void); void port_write(void); void delay_lcd(unsigned long); -void int_to_string(unsigned long num, unsigned char* str); unsigned long int init_command[] = {0x30, 0x30, 0x30, 0x20, 0x28, 0x0C, 0x01, 0x80}; -int main() { - // LCD GPIO setup - LPC_GPIO0->FIODIR = DT_CTRL | RS_CTRL | EN_CTRL; - - // ADC setup - LPC_PINCON->PINSEL3 = 3 << 28; // P1.30 function 3 - LPC_SC->PCONP = 1 << 12; // power control - LPC_ADC->ADCR = 1 << 4 | 1 << 16 | 1 << 21; // ADC4, burst mode, enable - LPC_ADC->ADINTEN = (1 << 4); // Interrupt enable +void ADC_Init(void) { + LPC_PINCON->PINSEL3 = 3 << 28; + LPC_SC->PCONP = 1 << 12; + LPC_ADC->ADCR = 1 << 4 | 1 << 16 | 1 << 21; + LPC_ADC->ADINTEN = (1 << 4); NVIC_EnableIRQ(ADC_IRQn); +} + +void ADC_IRQHandler(void) { + result = (LPC_ADC->ADGDR & (0xFFF << 4)) >> 4; + y = (LPC_ADC->ADDR4 & (0xFFF << 4)) >> 4; +} + +int main() { + LPC_GPIO0->FIODIR = DT_CTRL | RS_CTRL | EN_CTRL; + ADC_Init(); - // LCD initialization flag1 = 0; for (i = 0; i < 8; i++) { temp1 = init_command[i]; @@ -35,65 +38,25 @@ int main() { } flag1 = 1; + delay_lcd(500000); - while(1) { - // Convert ADC result to string and display - int_to_string(result, adc_string); + // Convert result to 4 ASCII digits + unsigned char digits[4]; + digits[0] = (result / 1000) % 10 + '0'; + digits[1] = (result / 100) % 10 + '0'; + digits[2] = (result / 10) % 10 + '0'; + digits[3] = result % 10 + '0'; - // Clear display and reset cursor - flag1 = 0; - temp1 = 0x01; // Clear display + for (i = 0; i < 4; i++) { + temp1 = digits[i]; lcd_write(); - temp1 = 0x80; // Set cursor to home - lcd_write(); - flag1 = 1; - - // Display the ADC result - i = 0; - while(adc_string[i] != '\0') { - temp1 = adc_string[i]; - i++; - lcd_write(); - } - - delay_lcd(5000000); // Update every ~1 second - } -} - -void ADC_IRQHandler(void) { - result = (LPC_ADC->ADGDR & (0xFFF << 4)) >> 4; // Read 12-bit ADC result - y = (LPC_ADC->ADDR4 & (0xFFF << 4)) >> 4; // Done bit reset -} - -void int_to_string(unsigned long num, unsigned char* str) { - int i = 0, j; - unsigned char temp; - - // Handle zero case - if (num == 0) { - str[0] = '0'; - str[1] = '\0'; - return; } - // Convert number to string (reverse order) - while (num > 0) { - str[i++] = (num % 10) + '0'; - num /= 10; - } - str[i] = '\0'; - - // Reverse the string - for (j = 0; j < i/2; j++) { - temp = str[j]; - str[j] = str[i-1-j]; - str[i-1-j] = temp; - } + while (1); } void lcd_write(void) { flag2 = (flag1 == 1) ? 0 : (((temp1 == 0x30) || (temp1 == 0x20)) ? 1 : 0); - temp2 = temp1 & 0xf0; temp2 = temp2 << 19; port_write(); @@ -107,13 +70,11 @@ void lcd_write(void) { void port_write(void) { LPC_GPIO0->FIOPIN = temp2; - if (flag1 == 0) { LPC_GPIO0->FIOCLR = RS_CTRL; } else { LPC_GPIO0->FIOSET = RS_CTRL; } - LPC_GPIO0->FIOSET = EN_CTRL; delay_lcd(100); LPC_GPIO0->FIOCLR = EN_CTRL; diff --git a/ES/Project/code.c b/ES/Project/code.c new file mode 100644 index 0000000..9a4a9dc --- /dev/null +++ b/ES/Project/code.c @@ -0,0 +1,330 @@ +#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); + } +} diff --git a/ES/Project/report.md b/ES/Project/report.md new file mode 100644 index 0000000..10fae47 --- /dev/null +++ b/ES/Project/report.md @@ -0,0 +1,62 @@ +# Calculator Program for Multi-Base Arithmetic + +## How to Use the Calculator + +### Initial Setup +- On power-up, the calculator starts in **DECIMAL mode** +- LCD shows: `Mode: DEC` on line 1, `Inp: 0` on line 2 +- 7-segment displays the last digit of your input + +### Basic Operations + +1. **Entering Numbers** + - Press keys 0-9 for decimal digits + - In HEX mode, you can also use A-F (keys 10-15) + - In OCT mode, only 0-7 are valid + - In BIN mode, only 0-1 are valid + - Invalid digits for the current mode are ignored + +2. **Changing Base Mode** + - Press **Key A (10)** to cycle through bases + - Order: BIN → OCT → DEC → HEX → BIN... + - Current mode displays on LCD top line + +3. **Performing Calculations** + - Enter first number + - Press operation key: + - **Key B (11)**: Addition + - **Key D (13)**: Subtraction + - **Key E (14)**: Multiplication + - Enter second number + - Press **Key F (15)** for equals/result + +4. **Clearing** + - Press **Key C (12)** to clear all (input, stored number, operation) + +### Example Usage + +**Example 1: Add 5 + 3 in Decimal** +``` +Press: 5 → B → 3 → F +Display: Res: 8 +``` + +**Example 2: Multiply 1010 × 11 in Binary** +``` +Press: A (change to BIN mode) +Press: 1 → 0 → 1 → 0 → E → 1 → 1 → F +Display: Res: 11110 (30 in decimal) +``` + +**Example 3: Subtract F - A in Hexadecimal** +``` +Press: A (cycle to HEX mode if not already) +Press: F → D → A (10) → F +Display: Res: 5 +``` + +### Tips +- The 7-segment always shows the last hex digit of your current input +- Results stay in the current base mode +- If result exceeds display capacity, only visible portion shows +- After equals, the result becomes the new input for next operation