Dec 162008
 

Although an LPC2148 has more than those, they are not very conveniently grouped on the board I have, so I used simple GPIO pins with software PWM. That reduced the amount of cabeling to using a single 10 pin flat ribbon cable to connect the LPC2148 board and the I/O board.

#define LAMPS_COUNT 4

void fiqISR (void)
{
  int i;

++fiqCounter;

for (i=0; i<4 ; ++i) {
  ++lampPWM[i].counter;
  if (lampPWM[i].counter > 99) {
  lampPWM[i].counter=0;
  if (lampPWM[i].duty!=0)
  /* Unless off forever, turn it on now */
  GPIO0_FIOCLR = lampPWM[i].gpio_mask;
}
  if (lampPWM[i].counter > lampPWM[i].duty)
  /* Turn off when duty cycle is fulfilled */
  GPIO0_FIOSET = lampPWM[i].gpio_mask;
  }

T1_IR = T_IR_MASK;
}


lampPWM is a struct with some fields, namely counter which counts up 1 per FIQ, duty which is the duty cycle from 0..100 with 0 being off, and 100 being on, and 1..99 for anything between, and gpio_mask which contains the GPIO pin to set/reset.

With an interrupt frequency of 10kHz (100 Hz update with 100 steps) this uses 3.4% CPU time on a LPC2148 at 48MHz and MAM fully enabled.

That's quite impressive. On a Z80 just entering the interrupt routine takes 3.2uS (19 cycles at 6MHz clock). Here the interrupt routine including all overhead runs in 3.3uS for 4 PWMs generated.