//Mark Higgins 2010
#include "LPC13xx.h" /* LPC13xx Peripheral Registers */
#define ZERO_CROSS ( 1 << 6)
#define LIGHT0 ( 1 << 0)
#define LIGHT1 ( 1 << 1)
#define LIGHT2 ( 1 << 2)
#define LIGHT3 ( 1 << 4)
#define LIGHT4 ( 1 << 11)
#define LIGHT5 ( 1 << 5)
#define LIGHT6 ( 1 << 6)
#define LIGHT7 ( 1 << 7)
typedef struct
{
uint16_t on_point;
uint16_t current_dim_value;
uint16_t irq_int_counter;
uint16_t *script;
} lights;
//COMMANDS
#define CMD_RETURN_TO_START 0 // no parameters
#define CMD_DELAY 1 //, delay
#define CMD_ON 2 //, delay
#define CMD_OFF 3 //, delay
#define CMD_MOVE_TO 4 //, target, steps
#define CMD_SYNC 5 // no parameters
const uint16_t script_light0[] = { CMD_ON , 60, CMD_OFF, 60, CMD_OFF, 60, CMD_OFF, 60,
CMD_OFF, 200, CMD_MOVE_TO, 1, 1, CMD_MOVE_TO, 450, 1, CMD_ON, 400,
CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60, CMD_ON, 60,
CMD_MOVE_TO, 450, 4, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light1[] = { CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60, CMD_OFF, 60,
CMD_ON, 200, CMD_MOVE_TO, 450, 1, CMD_MOVE_TO, 1, 1, CMD_ON, 400,
CMD_ON, 60, CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60,
CMD_MOVE_TO, 1, 4, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light2[] = { CMD_OFF, 60, CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60,
CMD_OFF, 200, CMD_MOVE_TO, 1, 1, CMD_MOVE_TO, 450, 1, CMD_ON, 400,
CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60, CMD_ON, 60,
CMD_MOVE_TO, 450, 4, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light3[] = { CMD_ON, 60, CMD_ON, 60, CMD_OFF, 60, CMD_ON, 60,
CMD_ON, 200, CMD_MOVE_TO, 450, 1, CMD_MOVE_TO, 1, 1, CMD_ON, 400,
CMD_ON, 60, CMD_OFF, 60, CMD_ON, 60, CMD_OFF, 60,
CMD_MOVE_TO, 1, 4, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light4[] = { CMD_OFF, 60, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light5[] = { CMD_OFF, 60, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light6[] = { CMD_OFF, 60, CMD_SYNC, CMD_RETURN_TO_START};
const uint16_t script_light7[] = { CMD_OFF, 60, CMD_SYNC, CMD_RETURN_TO_START};
uint8_t current_light;
uint16_t timer_int_counter;
lights light[8];
int main( void)
{
SystemInit();
current_light = 0;
light[0].current_dim_value = 1;
light[0].irq_int_counter = 0;
light[0].script = (uint16_t *)script_light0;
light[1].current_dim_value = 1;
light[1].irq_int_counter = 0;
light[1].script = (uint16_t *)script_light1;
light[2].current_dim_value = 1;
light[2].irq_int_counter = 0;
light[2].script = (uint16_t *)script_light2;
light[3].current_dim_value = 1;
light[3].irq_int_counter = 0;
light[3].script = (uint16_t *)script_light3;
light[4].current_dim_value = 1;
light[4].irq_int_counter = 0;
light[4].script = (uint16_t *)script_light4;
light[5].current_dim_value = 1;
light[5].irq_int_counter = 0;
light[5].script = (uint16_t *)script_light5;
light[6].current_dim_value = 1;
light[6].irq_int_counter = 0;
light[6].script = (uint16_t *)script_light6;
light[7].current_dim_value = 1;
light[7].irq_int_counter = 0;
light[7].script = (uint16_t *)script_light7;
//GPIO setup
//assign input for zero crossing
LPC_GPIO0->DIR &= ~(ZERO_CROSS);
LPC_IOCON->PIO0_6 |= (1<<5); //turn on hysteresis
//assign outputs
LPC_IOCON->JTAG_TMS_PIO1_0 &= ~0x07;
LPC_IOCON->JTAG_TMS_PIO1_0 |= 0x01; //change P1_0 to GPIO
LPC_IOCON->JTAG_TDO_PIO1_1 &= ~0x07;
LPC_IOCON->JTAG_TDO_PIO1_1 |= 0x01; //change P1_1 to GPIO
LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x07;
LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x01; //change P1_2 to GPIO
LPC_GPIO1->DIR |= LIGHT0 | LIGHT1 | LIGHT2 | LIGHT3 | LIGHT4 | LIGHT5 | LIGHT6 | LIGHT7;
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); //enable GPIO clock
NVIC_EnableIRQ(EINT0_IRQn);
//timer16 0 setup
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);
LPC_TMR16B0->PR = 0x08; // set prescaler
LPC_TMR16B0->MR0 = 30; //load match register 0
LPC_TMR16B0->MCR = 3; // Interrupt and Reset on MR0
NVIC_EnableIRQ(TIMER_16_0_IRQn);
//timer16 1 setup
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8);
LPC_TMR16B1->PR = 0x01; // set prescaler
LPC_TMR16B1->MR0 = 2000; //load match register 0
LPC_TMR16B1->MCR = 3; // Interrupt and Reset on MR0
NVIC_EnableIRQ(TIMER_16_1_IRQn);
LPC_GPIO0->IS &= ~(ZERO_CROSS); //interrupt sense - 0 = edge sensitive
LPC_GPIO0->IBE &= ~(ZERO_CROSS); //interrupt both edges - 0 = edge controlled by IEV
LPC_GPIO0->IEV &= ~(ZERO_CROSS); //interrupt event reg - 0 = rising edge interrupt
LPC_GPIO0->IE |= (ZERO_CROSS); //interrupt enable
while( 1 );
}
void PIOINT0_IRQHandler(void)
{
uint32_t regVal;
timer_int_counter = 0;
regVal = LPC_GPIO0->MIS & (ZERO_CROSS); //get interrupt status
if ( regVal )
{
current_light = 0;
while( current_light < 8)
{
light[current_light].irq_int_counter++;
switch( *(light[current_light].script))
{
case CMD_DELAY:
if( light[current_light].irq_int_counter > *(light[current_light].script + 1))
{
light[current_light].script += 2;
light[current_light].irq_int_counter = 0;
}
break;
case CMD_ON:
light[current_light].current_dim_value = 1;
if( light[current_light].irq_int_counter > *(light[current_light].script + 1))
{
light[current_light].script += 2;
light[current_light].irq_int_counter = 0;
}
break;
case CMD_OFF:
light[current_light].current_dim_value = 450;
if( light[current_light].irq_int_counter > *(light[current_light].script + 1))
{
light[current_light].script += 2;
light[current_light].irq_int_counter = 0;
}
break;
case CMD_MOVE_TO:
if( light[current_light].current_dim_value < (*(light[current_light].script + 1) - (*(light[current_light].script + 2) + 1)))
{
light[current_light].current_dim_value += *(light[current_light].script + 2);
}
else
{
if( light[current_light].current_dim_value > (*(light[current_light].script + 1) + (*(light[current_light].script + 2) - 1)))
{
light[current_light].current_dim_value -= *(light[current_light].script + 2);
}
else
{
light[current_light].current_dim_value = *(light[current_light].script + 1);
light[current_light].script += 3;
light[current_light].irq_int_counter = 0;
}
}
break;
case CMD_SYNC:
if ( *light[0].script == CMD_SYNC &&
*light[1].script == CMD_SYNC &&
*light[2].script == CMD_SYNC &&
*light[3].script == CMD_SYNC &&
*light[4].script == CMD_SYNC &&
*light[5].script == CMD_SYNC &&
*light[6].script == CMD_SYNC &&
*light[7].script == CMD_SYNC) //If every light has hit a SYNC event
{
light[0].script++; //let all lights continue processing
light[1].script++;
light[2].script++;
light[3].script++;
light[4].script++;
light[5].script++;
light[6].script++;
light[7].script++;
}
break;
case CMD_RETURN_TO_START:
switch( current_light)
{
case 0:
light[0].script = (uint16_t *)script_light0;
break;
case 1:
light[1].script = (uint16_t *)script_light1;
break;
case 2:
light[2].script = (uint16_t *)script_light2;
break;
case 3:
light[3].script = (uint16_t *)script_light3;
break;
case 4:
light[4].script = (uint16_t *)script_light4;
break;
case 5:
light[5].script = (uint16_t *)script_light5;
break;
case 6:
light[6].script = (uint16_t *)script_light6;
break;
case 7:
light[7].script = (uint16_t *)script_light7;
break;
}
break;
}
light[current_light].on_point = 160 + light[current_light].current_dim_value;
current_light++;
}
LPC_TMR16B0->TCR = 1;
LPC_GPIO0->IC |= (ZERO_CROSS); //clear interrupt
}
return;
}
void TIMER16_0_IRQHandler(void)
{
if ( LPC_TMR16B0->IR & 0x1 )
{
timer_int_counter++;
if( timer_int_counter > 700)
LPC_TMR16B0->TCR = 0; //disable timer
current_light = 0;
while( current_light < 8)
{
if( light[current_light].on_point == timer_int_counter) //turn on signal
{
switch( current_light)
{
case 0:
LPC_GPIO1->DATA |= LIGHT0;
break;
case 1:
LPC_GPIO1->DATA |= LIGHT1;
break;
case 2:
LPC_GPIO1->DATA |= LIGHT2;
break;
case 3:
LPC_GPIO1->DATA |= LIGHT3;
break;
case 4:
LPC_GPIO1->DATA |= LIGHT4;
break;
case 5:
LPC_GPIO1->DATA |= LIGHT5;
break;
case 6:
LPC_GPIO1->DATA |= LIGHT6;
break;
case 7:
LPC_GPIO1->DATA |= LIGHT7;
break;
}
}
if( light[current_light].on_point + 3 == timer_int_counter) //turn off signal
{
switch( current_light)
{
case 0:
LPC_GPIO1->DATA &= ~(LIGHT0);
break;
case 1:
LPC_GPIO1->DATA &= ~(LIGHT1);
break;
case 2:
LPC_GPIO1->DATA &= ~(LIGHT2);
break;
case 3:
LPC_GPIO1->DATA &= ~(LIGHT3);
break;
case 4:
LPC_GPIO1->DATA &= ~(LIGHT4);
break;
case 5:
LPC_GPIO1->DATA &= ~(LIGHT5);
break;
case 6:
LPC_GPIO1->DATA &= ~(LIGHT6);
break;
case 7:
LPC_GPIO1->DATA &= ~(LIGHT7);
break;
}
}
current_light++;
}
LPC_TMR16B0->IR = 1; // clear interrupt flag
}
return;
}