The code I've attached below is an attempt at producing two inverted SPWM signals using an RC compare interrupt on Timer Counter Channel 0 (TC0). TC0 is configured to count up at a rate of 4.2MHz, and restart back to 0 once RC is reached (WAVSEL = 2), RC was set to 2100 as to provide SPWM signals with a frequency of 20kHz, and RA and RB were set equal to one another, but with different compare effects (i.e. ACPA = 1, BCPB = 2, etc.) so that TIOA0 and TIOB0 would be inverted from one another. Whenever TC0 reaches RC and an interrupt is fired, the RA and RB registers are updated as to provide a sinusoidally varying duty cycle. The final goal of this code is to be used with a variable frequency drive, which is where values such as "ma" originate.
From what I've found from testing, everything works, except that pins 2 and 13, which should be outputting TIOA0 and TIOB0, are not outputting anything. This was confirmed using an oscilloscope. So it would seem to me that either I have not set up the PIO controller properly, or I'm not writing to the RA and RB registers properly, or maybe what I'm trying to do isn't even possible. Any insight would be greatly appreciated.
//PIO INITIALIZATION
#define PIO_WPEN 0
#define PIO_TIOA0 25
#define PIO_TIOB0 27
//PMC INITIALIZATION
#define PMC_WPEN 0
#define PMC_TC0 27
//HANDLER INITIALIZATION
volatile int const fc = 20000;
volatile float const VFR = 0.01664;
float const pi = 3.141593;
volatile float ma;
volatile int fm;
volatile float mf;
volatile int i = 0;
volatile int x;
volatile int sine[361];
//TIMER INITIALIZATION
#define TC0_WPEN 0
#define TC0_TCCLKS 0
#define TC0_WAVSEL 13
#define TC0_WAVE 15
#define TC0_ACPA 16
#define TC0_ACPC 18
#define TC0_BCPB 24
#define TC0_BCPC 26
#define TC0_CPCS 4
#define TC0_CLKEN 0
#define TC0_CLKDIS 1
#define TC0_SWTRG 2
unsigned volatile int Ra,Rb = 0;
unsigned volatile int const Rc = 2100;
void setup() {
noInterrupts();
//PIO SETUP
REG_PIOB_WPMR = (1 << PIO_WPEN);
REG_PIOB_PDR = (1 << PIO_TIOA0) | (1 << PIO_TIOB0);
pinMode(13,OUTPUT);
pinMode(2,OUTPUT);
//PMC SETUP
REG_PMC_WPMR = (1 << PMC_WPEN);
REG_PMC_PCER0 = (1 << PMC_TC0);
//NVIC SETUP
NVIC_EnableIRQ(TC0_IRQn);
//HANDLER SETUP
fm = map(analogRead(A0),0,1023,30,60);
mf = fc/fm;
ma = VFR*fm;
for (int j = 0; j <= 360; j++) {
sine[j] = 1050*(sin(j*pi/180)+1);
}
//TIMER SETUP
REG_TC0_WPMR = (1 << TC0_WPEN);
REG_TC0_CMR0 = (1 << TC0_BCPC) | (2 << TC0_BCPB) | (2 << TC0_ACPC) |
(1 << TC0_ACPA) | (1 << TC0_WAVE) | (2 << TC0_WAVSEL) |
(0 << TC0_TCCLKS);
REG_TC0_RA0 = Ra;
REG_TC0_RB0 = Rb;
REG_TC0_RC0 = Rc;
REG_TC0_IER0 = (1 << TC0_CPCS);
REG_TC0_IDR0 = (0 << TC0_CPCS);
REG_TC0_CCR0 = (1 << TC0_SWTRG) | (0 << TC0_CLKDIS) | (1 << TC0_CLKEN);
interrupts();
}
void loop() {
}
void TC0_Handler() {
TC_GetStatus(TC0,0);
i++;
fm = map(analogRead(A0),0,1023,30,60);
x = 360*(i/mf);
i++;
if (i == mf) {
i = 0;
mf = fc/fm;
ma = VFR*fm;
}
REG_TC0_RA0 = REG_TC0_RB0 = ma*sine[x];
}