main.c 6.93 KB
Newer Older
Jake Read's avatar
Jake Read committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*
* atkrouter.c
*
* Created: 6/17/2018 2:48:08 PM
* Author : Jake
*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include "hardware.h"
#include "fastmath.h"

// first setup all the pins
// want six step commutation, or sinpwm on encoder reading? 

void clock_init(void){
	OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_256CLK_gc | OSC_FRQRANGE_12TO16_gc; // select external source
	OSC.CTRL = OSC_XOSCEN_bm; // enable external source
	while(!(OSC.STATUS & OSC_XOSCRDY_bm)); // wait for external
	OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | OSC_PLLFAC0_bm | OSC_PLLFAC1_bm; // select external osc for pll, do pll = source * 3
	//OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | OSC_PLLFAC1_bm; // pll = source * 2 for 32MHz std clock
	OSC.CTRL |= OSC_PLLEN_bm; // enable PLL
	while (!(OSC.STATUS & OSC_PLLRDY_bm)); // wait for PLL to be ready
	CCP = CCP_IOREG_gc; // enable protected register change
	CLK.CTRL = CLK_SCLKSEL_PLL_gc; // switch to PLL for main clock
}

void uarts_init(void){
	// UP0
	rb_init(&up0rbrx);
	rb_init(&up0rbtx);
	pin_init(&up0rxled, &PORTE, PIN4_bm, 4, 1);
	pin_init(&up0txled, &PORTE, PIN5_bm, 5, 1);
	uart_init(&up0, &USARTE1, &PORTE, PIN6_bm, PIN7_bm, &up0rbrx, &up0rbtx, &up0rxled, &up0txled);
	//PORTE.PIN7CTRL = PORT_SRLEN_bm;
	uart_start(&up0, SYSTEM_BAUDA, SYSTEM_BAUDB);
	
	ups[0] = &up0;
}

void atkps_init(void){
	atkport_init(&atkp0, 0, &up0);
}

void encoder_init(void){
	pin_init(&spiEncCsPin, &PORTD, PIN4_bm, 4, 1);
	spi_init(&spiEncoder, &USARTD1, &PORTD, PIN6_bm, PIN7_bm, PIN5_bm, &spiEncCsPin);
	spi_start(&spiEncoder, 0);
}

Jake Read's avatar
Jake Read committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){
	// check overrun
	(peru > 1024) ? peru = 1024 : (0);
	(perv > 1024) ? perv = 1024 : (0);
	(perw > 1024) ? perw = 1024 : (0);
	// hi is lo, per xmega, let's undo this
	peru = 1024 - peru;
	perv = 1024 - perv;
	perw = 1024 - perw;
	// A: 3, B: 2, C: 1 - channels to board
	TCC0.CCABUFL = (uint8_t) perw;
	TCC0.CCABUFH = (uint8_t) (perw >> 8);
	TCC0.CCBBUFL = (uint8_t) perv;
	TCC0.CCBBUFH = (uint8_t) (perv >> 8);
	TCC0.CCCBUFL = (uint8_t) peru;
	TCC0.CCCBUFH = (uint8_t) (peru >> 8);
Jake Read's avatar
Jake Read committed
67 68
}

69 70 71 72 73 74 75 76 77
void pwm_by_offset(int16_t ofu, int16_t ofv, int16_t ofw){
	// +ve offset to spend more time with hi-side off, signals are complimentary
	uint16_t peru = 512 + ofu;
	uint16_t perv = 512 + ofv;
	uint16_t perw = 512 + ofw;
	// now through business
	pwm_periods(peru, perv, perw);
}

Jake Read's avatar
Jake Read committed
78
void pwm_init(void){
Jake Read's avatar
Jake Read committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
	// setup awex etc
	
	pin_init(&lo1, &PORTC, PIN4_bm, 4, 1);
	pin_init(&hi1, &PORTC, PIN5_bm, 5, 1);
	pin_init(&lo2, &PORTC, PIN2_bm, 2, 1);
	pin_init(&hi2, &PORTC, PIN3_bm, 3, 1);
	pin_init(&lo3, &PORTC, PIN0_bm, 0, 1);
	pin_init(&hi3, &PORTC, PIN1_bm, 1, 1);
	
	// compare and capture at value
	uint16_t per = 1024; // at DIV1, 1024 period is 23.5kHz
	// write low first, bc bussing / xmega 8-bit oddities cc datasheet @ 3.11
	uint8_t perl = (uint8_t) per;
	uint8_t perh = (uint8_t) (per >> 8);
	
	TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
	TCC0.PERBUFL = perl;
	TCC0.PERBUFH = perh;
	
	// turnt to dual-slope pwm to have center aligned, and eventually sampling on top event
	
	TCC0.CTRLB = TC_WGMODE_DS_T_gc;// | (1 << 7) | (1 << 6) | (1 << 5); // dual slope, and enable channels a, b, c for capture
	
	AWEXC.CTRL = AWEX_DTICCAEN_bm | AWEX_DTICCBEN_bm | AWEX_DTICCCEN_bm;
	AWEXC.DTBOTHBUF = 4; // four counts of pwm clock for deadtime
	AWEXC.OUTOVEN = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
	
106
	pwm_periods(0, 0, 0);
Jake Read's avatar
Jake Read committed
107 108 109
}

void drv_init(void){
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
	// mode pins
	pin_init(&drvEnPin, &PORTD, PIN1_bm, 1, 1);
	pin_init(&drvModePwm, &PORTB, PIN6_bm, 6, 1);
	pin_init(&drvModeGain, &PORTC, PIN6_bm, 6, 1);
	pin_init(&drvDcCal, &PORTB, PIN7_bm, 7, 1);
	// status
	pin_init(&drvFault, &PORTC, PIN7_bm, 7, 0);
	pin_init(&drvOCTW, &PORTD, PIN0_bm, 0, 0);
	
	// setup drv8302 mode
	pin_clear(&drvModePwm); // low for 6-channel pwm, hi and lo sides from uc
	pin_clear(&drvModeGain); // low for 10v/v, hi for 40v/v current sense gains
	pin_clear(&drvDcCal); // turn DC cal off, we turn this high to set midpoint on amps
	pin_clear(&drvEnPin); // disable the gate driver, to start. also broken by no/go hardware switch 
}

void drv_enable(void){
	pin_set(&drvEnPin);
}

void drv_disable(void){
	pin_clear(&drvEnPin);
Jake Read's avatar
Jake Read committed
132 133 134
}

void tickers_init(void){
Jake Read's avatar
Jake Read committed
135
	// sets up two timers
Jake Read's avatar
Jake Read committed
136 137
	
	// compare and capture at value
138 139
	// this is a low-speed-start friendly value, to start the commutation ticker with 
	uint16_t perStartSpeed = 2400; 
Jake Read's avatar
Jake Read committed
140
	// write low first, bc bussing / xmega 8-bit oddities cc datasheet @ 3.11
141 142
	uint8_t perSl = (uint8_t) perStartSpeed;
	uint8_t perSh = (uint8_t) (perStartSpeed >> 8);
Jake Read's avatar
Jake Read committed
143 144
	
	// turn on TCC0
145 146 147
	TCD0.CTRLA = TC_CLKSEL_DIV64_gc;
	TCD0.PERBUFL = perSl;
	TCD0.PERBUFH = perSh;
Jake Read's avatar
Jake Read committed
148 149
	
	// set cca interrupt on
Jake Read's avatar
Jake Read committed
150
	TCD0.INTCTRLA = TC_OVFINTLVL_HI_gc;
151 152 153
	
	// and a reasonable speed for acceleration ticking
	
154
	uint16_t perAccelRate = 800;
155 156 157
	uint8_t perAl = (uint8_t) perAccelRate;
	uint8_t perAh = (uint8_t) (perAccelRate >> 8);
	
Jake Read's avatar
Jake Read committed
158
	// another ticker to execute accel
159 160 161
	TCD1.CTRLA = TC_CLKSEL_DIV64_gc;
	TCD1.PERBUFL = perAl;
	TCD1.PERBUFH = perAh;
Jake Read's avatar
Jake Read committed
162
	
Jake Read's avatar
Jake Read committed
163
	TCD1.INTCTRLA = TC_OVFINTLVL_HI_gc;
Jake Read's avatar
Jake Read committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
}

int main(void)
{
	clock_init();
	uarts_init();
	atkps_init();
	
	// enable interrupts
	sei();
	PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;

	pin_init(&stlclk, &PORTE, PIN1_bm, 1, 1);
	pin_init(&stlerr, &PORTE, PIN0_bm, 0, 1);
	pin_set(&stlerr);
	pin_set(&stlclk);
	
Jake Read's avatar
Jake Read committed
181 182 183
	//pin_init(&tstpin1, &PORTC, PIN5_bm, 5, 1);
	//pin_init(&tstpin2, &PORTC, PIN3_bm, 3, 1);
	
184
	// start timers for commutation, accel tickers 
Jake Read's avatar
Jake Read committed
185
	tickers_init();
Jake Read's avatar
Jake Read committed
186 187 188
	// startup encoder
	//encoder_init();
	
189
	// start pwm system
Jake Read's avatar
Jake Read committed
190
	pwm_init();
191 192 193
	// initialize the bldc state structure
	bldc_init(&bldc);
	// on startup speed and duty
194
	bldc_setTargetSpeed(&bldc, 1000);
195 196 197 198 199 200
	bldc_setDuty(&bldc, 10);
	// startup the driver
	drv_init();
	// and enable the gate
	drv_enable();
	// now we should be spinning at 500 eRPM, so we can set an accel... later
Jake Read's avatar
Jake Read committed
201 202 203 204 205 206

	// runtime globals
	uint32_t tck = 0;

	while (1)
	{
Jake Read's avatar
Jake Read committed
207
		//ams5047_write(&ams5047, 1200);
Jake Read's avatar
Jake Read committed
208 209 210 211 212 213 214 215 216 217 218 219
		atkport_scan(&atkp0, 2);
		// just... as fast as we can 
 		tck++;
 		// this modulo op is slow AF
 		// that means streamlining atkport_scan without modulos is probably a rad thing
    	if(!(fastModulo(tck, 4096))){
     		pin_toggle(&stlclk);
     	}
	}
}

ISR(TCC0_OVF_vect){
Jake Read's avatar
Jake Read committed
220 221 222
	pin_toggle(&hi1);
}

223 224 225 226 227 228 229 230 231 232
int8_t comTable[6][3] = {
	{1,-1,0},
	{1,0,-1},
	{0,1,-1},
	{-1,1,0},
	{-1,0,1},
	{0,-1,1}
};

// commutation timer
Jake Read's avatar
Jake Read committed
233 234
ISR(TCD0_OVF_vect){
	// commutate?
235 236 237 238 239 240 241 242 243
	(bldc.comDir) ? (bldc.comState ++) : (bldc.comState --);
	if(bldc.comState > 5){
		bldc.comState = 0;
	}
	
	pwm_by_offset(	comTable[bldc.comState][0] * bldc.comDuty,
					comTable[bldc.comState][1] * bldc.comDuty,
					comTable[bldc.comState][2] * bldc.comDuty 
				 );
Jake Read's avatar
Jake Read committed
244 245
}

246
// acceleration timer
Jake Read's avatar
Jake Read committed
247
ISR(TCD1_OVF_vect){
248 249 250 251 252 253 254 255 256
	if(bldc.currentSpeed != bldc.targetSpeed){
		if(bldc.currentSpeed < bldc.targetSpeed){
			bldc.currentSpeed ++;
			bldc_setSpeed(&bldc, bldc.currentSpeed);
		} else {
			bldc.currentSpeed --;
			bldc_setSpeed(&bldc, bldc.currentSpeed);
		}
	}
Jake Read's avatar
Jake Read committed
257 258 259 260 261 262 263 264 265
}

ISR(USARTE1_RXC_vect){
	uart_rxhandler(&up0);
}

ISR(USARTE1_DRE_vect){
	uart_txhandler(&up0);
}