Skip to main content
Topic: Firmware source code (Read 2730 times) previous topic - next topic

Firmware source code

Hi guys

Does anyone know where can I find the USB color changer firmware source code?
At DIYLife it just comes with the hex file, and I would like to compile the source myself.

Thanks in advance

Thiago

Re: Firmware source code

Reply #1
Thanks for asking here. I couldn't find a version that didn't include the Microchip USB stack source, which we can't distribute (you have to get it yourself from the Microchip website).

Here is the fader code from user.c though:

Code: [Select]
//variables for the color fader
unsigned short fade_increment;
unsigned char i;
unsigned char current_color[3];
unsigned char color_track[3];
unsigned char ackCommand=0;
//these arrays are a color pallet used by the auto fader. each set of 3 define a color (RGB).
//The auto fader simply counts to value in the pallet, then it starts counting to the next value.
char COLOR_PAL[21] ={255,0,0,255,128,0,255,255,0,0,255,0,0,255,255,0,0,255,255,0,255};
char COLOR_LU[32] = {0,0,0,0,255,0,0,85,255,128,0,127,255,255,0,170,0,255,0,85,0,255,255,170,0,0,255,85,255,0,255,170};

//this structure holds all the variables used in the software pulse width modulator
struct
{
//put new PWM values in these variables and set UPDATE=1;
//the new values will be moved into the R/G/B registers on the next interrupt
//this prevents a nasty blinking glitch if an interrupt occurs in the middle of an update.
   unsigned char R;
   unsigned char G;
   unsigned char B;
unsigned char UPDATE;
//these are the actual value registers for the soft PWM. 
//values are moved from R,G,B in the interrupt routine if the change flag is set
unsigned char Rreg;
unsigned char Greg;
unsigned char Breg;
unsigned char port;
//keeps track of the current tick of the PWM
//this value increments to 255 (8 bits) and then rolls back to 0.
unsigned char tick;
} SoftPWM; //SoftPWM is the name of our structure, access its elements like so: SoftPWM.R=0; //sets red to 0%

//ASCII values come in from the computer on USB, we need to convert them to values we can use.
unsigned char AtoITempArrayCounter=0; //counts the number of characters in received
unsigned char AtoITempArray[3]; //holds the ASCII values for decoding
unsigned char SoftPWMRegCounter=0; //tracks R/G/B values as they are received
unsigned char SoftPWMReg[3]; //holds the decoded values until a full command is received.

void InterruptHandlerHigh (void);
void ProcessUSBRGB(void);
void TickFade(void);

#pragma code
void UserInit(void)
{

//set initial auto fader color to black
current_color[0]=0;
current_color[1]=0;
current_color[2]=0;
//disable some default nonsense
ADCON1=0b00001111; //ADC pins to digital
CVRCON=0b00000000;
TRISA=0;
TRISB=0;
TRISC=0;

//our LEDS are connected on PORTC, Pins 0,1, and 2.
//0 - power/auto fade mode
//1 - USB status
//2 - serial RX activity

//this function configures the USB status LED
//it is a part of the Microchip USB driver
//we configure it for PORTC pin 1 in io_cfg.h
   //mInitAllLEDs(); //replaced below

//now we configure our custom status LEDs
LATCbits.LATC0=1;//power LED on
LATCbits.LATC1=0;//USB LED off
LATCbits.LATC2=0;//Serial RX LED off
TRISCbits.TRISC0=0; //direction to output
TRISCbits.TRISC1=0;
TRISCbits.TRISC2=0;

//RGB LED outputs are on PORTB, pins 0,1,2
LATBbits.LATB3=0; //all RGB outputs off by default
LATBbits.LATB4=0;
LATBbits.LATB5=0;
TRISBbits.TRISB3=0; //direction to output
TRISBbits.TRISB4=0;
TRISBbits.TRISB5=0;

//zero the data structure that holds the PWM counts
SoftPWM.R=0;
SoftPWM.B=0;
SoftPWM.G=0;
SoftPWM.Rreg=0;
SoftPWM.Breg=0;
SoftPWM.Greg=0;
SoftPWM.tick=0;
SoftPWM.port=0;
SoftPWM.UPDATE=0;


//setup the timer that will be used for PWM
    INTCON2 = 0x84;             //TMR0 high priority
TMR0H=0; //put high byte first, it will be updated on a write to the low byte (see datasheet pg 126)
TMR0L=0; //put low byte, this updates both bytes at once.
T0CON=0b11000000; //setup Timer 1 - Enabled/16bit/internal clock/rising edge/prescaler/1:2 prescaler.
INTCON=0b11100000; //global/peripheral/tmr0ie/_/_/TMR0IF/_/_
INTCONbits.GIEH = 1;        //enable interrupts

}//end UserInit


void ProcessIO(void)
{
    BlinkUSBStatus();
    // User Application USB tasks
    if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1))
{ //there is NO USB connection
TickFade(); //advance color auto fader
}
else
{//there IS a USB connection, check for USB data in the buffer
    ProcessUSBRGB();
}

}//end ProcessIO

/******************************************************************************
 * Function:        void ProcessUSBRGB(void)
 *
 *
 * Note:            This function checks for data in the USB buffer.
 * Bytes are processed as they come in.
 * Valid values are moved to the SoftPWM registers and the ackCommand flag is set
 * acknowledgement is handled the next time the function is called.
 *
 *****************************************************************************/
void ProcessUSBRGB(void)
{
unsigned char cnt; //a byte sized counter
unsigned char input_buffer_length;

if(ackCommand==1){//we need to acknowledge a command
if(mUSBUSARTIsTxTrfReady()){
output_buffer[0]=0x30; //ascii code for 0
output_buffer[1]=0x0d; //ascii code for 0
output_buffer[2]=0x0a; //ascii code for 0
output_buffer[3]=0; //Null terminate buf
putsUSBUSART(output_buffer); //send to USB
ackCommand=0; //clear the respond flag
}//end if
    }//end if


if(getsUSBUSART(input_buffer, 64)){//there is data in the USB buffer
input_buffer_length=mCDCGetRxLength();//how many bytes?

for(cnt=0;cnt<input_buffer_length;cnt++)//process each byte in this for loop
{
byte temp, tempcount;

switch(input_buffer[cnt]) //this switch decodes the meaning of each byte
{
case 0x20://space and break signal the end of a ASCII number, we decode on these characters
case 0x0d: //next line is break, convert array to decimal here, then break on 0x0a...
//multiply each value by 10*place to convert from array to decimal, get final byte value
temp=0;
for(tempcount=0; tempcount<AtoITempArrayCounter; tempcount++){//loop through values, multiply by ten each time
temp*=10;
temp+=AtoITempArray[tempcount];
}
SoftPWMReg[SoftPWMRegCounter]=temp; //update the temporary array with the new value
AtoITempArrayCounter=0; //zero the ASCII byte receive counter
SoftPWMRegCounter++; //increment the digit to be received
if(SoftPWMRegCounter>2) //more than 3 bytes is an error because our max ASCII value is 2-5-5
{
SoftPWMRegCounter=0; //reset everything
AtoITempArrayCounter=0; //start at beginning
}
break;
case 0x0a: //signals the end of the command
SoftPWMRegCounter=0; //reset the digit counter
ackCommand=1; //set the flag to acknowledge the command with a 0
SoftPWM.R=SoftPWMReg[0]; //put the new values in the color registers
SoftPWM.G=SoftPWMReg[1];
SoftPWM.B=SoftPWMReg[2];
SoftPWM.UPDATE=1; //set the register update flag to move the new values into the PWM register.
break;
default: //for all other values
if(0x2f<input_buffer[cnt] && input_buffer[cnt]<0x3a)
{ //a valid ascii numerical value 0-9 (0x30-0x39)
//subtract 0x30 (48) from each ASCII digit to get decimal value (set bits 5,4 to 0...)
AtoITempArray[AtoITempArrayCounter]=(input_buffer[cnt]&~0x30);
AtoITempArrayCounter++;
//more than 3 digit number is an error (max value=255 or 0x32-0x35-0x35)
if(AtoITempArrayCounter>3)
{//error, reset everyuthing
SoftPWMRegCounter=0;
AtoITempArrayCounter=0;
}
}else{ //invalid character
//error, reset everything
SoftPWMRegCounter=0;
AtoITempArrayCounter=0;
}
break;

}//switch

}//for

}//if

}

/******************************************************************************
 * Function:        void TickFade(void)
 *
 *
 * Note:            This function was ported from the si-light project at http://si-light.sourceforge.net
 *     This is a very plain color auto fader that counts between color values contained in an array.
 *
 *
 *****************************************************************************/
void TickFade(void)
{
   static word fade_count=0;
   static byte dest_color=0;
   byte tem_color=0;

   //this counter is a delay
   if(fade_count == 0)fade_count = 10000U;
   fade_count--;

//increment the color fade once per 10000U cycles
if(fade_count==0)
{   
//(de)increment each value if it has not reached the destination color
  for(i=0;i<3;i++){
tem_color=((3*dest_color)+i);
         if (current_color[i]==COLOR_PAL[tem_color])
{
color_track[i]=1; //we have reached the destination value for this color, set the flag
}else{
            if(current_color[i]<COLOR_PAL[tem_color])
{
               current_color[i]=current_color[i]+1;
            }else{
               current_color[i]=current_color[i]-1;
            }
         }
      }//for loop

//check if all colors have reached the desination values
   tem_color=color_track[0]+color_track[1]+color_track[2];

//if all have reached the final color,
//set destination color to next value in the pallet
   if(tem_color==3)
{
        for(i=0;i<3;i++)color_track[i]=0;
            if(dest_color<6)
{
             dest_color = dest_color+1;
            }else{
               dest_color=0;
            }
      }//color shift

//put the color values in the PWM
SoftPWM.R=current_color[0];
SoftPWM.G=current_color[1];
SoftPWM.B=current_color[2];
SoftPWM.UPDATE=1; //set the update flag to move the new values into the PWM register
    }//   'color fade
}

And the interrrupt:

Code: [Select]
#pragma code
#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh ()
{
  if (INTCONbits.TMR0IF)      //check for TMR0 overflow
    {                
      INTCONbits.TMR0IF = 0;            //clear interrupt flag

  if(SoftPWM.tick==0x00){
SoftPWM.port=0b00111000; //if it is going to overflow, set port to 0x00
//this fixes the flashes caused when the PWM gets reset half way through a register update.
//it goes in the reset check so it isnt done each time, and because we dont want values to change half way thorugh a period.
if(SoftPWM.UPDATE==1){
SoftPWM.Rreg=SoftPWM.R;
SoftPWM.Greg=SoftPWM.G;
SoftPWM.Breg=SoftPWM.B;
SoftPWM.UPDATE=0;
}
  }
  if(SoftPWM.tick==SoftPWM.Rreg)SoftPWM.port&=~0b00001000; //set red bit off
  if(SoftPWM.tick==SoftPWM.Greg)SoftPWM.port&=~0b00010000; //set green bit off
  if(SoftPWM.tick==SoftPWM.Breg)SoftPWM.port&=~0b00100000; //set blue bit off
      LATB=SoftPWM.port; //put values on the port
  SoftPWM.tick++;
}
}
Got a question? Please ask in the forum for the fastest answers.

Re: Firmware source code

Reply #2
Thanks a lot Ian

Best  regards