Main Page | File List | Globals | Related Pages

t2313_softpwm.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00072 #include <ctype.h>
00073 #include "t2313_softpwm.h"
00074 #if defined(__ICCAVR__)
00075   #include <iotiny2313.h>
00076   #include <inavr.h>
00077 #elif __GNUC__ > 0
00078   #include <avr/io.h>
00079   #include <avr/interrupt.h>
00080   #include <avr/signal.h>
00081   #include <avr/wdt.h>
00082 #else
00083 # error "Unsupported compiler."
00084 #endif
00085 
00087 unsigned char compare[CHMAX];
00088 volatile unsigned char compbuff[CHMAX];
00089 
00090 #if DEBUG
00091 volatile unsigned int debugTimer;
00092 #endif
00093 
00097 __C_task main(void)
00098 {
00099   Init();
00100   USART0_Init(11);
00101   for(;;)
00102   {
00103 #if DEBUG
00104     DebugMonitor();
00105 #else
00106     ManualControl();
00107 #endif
00108   }
00109 }
00110 
00113 void ManualControl(void)
00114 {
00115   unsigned char rxdata, channel, temp, error;
00116 
00117     error = 0;                          // clear error flag
00118     while(USART0_Receive() != '#');     // wait for sync character
00119     USART0_Transmit('#');               // echo sync character
00120     channel = USART0_Receive() - 0x30;  // receive channel number
00121     if(channel >= CHMAX) error = 1;     // error if invalid channel
00122     USART0_Transmit(channel + 0x30);    // echo received character
00123 
00124     temp = GetNextChar();         // fetch upper nibble
00125     USART0_Transmit(temp);        // echo received character
00126     if (isxdigit(temp))           // check for a hex character
00127     {
00128       if ( temp > '9') temp -= 7; // subtract offset for A-F
00129       temp -= 0x30;               // subtract ASCII offset
00130     }
00131     else error = 1;               // error if not hex
00132     rxdata = temp << 4;           // store received upper nibble
00133 
00134     temp = GetNextChar();         // fetch lower nibble
00135     USART0_Transmit(temp);        // echo received character
00136     if (isxdigit(temp))           // check for a hex character
00137     {
00138       if ( temp > '9') temp -= 7; // subtract offset for A-F
00139       temp -= 0x30;               // subtract ASCII offset
00140     }
00141     else error = 1;               // error if not hex
00142     rxdata += temp;               // add lower nibble to upper nibble
00143 
00144     if(!error)                    // if data is good
00145     {
00146       compbuff[channel] = rxdata; // update compare buffer
00147 
00148       USART0_Transmit(':');       // send OK message
00149       USART0_Transmit('O');
00150       USART0_Transmit('K');
00151       USART0_Transmit('\r');
00152       USART0_Transmit('\n');
00153     }
00154     else                          // if data is not good
00155     {
00156       USART0_Transmit(':');       // send ERRor message
00157       USART0_Transmit('E');
00158       USART0_Transmit('R');
00159       USART0_Transmit('R');
00160       USART0_Transmit('\r');
00161       USART0_Transmit('\n');
00162     }
00163 }
00164 
00167 #if DEBUG
00168 void DebugMonitor(void)
00169 {
00170   signed char i;
00171   unsigned int temp;
00172 
00173   temp = debugTimer;              // fetch latest timer value
00174   USART0_Transmit('\r');
00175   USART0_Transmit('0');
00176   USART0_Transmit('x');
00177   // transmit 16 bit timer value as four hex characters
00178   for(i=3;i>=0;i--) USART0_Transmit(HexToASCII(0x0F & (temp >> (4*i))));
00179 
00180 }
00181 #endif
00182 
00184 void Init(void)
00185 {
00186   unsigned char i, pwm;
00187 
00188   CLKPR = (1 << CLKPCE);        // enable clock prescaler update
00189   CLKPR = 0;                    // set clock to maximum (= crystal)
00190 
00191   __watchdog_reset();           // reset watchdog timer
00192   MCUSR &= ~(1 << WDRF);        // clear the watchdog reset flag
00193   WDTCSR |= (1<<WDCE)|(1<<WDE); // start timed sequence
00194   WDTCSR = 0x00;                // disable watchdog timer
00195 
00196   DDRD = PORTD_MASK;            // set port pins to output
00197   DDRB = PORTB_MASK;            // set port pins to output
00198 
00199 #if DEBUG
00200   DEBUGSET;                     // make debug pin output (header file macro)
00201   pwm = 0;                      // worst-case default PWM level
00202 #else
00203   pwm = PWMDEFAULT;
00204 #endif
00205 
00206   for(i=0 ; i<CHMAX ; i++)      // initialise all channels
00207   {
00208     compare[i] = pwm;           // set default PWM values
00209     compbuff[i] = pwm;          // set default PWM values
00210   }
00211 
00212 #if DEBUG
00213   compare[0] = 0x01;            // make one channel active
00214   compbuff[0] = 0x01;
00215 #endif
00216 
00217   TIFR = (1 << TOV0);           // clear interrupt flag
00218   TIMSK = (1 << TOIE0);         // enable overflow interrupt
00219   TCCR0B = (1 << CS00);         // start timer, no prescale
00220 
00221   __enable_interrupt();         // enable interrupts
00222 }
00223 
00226 #if defined(__ICCAVR__)
00227   #pragma vector=TIMER0_OVF0_vect
00228   __interrupt void ISR_TOV0 (void)
00229 
00230 #elif __GNUC__ > 0
00231   SIGNAL (SIG_TIMER0_OVF)
00232 #endif
00233 {
00234   static unsigned char pinlevelB=PORTB_MASK, pinlevelD=PORTD_MASK;
00235   static unsigned char softcount=0xFF;
00236 
00237   PORTB = pinlevelB;            // update outputs
00238   PORTD = pinlevelD;            // update outputs
00239 
00240 #if DEBUG
00241   DEBUGPIN_ON;                  // set debug pin
00242   TCNT1 = 0;                    // clear timer
00243   TCCR1B = (1 << CS10);         // start timer
00244 #endif
00245 
00246   if(++softcount == 0){         // increment modulo 256 counter and update
00247                                 // the compare values only when counter = 0.
00248     compare[0] = compbuff[0];   // verbose code for speed
00249     compare[1] = compbuff[1];
00250     compare[2] = compbuff[2];
00251     compare[3] = compbuff[3];
00252     compare[4] = compbuff[4];
00253     compare[5] = compbuff[5];
00254     compare[6] = compbuff[6];
00255     compare[7] = compbuff[7];
00256     compare[8] = compbuff[8];
00257     compare[9] = compbuff[9];   // last element should equal CHMAX - 1
00258 
00259     pinlevelB = PORTB_MASK;     // set all port pins high
00260     pinlevelD = PORTD_MASK;     // set all port pins high
00261   }
00262   // clear port pin on compare match (executed on next interrupt)
00263   if(compare[0] == softcount) CH0_CLEAR;
00264   if(compare[1] == softcount) CH1_CLEAR;
00265   if(compare[2] == softcount) CH2_CLEAR;
00266   if(compare[3] == softcount) CH3_CLEAR;
00267   if(compare[4] == softcount) CH4_CLEAR;
00268 
00269   if(compare[5] == softcount) CH5_CLEAR;
00270   if(compare[6] == softcount) CH6_CLEAR;
00271   if(compare[7] == softcount) CH7_CLEAR;
00272   if(compare[8] == softcount) CH8_CLEAR;
00273   if(compare[9] == softcount) CH9_CLEAR;
00274 
00275 #if DEBUG
00276   DEBUGPIN_OFF;                 // clear debug pin
00277   TCCR1B = 0;                   // stop timer
00278   if(!softcount) debygTimer = TCNT1;  // store value for softcount=0 ISR
00279 #endif
00280 }
00281 
00284 void USART0_Init( unsigned int baudrate )
00285 {
00286   // Set the baud rate
00287   UBRRH = (unsigned char) (baudrate>>8);
00288   UBRRL = (unsigned char) baudrate;
00289         
00290   // Enable UART receiver and transmitter
00291   UCSRB = ((1 << RXEN) | (1 << TXEN));
00292         
00293   // Set frame format: 8 data, 1 stop
00294   UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
00295 }
00296 
00299 unsigned char USART0_Receive( void )
00300 {
00301   while ( !(UCSRA & (1<<RXC)) );  // Wait for incoming data
00302   return UDR;                     // Return the data
00303 }
00304 
00307 void USART0_Transmit( unsigned char data )
00308 {
00309   while ( !(UCSRA & (1<<UDRE)) ); // Wait for empty transmit buffer
00310   UDR = data;                     // Start transmittion
00311 }
00312 
00315 unsigned char HexToASCII (unsigned char ch)
00316 {
00317   ch += 0x30;             // add offset to ASCII '0'
00318   if (ch > '9') ch += 7;  // if alphabetic add offset to ASCII 'A'
00319   return ch;
00320 }
00321 
00324 unsigned char GetNextChar(void)
00325 {
00326   char tmp;
00327 
00328   tmp = USART0_Receive(); // get next character
00329   tmp = toupper(tmp);     // force to upper case
00330   return(tmp);
00331 }
00332 

Generated on Tue Dec 20 15:11:31 2005 for AVR136: Low-Jitter Multi-Channel Software PWM by  doxygen 1.4.4