ATtiny402-5pins-pwm-TCA-TCB

This was just my way of teaching myself PWM with as many pins as I could with ATtiny 0-Series 

Wrote an analogWrite function, it works great..


/* * ATtiny402-5pin-pwm-analog-out.c * * Works Great.. * * Created: 4/25/2023 16:34:19 * Author : Sherman Stebbins */ 
#include <avr/io.h>
void TCB0_init (void);void TCA0_init(void);void analogWrite(uint8_t pin, uint8_t phase);
int main(void){ CCP = 0xD8; CLKCTRL.MCLKCTRLB = 0b00000001; //clock at full speed /* Wait for system oscillator changing to finish */ while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm){;} PORTA.DIR = 0b11111111; TCB0_init(); TCA0_init(); uint16_t count = 0; uint8_t phase = 0; uint8_t light = 0; static volatile uint8_t direction = 1; while (1) { for(uint16_t i=0;i<50000;i++){ if(++count > 2000){ count=0; if(direction){ phase++; if(phase>=254){ direction = 0; } } else{ if(phase == 0 ){ direction = 1; light++; if(light>4){light=0;} } phase--; } switch (light){ case 0: analogWrite(6,phase); //Changes PA6 break; case 1: analogWrite(3,phase); //Changes PA3 break; case 2: analogWrite(1,phase); //changes PA1 break; case 3: analogWrite(2,phase); //changes PA2 break; case 4: analogWrite(7,phase); //changes PA7 break; }
} } }}
void TCA0_init(void){ /* set waveform output on PORT A */// PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTA_gc; //TOTAL FAILURE FROM EXAMPLE PORTMUX.CTRLC = PORTMUX_TCA00_ALTERNATE_gc; // Move it to PA7 TOTALLY WOKED AND MOVED TO PA7 //added 4/20/23 WORKED AND ADDED 5TH CHANNEL /* enable split mode */ TCA0.SPLIT.CTRLD = TCA_SPLIT_SPLITM_bm; TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP0EN_bm /* enable compare channel 0 for the higher byte */ |TCA_SPLIT_LCMP0EN_bm | TCA_SPLIT_HCMP1EN_bm | TCA_SPLIT_LCMP1EN_bm  | TCA_SPLIT_LCMP2EN_bm | TCA_SPLIT_HCMP2EN_bm; /* TCA_SPLIT_LCMP0EN_bm;  enable compare channel 0 for the lower byte  "This is the mystry trying to get to a port. */ /* set the PWM frequencies and duty cycles */ // PA1 Low still not working to a port (UPDATE: WORKS GREAT NOW!!) TCA0.SPLIT.LPER = 0xFF; //PERIOD_EXAMPLE_VALUE_L //changes frequency
// (PA3): TCA0.SPLIT.HPER = 0xFF;//PERIOD_EXAMPLE_VALUE_H; TCA0.SPLIT.HCMP1 = 0xFF; // DUTY_CYCLE_EXAMPLE_VALUE_H; TCA0.SPLIT.HCMP2 = 0xFF; // DUTY_CYCLE_EXAMPLE_VALUE_H; TCA0.SPLIT.CTRLA = TCA_SPLIT_CLKSEL_DIV2_gc /* set clock source (sys_clk/16) */ | TCA_SPLIT_ENABLE_bm; /* start timer */}
//Pin PA6:void TCB0_init (void){ /* Load CCMP register with the period and duty cycle of the PWM */ TCB0.CCMP = 0x03AF; //first two digits adjust phase, second two fine tune frequency

/* Enable TCB0 and Divide CLK_PER by 2 */ TCB0.CTRLA |= TCB_ENABLE_bm; TCB0.CTRLA |= TCB_CLKSEL_CLKDIV2_gc; /* Enable Pin Output and configure TCB in 8-bit PWM mode */ TCB0.CTRLB |= TCB_CCMPEN_bm; TCB0.CTRLB |= TCB_CNTMODE_PWM8_gc;}
void analogWrite(uint8_t pin, uint8_t phase){ switch (pin){ case 6: TCB0.CCMPH = phase; //Changes PA6 //if (phase=0) break; case 3: TCA0.SPLIT.HCMP0 = phase; //Changes PA3 break; case 1: TCA0.SPLIT.LCMP1 = phase; //changes PA1 break; case 2: TCA0.SPLIT.LCMP2 = phase; //changes PA2 break; case 7: TCA0.SPLIT.LCMP0 = phase; //changes PA7 break; }}