Monday, January 23, 2006

Two timers and a fade

The following code demonstrates the difference between the two timers on HCS08 and their respective channels. LED1 is on Timer1 Channel1 and LED3 is on Timer2 Channel0. Their interrupt functions are identical, but their behavior is different due to their respective timers and duties. Pressing SWITCH1 will increase pulseMod and thus decrease the blink rate, whereas pressing SWITCH2 will decrease pulseMod and increase the blink rate. Lastly, LED5 is a good example of exercising the duty cycle. It's duty is being decremented/incremented through the main loop and will thus decrease/increase the duty (time of period) that the led is on.
---------------------
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "M68DEMO908gb60.h"
#define PRESCALAR 7
//#define MODULUS 32768
//#define MODULUS 16384
//#define MODULUS 8192
//#define MODULUS 4096
#define MODULUS 2048
#define DUTY75 (MODULUS-(MODULUS/4))
#define DUTY25 (MODULUS/4)
#define DUTY50 (MODULUS/2)
long cntr=0;
long cntr2=0;
int goUp = 0;
int goUp2 = 0;
long cntr3 = 0;
long timer2chnl0 = 0;
long pulseMod = 25;
int fadeTime = 4;

void MCU_init(void); /* Device initialization function declaration */

void speedUpOrSlowDown(){
    if(SWITCH3==DOWN){      
       TPM1C0V = TPM1C0V/2;
    } else if(SWITCH4 == DOWN){
      if(TPM1C0V <= (MODULUS/2))
        TPM1C0V = TPM1C0V*2;
    }
}


void  interrupt VTimer1Chnl1 intTimer1Chnl1(){//for every period of zone out on LED5, this intterupt is set 500 times
 
 if(cntr3 %pulseMod ==0 )
   LED1 = ~LED1 ;
 cntr3++;
 TPM1C1SC_CH1F = 0; //reset interrupt
}

void initTimer1Chnl1(){
   /*configure PWM mode and pulse*/
  TPM1C1SC = 1;
  TPM1C1SC_MS1B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
  TPM1C1SC_ELS1A = 1; /*Select low as true*/
  TPM1SC_PS1 = PRESCALAR;/*clock source divided by prescalar*/
  TPM1C1V = DUTY50;

  TPM1C1SC_CH1IE = 1;//turn on interrupt
}



void initTimer1Chnl0(){//LED5
   /*Initialize timer TPM1 channel, assumes not touched since reset!*/
  TPM1SC_CLKSA = 1;/*Select BUS clock*/
  TPM1SC_CLKSB = 0;

  TPM1SC_PS0 = PRESCALAR;/*clock source divided by prescalar*/
  TPM1MOD = MODULUS;/*counter value, counts up to*/
  TPM1SC_CPWMS = 1;
  /*configure PWM mode and pulse*/
  TPM1C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
  TPM1C0SC_ELS0A = 1; /*Select low as true*/
  //TPM1C0V = DUTY75;/*select final divider (duty cycle)*/
  TPM1C0V = 16;/*select final divider (duty cycle)*/
 
}


void interrupt VTimer2Chnl0 intTimer2Chnl0(){
 if(timer2chnl0 % pulseMod ==0)
  LED3 = ~LED3;
 
 timer2chnl0++;
 TPM2C0SC_CH0F = 0;
}

void initTimer2Chnl0(){
  TPM2C0SC_CH0IE = 1;  //enable channel
   
  TPM2SC_CLKSA = 1;/*Select BUS clock*/
  TPM2SC_CLKSB = 0;

  TPM2SC_PS = PRESCALAR;/*clock source divided by prescalar*/
  TPM2MOD = 8192;/*counter value, counts up to*/
  TPM2SC_CPWMS = 1;
  /*configure PWM mode and pulse*/
  TPM2C0SC_MS0B = 1; /*MS0B=1, MS0A=0; << Edge align PWM*/
  TPM2C0SC_ELS0A = 1; /*Select low as true*/
  TPM2C0V = TPM2MOD/2;/*select final divider (duty cycle)*/
 
}

void initICG(){
  /*configure Internal Clock Generator [ICG]*/
  /*MFD[]={4,6,8,10,12,14,16,18}*/
  ICGC2_MFD = 7; /*32KHz crystal, demo board.
  For 4MHz crystal (eval board):
  ICGC2_MFD = 3
  */
  ICGC2_RFD = 0; /* RFD[]={1,2,4,8,16,32,64,128}*/
  //ICGC1 = 0b00110000;
  ICGC1 = 0b00111000;
  /*32KHz crystal, demo board.
  For 4MHz crystal (eval board):
  ICGC1 = 0b01111000;
  */
  while((ICGS1_LOCK==0)||(ICGS1_ERCS==0)){
  /*Ensure COP doesn't reset device whilst waiting for clock lock*/
  __RESET_WATCHDOG(); /* kicks the dog */
  }
  ICGC2_LOCRE = 1; /*enable reset if clock fails*/
 
}

void initKeyboardInterrupt(){
  KBI1SC_KBIE = 1;  //KBIE =>Keyboard Interrupt Enable
  KBI1PE_KBIPE4 = 1; //Keyboard Interrupt Port Enable 4 (switch1)
  KBI1PE_KBIPE5 = 1; //Keyboard Interrupt Port Enable 5 (switch2)
  KBI1PE_KBIPE6 = 1; //Keyboard Interrupt Port Enable 6 (switch3)
  KBI1PE_KBIPE7 = 1; //Keyboard Interrupt Port Enable 7 (switch4)
}

void interrupt Vkeyboard intSWITCH1(){
 if(SWITCH1 == DOWN){
  pulseMod +=2;
 }
 if(SWITCH2 == DOWN){
  pulseMod -=2;
 }
 KBI1SC_KBACK = 1;//ack
}

void main(void) {

  /* Uncomment this function call after using Device Initialization
     to use the generated code */
  /* MCU_init(); */

  EnableInterrupts; /* enable interrupts */
  PTADD = 0; //initialize as input (Data Direction Register)
  PTAPE = 0xf0; //Pullups on upper 4 bits
  /*initialize bits 0-3 of Port F as outputs (connected to led's)*/
  PTFDD = 0x0f;
  LED1 = OFF;
  LED2 = OFF;
  LED3 = OFF;
  LED4 = OFF;
  LED5 = OFF;
 
  initICG();
 
  initKeyboardInterrupt();
 
  initTimer1Chnl0();//LED5
 
  initTimer1Chnl1();//LED1
 
  initTimer2Chnl0();//LED3

  for(;;) {
    __RESET_WATCHDOG(); /* feeds the dog */
    
      if(goUp==1){
        TPM1C0V = TPM1C0V+fadeTime;
        cntr=0;
        cntr2++;
        if(TPM1C0V >= MODULUS){
          goUp = 0;
        }
      } else{
        //TPM1C0V = TPM1C0V/2;
        TPM1C0V = TPM1C0V-fadeTime;
        cntr2=0;
        cntr++;
        if (TPM1C0V <=0){
          goUp =1;
          TPM1C0V = fadeTime;
        }
      }
     
  } /* loop forever */
  /* please make sure that you never leave this function */
}

No comments: