SAMD21E17A - TCC and TC integration

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all,

 

I'm fairly new to embedded programming, so please forgive me if some of my understanding is off or doesn't make sense. I will try to clarify.

 

Goal: This project is using the SAMD21E17A, and I want to create 5 PWM signals to drive different brightness levels of (up to) 5 LEDs. The brightness level will be determined by a photo diode. There are 60 LEDs on the board.

 

Step 1) Create 5 PWM signals using TCC ASF (On PA 17, 18, 23, 24, 25 - these are sink pins)

Step 2) Use ADC ASF to read brightness on photo diode (On PA03, AIN[1])

Step 3) Use TC ASF to run a state driver (1000ms, 100ms, 10ms, and 1ms loops) mostly for the LED logic.

Step 4) Integrate everything. Use brightness reading to drive a "set point" for the brightest LED, and a progressive dimming effect for the other four (think of an LED trail all the way to "off").

 

I've followed some online resources and I believe I have (1), (2), and (3) completed independently. When I combine everything is when I have issues, and admittedly my understanding of TC and TCC is poor. For step (1), my code is as follows in a separate .c file:

struct tcc_module tcc_instance;
struct tcc_module tcc_instance1;

static void configure_tcc(void)
{
	struct tcc_config config_tcc;
	struct tcc_config config_tcc1;

	tcc_get_config_defaults(&config_tcc, TCC0);
	config_tcc.counter.period = 0xFFFF;
	config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM;
	config_tcc.compare.match[0] = 0xFFFF;
	config_tcc.compare.match[1] = 0xFFFF;
	config_tcc.compare.match[2] = 0xFFFF;
	config_tcc.compare.match[3] = 0xFFFF;
	
	//COMPARE TO [3]
	config_tcc.pins.enable_wave_out_pin[7] = true;
	config_tcc.pins.wave_out_pin[7]        = PIN_PA17F_TCC0_WO7;
	config_tcc.pins.wave_out_pin_mux[7]    = MUX_PA17F_TCC0_WO7;
	
	//COMPARE TO [2]
	config_tcc.pins.enable_wave_out_pin[2] = true;
	config_tcc.pins.wave_out_pin[2]		   = PIN_PA18F_TCC0_WO2;
	config_tcc.pins.wave_out_pin_mux[2]	   = MUX_PA18F_TCC0_WO2;
	
	//COMPARE TO [1]
	config_tcc.pins.enable_wave_out_pin[5] = true;
	config_tcc.pins.wave_out_pin[5]		   = PIN_PA23F_TCC0_WO5;
	config_tcc.pins.wave_out_pin_mux[5]	   = MUX_PA23F_TCC0_WO5;
	
	tcc_init(&tcc_instance, TCC0, &config_tcc);

	tcc_get_config_defaults(&config_tcc1, TCC1);
	config_tcc.counter.period = 0xFFFF;
	config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM;
	config_tcc.compare.match[0] = 0xFFFF;
	config_tcc.compare.match[1] = 0xFFFF;
	config_tcc.compare.match[2] = 0xFFFF;
	config_tcc.compare.match[3] = 0xFFFF;
	
	//COMPARE TO [1]
	config_tcc.pins.enable_wave_out_pin[3] = true;
	config_tcc.pins.wave_out_pin[3]        = PIN_PA25F_TCC1_WO3;
	config_tcc.pins.wave_out_pin_mux[3]    = MUX_PA25F_TCC1_WO3;
	
	//COMPARE TO [0]
	config_tcc.pins.enable_wave_out_pin[2] = true;
	config_tcc.pins.wave_out_pin[2]        = PIN_PA24F_TCC1_WO2;
	config_tcc.pins.wave_out_pin_mux[2]    = MUX_PA24F_TCC1_WO2;
	
	
	tcc_init(&tcc_instance1, TCC1, &config_tcc1);
	
	tcc_enable(&tcc_instance);
	tcc_enable(&tcc_instance1);
}

void *const tccAddress[] = {&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //0, 1 , 2 , 3 , 4
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //5
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //10
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //15
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //20
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //25
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //30
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //35
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //40
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //45
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance, //50
	&tcc_instance,&tcc_instance,&tcc_instance1,&tcc_instance1, &tcc_instance //55
};

uint8_t waveformAddress[] = {7,2,3,2,5,  //0, 1 , 2 , 3 , 4
	7,5,2,3,2,
	7,2,3,2,5,
	7,5,2,3,2,
	7,2,3,2,5,
	7,5,2,3,2,
	7,2,3,2,5,
	7,5,2,3,2,
	7,2,3,2,5,
	7,5,2,3,2,
	7,2,3,2,5,
	7,5,2,3,2

};

void setPWM(uint8_t ledNumber, uint8_t pwmPercentage)
{
	tcc_set_compare_value((struct tcc_module *const) tccAddress[ledNumber],waveformAddress[ledNumber],(100-pwmPercentage)*0xFFFF/100);

}

for (2):

struct adc_module adc_instance;
uint16_t result;	
int adcOutput;

void adc_complete_callback(void)
{
	//translate adc value into PWM scale for LED's
	turnOffAllLEDS();
	adcOutput = -0.075*result+135;
	switchLED(adcOutput,true); //Turn on LED corresponding to light level in the room (visual validation of LEDs)
}

void configure_adc(void)
{
	struct adc_config config_adc;
	adc_get_config_defaults(&config_adc);	
	config_adc.positive_input  = ADC_POSITIVE_INPUT_PIN1;
	adc_init(&adc_instance, ADC, &config_adc);
	adc_enable(&adc_instance);

	//turns the photodiode on
	ioport_set_pin_dir(PIN_PA02, IOPORT_DIR_OUTPUT);
	ioport_set_pin_level(PIN_PA02, 1);

	adc_register_callback(&adc_instance, adc_complete_callback, ADC_CALLBACK_READ_BUFFER);
	adc_enable_callback(&adc_instance, ADC_CALLBACK_READ_BUFFER);
}

and (3)

 

struct tc_module tc_instance;

void timeSlot_1ms(void);
void timeSlot_10ms(void);
void timeSlot_100ms(void);
void timeSlot_1000ms(void);

void configure_tc(void);
void configure_tc_callbacks(void);
void tc_callback_method(struct tc_module *const module_inst);

void configure_tc(void)
{
	struct tc_config config_tc;
	tc_get_config_defaults(&config_tc);
	config_tc.counter_size    = TC_COUNTER_SIZE_16BIT;
	config_tc.counter_16_bit.compare_capture_channel[0] = 0x1E60;
	tc_init(&tc_instance, TC3, &config_tc);
	tc_enable(&tc_instance);
	tc_register_callback(
	&tc_instance,
	tc_callback_method,
	TC_CALLBACK_CC_CHANNEL0);
	tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0);
}

void tc_callback_method(struct tc_module *const module_inst)
{
	static timeslotCounter = 0;
	
	tc_set_count_value(module_inst, 0x0000);
	timeSlot_1ms();
	if(timeslotCounter % 10 == 0){
		timeSlot_10ms();
	}
	if(timeslotCounter % 100 == 0){
		timeSlot_100ms();
	}
	if(timeslotCounter % 1000 == 0){
		timeSlot_1000ms();
	}
	
	timeslotCounter++;
	if(timeslotCounter == 1000){
		timeslotCounter = 0;
	}
}

 

Now my main.c looks like this:

#include <asf.h>
#include <lib/ledDriver.c>
#include <lib/timer.c>
#include <lib/i2c.c>
#include <lib/pwmDriver.c>
#include <lib/adcDriver.c>


void timeSlot_1ms(void){
	driveLEDs();
}

void timeSlot_10ms(void){
	
}

void timeSlot_100ms(void){
	
}

void timeSlot_1000ms(void){
	
}


int main (void)
{
	system_init();

	configure_tc();
	configure_tcc();
	configure_adc();

	system_interrupt_enable_global();
        setLEDPinsAsOutputs();	
	
        TurnOnLED(2);
	setPWM(2,99);

	while(1){

	}

}

So what happens when I run this code? The sink pin for the "2" LED is set correctly, but all other LEDs with the same sink pin are turned on, and a flickering effect is also seen. I can confirm that the ADC read is going through as I am able to read different ADC values. Any suggestions at where to go next or if there are clarifying questions, just let me know.

 

Appreciate any insight!