From e36e8515931ec047100fffb75a9d3e330a5ab5a6 Mon Sep 17 00:00:00 2001 From: sherlock Date: Thu, 23 Oct 2025 12:56:40 +0530 Subject: [PATCH] PWM Disp --- ES/Lab/Lab11/PWM_Keyboard.c | 115 ++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/ES/Lab/Lab11/PWM_Keyboard.c b/ES/Lab/Lab11/PWM_Keyboard.c index ab9d4f2..ad1a739 100644 --- a/ES/Lab/Lab11/PWM_Keyboard.c +++ b/ES/Lab/Lab11/PWM_Keyboard.c @@ -1,8 +1,8 @@ #include "LPC17xx.h" // PWM variables -unsigned long int duty_cycle = 0; -unsigned long int pwm_counter = 0; +volatile unsigned long int duty_cycle = 10; // Start at 10% +volatile unsigned long int pwm_counter = 0; // Pin definitions #define LED_SHIFT 4 // CNA: P0.4-P0.11 @@ -18,10 +18,12 @@ unsigned long int pwm_counter = 0; #define COL_MASK_P0 (COL2 | COL3) #define COL_MASK_P2 (COL0 | COL1) -#define PWM_PERIOD 100 // Smaller for faster PWM +#define PWM_PERIOD 100 // 100 steps for percentage -static void short_delay(volatile unsigned int d) { - while(d--) __NOP(); +static void delay_ms(unsigned int ms) { + unsigned int i, j; + for(i = 0; i < ms; i++) + for(j = 0; j < 10000; j++); } static void set_column(unsigned int col) @@ -42,12 +44,12 @@ static unsigned int is_row0_pressed(void) return !(LPC_GPIO0->FIOPIN & ROW0); } -// PWM Interrupt Handler - Software PWM +// HIGH-SPEED PWM Interrupt Handler void PWM1_IRQHandler(void) { if (LPC_PWM1->IR & (1 << 0)) { - // Software PWM for all 8 LEDs + // Fast software PWM for all 8 LEDs if(pwm_counter < duty_cycle) LPC_GPIO0->FIOSET = LED_MASK; // All LEDs ON else @@ -57,72 +59,71 @@ void PWM1_IRQHandler(void) if(pwm_counter >= PWM_PERIOD) pwm_counter = 0; - LPC_PWM1->IR = (1 << 0); // Clear interrupt + LPC_PWM1->IR = (1 << 0); // Clear interrupt flag } } int main(void) { unsigned int col_idx; - unsigned int candidate_key = 0xFF; - unsigned int stable = 0; + unsigned int read_key; unsigned int last_key = 0xFF; - // === SYSTEM CLOCK SETUP (Optional but recommended) === - SystemInit(); // Use default clock setup - // === PIN CONFIGURATION === - LPC_PINCON->PINSEL0 &= ~(0xFFFF << 8); // Clear P0.4-P0.11 (GPIO) - LPC_PINCON->PINSEL1 &= ~(0xFFFF << 14); // Clear P0.23-P0.28 - LPC_PINCON->PINSEL3 &= ~(0x3 << 14); // Clear P1.23 - LPC_PINCON->PINSEL4 &= ~(0xF << 0); // Clear P2.0-P2.1 + LPC_PINCON->PINSEL0 &= ~(0xFFFF << 8); // P0.4-P0.11 as GPIO + LPC_PINCON->PINSEL1 &= ~(0xFFFF << 14); // P0.23-P0.28 as GPIO + LPC_PINCON->PINSEL4 &= ~(0xF << 0); // P2.0-P2.1 as GPIO - // === GPIO DIRECTION SETUP === - LPC_GPIO0->FIODIR |= LED_MASK; // P0.4-P0.11: LEDs (output) - LPC_GPIO0->FIODIR |= COL_MASK_P0; // Keypad columns (output) - LPC_GPIO2->FIODIR |= COL_MASK_P2; // Keypad columns (output) - LPC_GPIO0->FIODIR &= ~ROW0; // Row-0 (input) + // === GPIO SETUP === + LPC_GPIO0->FIODIR |= LED_MASK; // LEDs output + LPC_GPIO0->FIODIR |= COL_MASK_P0; // Columns output + LPC_GPIO2->FIODIR |= COL_MASK_P2; // Columns output + LPC_GPIO0->FIODIR &= ~ROW0; // Row input - // === INITIALIZE GPIO === - LPC_GPIO0->FIOCLR = LED_MASK; // All LEDs off initially - LPC_GPIO2->FIOSET = COL_MASK_P2; // Columns high - LPC_GPIO0->FIOSET = COL_MASK_P0; // Columns high + // Initialize + LPC_GPIO0->FIOCLR = LED_MASK; + LPC_GPIO2->FIOSET = COL_MASK_P2; + LPC_GPIO0->FIOSET = COL_MASK_P0; - // === PWM CONFIGURATION === + // === HIGH-SPEED PWM CONFIGURATION === LPC_SC->PCONP |= (1 << 6); // Power on PWM1 - LPC_PWM1->TCR = (1 << 1); // Reset PWM + LPC_PWM1->TCR = (1 << 1); // Reset LPC_PWM1->CTCR = 0; // Timer mode - LPC_PWM1->PR = 99; // Prescaler: divide by 100 - // Creates ~10kHz interrupt rate + LPC_PWM1->PR = 9; // Prescaler = 10 + // 100MHz / 10 = 10MHz timer clock - LPC_PWM1->MR0 = PWM_PERIOD; // PWM period = 100 - LPC_PWM1->MR4 = 0; // Duty cycle = 0 + LPC_PWM1->MR0 = 100; // Match every 100 ticks + // Interrupt rate = 10MHz/100 = 100kHz + // PWM frequency = 100kHz/100 = 1kHz + // NO VISIBLE FLICKER! - LPC_PWM1->MCR = (1 << 1) | (1 << 0); // Reset on MR0, interrupt enabled + LPC_PWM1->MCR = (1 << 1) | (1 << 0); // Reset on MR0 + interrupt LPC_PWM1->LER = (1 << 0); // Latch MR0 - NVIC_EnableIRQ(PWM1_IRQn); // Enable PWM interrupt + NVIC_EnableIRQ(PWM1_IRQn); // Enable interrupt NVIC_SetPriority(PWM1_IRQn, 0); // Highest priority - LPC_PWM1->TCR = (1 << 0) | (1 << 3); // Enable PWM and counter - - // Initial duty cycle: 10% - duty_cycle = 10; + LPC_PWM1->TCR = (1 << 0) | (1 << 3); // Start PWM // === MAIN LOOP === while(1) { - unsigned int read_key = 0xFF; + read_key = 0xFF; - // Scan ROW-0 (keys 0, 1, 2, 3) + // Scan ROW-0 only for(col_idx = 0; col_idx < 4; col_idx++) { set_column(col_idx); - short_delay(500); + delay_ms(5); // Short delay for stable reading if(is_row0_pressed()) { - read_key = col_idx; + read_key = col_idx; // Key 0, 1, 2, or 3 + + // Wait for key release + while(is_row0_pressed()) { + delay_ms(10); + } break; } } @@ -131,30 +132,18 @@ int main(void) LPC_GPIO2->FIOSET = COL_MASK_P2; LPC_GPIO0->FIOSET = COL_MASK_P0; - // Debounce - if(read_key == candidate_key) { - if(stable < 5) stable++; - } else { - candidate_key = read_key; - stable = 1; - } + // Update brightness immediately on key press + if(read_key != 0xFF && read_key != last_key) { + last_key = read_key; - // Update intensity when stable - if(stable >= 5) { - if(candidate_key != last_key && candidate_key != 0xFF) { - last_key = candidate_key; - - // Set duty cycle (out of 100) - switch(candidate_key) { - case 0: duty_cycle = 10; break; // 10% - case 1: duty_cycle = 25; break; // 25% - case 2: duty_cycle = 50; break; // 50% - case 3: duty_cycle = 75; break; // 75% - } + switch(read_key) { + case 0: duty_cycle = 10; break; // 10% + case 1: duty_cycle = 25; break; // 25% + case 2: duty_cycle = 50; break; // 50% + case 3: duty_cycle = 75; break; // 75% } - stable = 5; } - short_delay(5000); + delay_ms(50); // Main loop delay } }