#include "LPC17xx.h" // PWM variables unsigned long int duty_cycle = 0; unsigned long int pwm_counter = 0; // Pin definitions based on connectors #define LED_SHIFT 4 // CNA: P0.4-P0.11 (8 LEDs) #define LED_MASK (0xFF << LED_SHIFT) // Keypad on CND - Only ROW-0 #define COL0 (1<<0) // P2.0 #define COL1 (1<<1) // P2.1 #define COL2 (1<<23) // P0.23 #define COL3 (1<<24) // P0.24 #define ROW0 (1<<25) // P0.25 (ROW-0 only) #define COL_MASK_P0 (COL2 | COL3) #define COL_MASK_P2 (COL0 | COL1) static void short_delay(volatile unsigned int d) { while(d--) __NOP(); } // Set a specific column low, others high static void set_column(unsigned int col) { // Set all columns high first LPC_GPIO2->FIOSET = COL_MASK_P2; LPC_GPIO0->FIOSET = COL_MASK_P0; // Pull specific column low switch(col) { case 0: LPC_GPIO2->FIOCLR = COL0; break; case 1: LPC_GPIO2->FIOCLR = COL1; break; case 2: LPC_GPIO0->FIOCLR = COL2; break; case 3: LPC_GPIO0->FIOCLR = COL3; break; } } // Check if ROW-0 is pressed static unsigned int is_row0_pressed(void) { return !(LPC_GPIO0->FIOPIN & ROW0); } // PWM Interrupt Handler void PWM1_IRQHandler(void) { if (LPC_PWM1->IR & (1 << 0)) { // Software PWM for LEDs (CNA: P0.4-P0.11) pwm_counter++; if(pwm_counter >= 3000) pwm_counter = 0; if(pwm_counter < duty_cycle) LPC_GPIO0->FIOSET = LED_MASK; // LEDs ON else LPC_GPIO0->FIOCLR = LED_MASK; // LEDs OFF LPC_PWM1->IR = (1 << 0); // Clear interrupt } } int main(void) { unsigned int col_idx; unsigned int candidate_key = 0xFF; unsigned int stable = 0; unsigned int last_key = 0xFF; // === PIN CONFIGURATION === LPC_PINCON->PINSEL0 = 0x00000000; // All GPIO LPC_PINCON->PINSEL1 = 0x00000000; LPC_PINCON->PINSEL3 = (2 << 14); // PWM1.4 on P1.23 (optional) LPC_PINCON->PINSEL4 = 0x00000000; // === GPIO DIRECTION SETUP === // CNA: LEDs (P0.4-P0.11) LPC_GPIO0->FIODIR |= LED_MASK; // CND: Keypad - Columns output, Row-0 input LPC_GPIO0->FIODIR |= COL_MASK_P0; // Columns (output) LPC_GPIO2->FIODIR |= COL_MASK_P2; // Columns (output) LPC_GPIO0->FIODIR &= ~ROW0; // Row-0 (input) // === INITIALIZE GPIO STATES === LPC_GPIO0->FIOCLR = LED_MASK; // LEDs off LPC_GPIO2->FIOSET = COL_MASK_P2; // Columns high (idle) LPC_GPIO0->FIOSET = COL_MASK_P0; // Columns high (idle) // === PWM CONFIGURATION === LPC_PWM1->TCR = (1 << 1); // Reset PWM LPC_PWM1->CTCR = 0; // Timer mode LPC_PWM1->PR = 0; // No prescaler LPC_PWM1->MR0 = 3000; // PWM period = 3000 LPC_PWM1->MR4 = duty_cycle; // Initial duty cycle = 0 LPC_PWM1->MCR = (1 << 1) | (1 << 0); // Reset and interrupt on MR0 LPC_PWM1->PCR = (1 << 12); // Enable PWM4 output LPC_PWM1->LER = (1 << 0) | (1 << 4); // Latch MR0 and MR4 NVIC_EnableIRQ(PWM1_IRQn); // Enable PWM interrupt LPC_PWM1->TCR = (1 << 0) | (1 << 3); // Enable counter and PWM // === MAIN LOOP === while(1) { unsigned int read_key = 0xFF; // Scan ROW-0 only (columns 0-3 = keys 0, 1, 2, 3) for(col_idx = 0; col_idx < 4; col_idx++) { set_column(col_idx); short_delay(200); if(is_row0_pressed()) { read_key = col_idx; // Key 0, 1, 2, or 3 break; } } // Restore all columns high LPC_GPIO2->FIOSET = COL_MASK_P2; LPC_GPIO0->FIOSET = COL_MASK_P0; // Debounce logic if(read_key == candidate_key) { if(stable < 3) stable++; } else { candidate_key = read_key; stable = 1; } // Update intensity when key is stable and changed if(stable >= 3) { if(candidate_key != last_key && candidate_key != 0xFF) { last_key = candidate_key; // Set duty cycle based on key pressed switch(candidate_key) { case 0: duty_cycle = 300; break; // 10% of 3000 case 1: duty_cycle = 750; break; // 25% of 3000 case 2: duty_cycle = 1500; break; // 50% of 3000 case 3: duty_cycle = 2250; break; // 75% of 3000 } LPC_PWM1->MR4 = duty_cycle; LPC_PWM1->LER = (1 << 4); } stable = 3; } short_delay(2000); } }