diff --git a/circuit/README.md b/circuit/README.md
index 5d23ea832e6eb7e7913b8822f826df2114b43d56..a2f06f0e24571e674aa193f6690854e4ea036b2f 100644
--- a/circuit/README.md
+++ b/circuit/README.md
@@ -12,6 +12,7 @@ Power is bussed to the board with two M3 Screw Terminals. The board includes roo
 
  - label lights 
  - wants one lo-side debug pin!
+ - for resets etc, pull en to gnd on other side of switch!
 
  - might have to go to DRV8320 - newer, available
   - CSD88548 is CSD88599 but more amps less volts, use these 
diff --git a/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile b/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile
index 55ad9d1111549880886972fd7462368f73d22cec..a701f1dc9378c8c7fdc56d2afac212dc85366e6c 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile
+++ b/embedded/atkbldcdriver/atkbldcdriver/Debug/Makefile
@@ -39,6 +39,7 @@ SUBDIRS :=
 C_SRCS +=  \
 ../atkhandler.c \
 ../atkport.c \
+../bldc.c \
 ../fastmath.c \
 ../main.c \
 ../pin.c \
@@ -57,6 +58,7 @@ ASM_SRCS +=
 OBJS +=  \
 atkhandler.o \
 atkport.o \
+bldc.o \
 fastmath.o \
 main.o \
 pin.o \
@@ -68,6 +70,7 @@ uartport.o
 OBJS_AS_ARGS +=  \
 atkhandler.o \
 atkport.o \
+bldc.o \
 fastmath.o \
 main.o \
 pin.o \
@@ -79,6 +82,7 @@ uartport.o
 C_DEPS +=  \
 atkhandler.d \
 atkport.d \
+bldc.d \
 fastmath.d \
 main.d \
 pin.d \
@@ -90,6 +94,7 @@ uartport.d
 C_DEPS_AS_ARGS +=  \
 atkhandler.d \
 atkport.d \
+bldc.d \
 fastmath.d \
 main.d \
 pin.d \
@@ -130,6 +135,8 @@ LINKER_SCRIPT_DEP+=
 
 
 
+
+
 
 ./%.o: .././%.c
 	@echo Building file: $<
diff --git a/embedded/atkbldcdriver/atkbldcdriver/Debug/makedep.mk b/embedded/atkbldcdriver/atkbldcdriver/Debug/makedep.mk
index d5a1f4deaaeea7141daebfba92ac8c3db20f3106..0d51b274956f4b3ba52ae51603b37953a05dcbe2 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/Debug/makedep.mk
+++ b/embedded/atkbldcdriver/atkbldcdriver/Debug/makedep.mk
@@ -6,6 +6,8 @@ atkhandler.c
 
 atkport.c
 
+bldc.c
+
 fastmath.c
 
 main.c
diff --git a/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj b/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj
index 500ce0ac9e04aa4c870817b41597ab6c2b555f2b..56c8b18cc01bff2fa54d736eb93df42a807a3baa 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj
+++ b/embedded/atkbldcdriver/atkbldcdriver/atkbldcdriver.cproj
@@ -148,6 +148,12 @@
     <Compile Include="atkport.h">
       <SubType>compile</SubType>
     </Compile>
+    <Compile Include="bldc.c">
+      <SubType>compile</SubType>
+    </Compile>
+    <Compile Include="bldc.h">
+      <SubType>compile</SubType>
+    </Compile>
     <Compile Include="fastmath.c">
       <SubType>compile</SubType>
     </Compile>
diff --git a/embedded/atkbldcdriver/atkbldcdriver/atkhandler.c b/embedded/atkbldcdriver/atkbldcdriver/atkhandler.c
index d930ce591de717d660533c01d0527115f5df1030..0577c4693978a6a15babaa7626e12c2cdc666a99 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/atkhandler.c
+++ b/embedded/atkbldcdriver/atkbldcdriver/atkhandler.c
@@ -8,7 +8,8 @@
 #include "hardware.h"
 #include "atkhandler.h"
 
-int32_t steps;
+uint8_t testReply[4] = {127, 12, 24, 48};
+uint8_t speedReply[4] = {141, 13, 25, 49};
 
 void atk_handle_packet(uint8_t *packet, uint8_t length){
 	// dirty debug reply
@@ -16,7 +17,6 @@ void atk_handle_packet(uint8_t *packet, uint8_t length){
 	// through packet
 	int i = 0;
 	int atk_handler_state = ATK_HANDLER_OUTSIDE;
-	uint8_t testReply[4] = {127, 12, 24, 48};
 		
 	while(i < length){ // prep for the messy double switch :|
 		switch (atk_handler_state){
@@ -50,7 +50,16 @@ void atk_handle_packet(uint8_t *packet, uint8_t length){
 						break;
 						
 					case DELIM_KEY_SPEED:
-						// set timers
+						// integer signed so that we can do dir with the same command 
+						if(i + 9 > length){
+							i ++;
+						} else {
+							int32_t speed = ((int32_t)packet[i+1] << 24) | ((int32_t)packet[i+2] << 16) | ((int32_t)packet[i+3] << 8) | (int32_t)packet[i+4];
+							uint32_t duty = ((int32_t)packet[i+5] << 24) | ((int32_t)packet[i+6] << 16) | ((int32_t)packet[i+7] << 8) | (int32_t)packet[i+8];
+							i += 9;
+							bldc_newSpeed(&bldc, speed, duty);
+							atk_reply_packet(packet, speedReply, 4);
+							}
 						break;
 					
 					case DELIM_KEY_TRAPEZOID:
diff --git a/embedded/atkbldcdriver/atkbldcdriver/bldc.c b/embedded/atkbldcdriver/atkbldcdriver/bldc.c
new file mode 100644
index 0000000000000000000000000000000000000000..d99f98b189982de81d7c6780fc43485e5cca4903
--- /dev/null
+++ b/embedded/atkbldcdriver/atkbldcdriver/bldc.c
@@ -0,0 +1,57 @@
+/*
+ * bldc.c
+ *
+ * Created: 7/12/2018 1:52:34 PM
+ *  Author: Jake
+ */ 
+
+#include "bldc.h"
+#include "hardware.h"
+
+void bldc_init(bldc_t *bldc){
+	bldc->comState = 0;
+	bldc->comDir = 1;
+	bldc->comDuty = 0;
+}
+
+void bldc_shutdown(bldc_t *bldc){
+	pin_clear(&drvEnPin);
+	bldc->comState = 0;
+	bldc->comDir = 1;
+	bldc->comDuty = 0;
+}
+
+void bldc_setDuty(bldc_t *bldc, uint32_t duty){
+	// blind pwm duty 0-512
+	(duty > 512) ? duty = 512 : (0);
+	bldc->comDuty = (uint16_t) duty;
+}
+
+void bldc_setSpeed(bldc_t *bldc, int32_t speed){
+	// speed in eRPM
+	// assert max
+	uint32_t sAbs = abs(speed);
+	(sAbs > 20000) ? sAbs = 20000 : (0);
+	// check dir
+	if(speed == 0){
+		bldc_shutdown(bldc);
+	} else if (speed > 0){
+		bldc->comDir = 1;
+	} else {
+		bldc->comDir = 0;
+	}
+	
+	// base time, and we want 6 steps / rev, and rpm-rps
+	bldc->comPeriod = COMTICKER_TICKS_SECOND / (sAbs / 10); 
+	
+	// set a new timer period
+	uint8_t ctPerBufL = (uint8_t) bldc->comPeriod;
+	uint8_t ctPerBufH = (uint8_t) (bldc->comPeriod >> 8);
+	TCD0.PERBUFL = ctPerBufL;
+	TCD0.PERBUFH = ctPerBufH;
+}
+
+void bldc_newSpeed(bldc_t *bldc, int32_t speed, uint32_t duty){
+	bldc_setDuty(bldc, duty);
+	bldc_setSpeed(bldc, speed);
+}
\ No newline at end of file
diff --git a/embedded/atkbldcdriver/atkbldcdriver/bldc.h b/embedded/atkbldcdriver/atkbldcdriver/bldc.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0a911f8fdeef19285fa4010ea502b8cc6ac70ec
--- /dev/null
+++ b/embedded/atkbldcdriver/atkbldcdriver/bldc.h
@@ -0,0 +1,35 @@
+/*
+ * bldc.h
+ *
+ * Created: 7/12/2018 1:52:26 PM
+ *  Author: Jake
+ */ 
+
+
+#ifndef BLDC_H_
+#define BLDC_H_
+
+#include "avr/io.h"
+
+typedef struct{
+	uint8_t comState;
+	uint8_t comDir;
+	uint16_t comDuty;
+	
+	uint16_t comPeriod;
+}bldc_t;
+
+void bldc_init(bldc_t *bldc);
+
+void bldc_shutdown(bldc_t *bldc);
+
+void bldc_setDuty(bldc_t *bldc, uint32_t duty);
+
+void bldc_setSpeed(bldc_t *bldc, int32_t speed);
+
+void bldc_start(bldc_t *bldc, int32_t speed, uint32_t duty);
+
+void bldc_newSpeed(bldc_t *bldc, int32_t speed, uint32_t duty);
+
+
+#endif /* BLDC_H_ */
\ No newline at end of file
diff --git a/embedded/atkbldcdriver/atkbldcdriver/hardware.h b/embedded/atkbldcdriver/atkbldcdriver/hardware.h
index 35003eaaf7c9dcbdc1eb91de57aafd93cb420950..85044ecf054ca0af8e8abc18c980a5a53ff7b0b0 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/hardware.h
+++ b/embedded/atkbldcdriver/atkbldcdriver/hardware.h
@@ -16,12 +16,17 @@
 #include "atkport.h"
 #include "atkhandler.h"
 #include "ams5047.h"
+#include "bldc.h"
 
 // results in 1MBaud
 #define SYSTEM_BAUDA 3
 #define SYSTEM_BAUDB 0
 #define SYSTEM_NUM_UPS 1
 
+// ticker bases
+
+#define COMTICKER_TICKS_SECOND 750000
+
 pin_t stlclk;
 pin_t stlerr;
 
@@ -70,6 +75,11 @@ pin_t hi3;
 
 // controller functions 
 
+bldc_t bldc;
+
+uint8_t comState;
+uint16_t comDuty;
+
 // bldc_t bldc;
 
 pin_t tstpin1;
diff --git a/embedded/atkbldcdriver/atkbldcdriver/main.c b/embedded/atkbldcdriver/atkbldcdriver/main.c
index 0da60d43cc64ab7324db027c3f4d68b15cad2211..a90dc47329dd582d77bbffbfbd82b5c8827a0801 100644
--- a/embedded/atkbldcdriver/atkbldcdriver/main.c
+++ b/embedded/atkbldcdriver/atkbldcdriver/main.c
@@ -66,6 +66,15 @@ void pwm_periods(uint16_t peru, uint16_t perv, uint16_t perw){
 	TCC0.CCCBUFH = (uint8_t) (peru >> 8);
 }
 
+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);
+}
+
 void pwm_init(void){
 	// setup awex etc
 	
@@ -94,34 +103,62 @@ void pwm_init(void){
 	AWEXC.DTBOTHBUF = 4; // four counts of pwm clock for deadtime
 	AWEXC.OUTOVEN = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5);
 	
-	pwm_periods(256, 512, 768);
+	pwm_periods(0, 0, 0);
 }
 
 void drv_init(void){
-	
+	// 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);
 }
 
 void tickers_init(void){
 	// sets up two timers
 	
 	// compare and capture at value
-	uint16_t pera = 1200; 
+	// this is a low-speed-start friendly value, to start the commutation ticker with 
+	uint16_t perStartSpeed = 2400; 
 	// write low first, bc bussing / xmega 8-bit oddities cc datasheet @ 3.11
-	uint8_t peral = (uint8_t) pera;
-	uint8_t perah = (uint8_t) (pera >> 8);
+	uint8_t perSl = (uint8_t) perStartSpeed;
+	uint8_t perSh = (uint8_t) (perStartSpeed >> 8);
 	
 	// turn on TCC0
-	TCD0.CTRLA = TC_CLKSEL_DIV256_gc;
-	TCD0.PERBUFL = peral;
-	TCD0.PERBUFH = perah;
+	TCD0.CTRLA = TC_CLKSEL_DIV64_gc;
+	TCD0.PERBUFL = perSl;
+	TCD0.PERBUFH = perSh;
 	
 	// set cca interrupt on
 	TCD0.INTCTRLA = TC_OVFINTLVL_HI_gc;
-		
+	
+	// and a reasonable speed for acceleration ticking
+	
+	uint16_t perAccelRate = 2400;
+	uint8_t perAl = (uint8_t) perAccelRate;
+	uint8_t perAh = (uint8_t) (perAccelRate >> 8);
+	
 	// another ticker to execute accel
-	TCD1.CTRLA = TC_CLKSEL_DIV256_gc;
-	TCD1.PERBUFL = peral;
-	TCD1.PERBUFH = perah;
+	TCD1.CTRLA = TC_CLKSEL_DIV64_gc;
+	TCD1.PERBUFL = perAl;
+	TCD1.PERBUFH = perAh;
 	
 	TCD1.INTCTRLA = TC_OVFINTLVL_HI_gc;
 }
@@ -144,9 +181,20 @@ int main(void)
 	//pin_init(&tstpin1, &PORTC, PIN5_bm, 5, 1);
 	//pin_init(&tstpin2, &PORTC, PIN3_bm, 3, 1);
 	
+	// start timers for commutation, accel tickers 
 	tickers_init();
-	
+	// start pwm system
 	pwm_init();
+	// initialize the bldc state structure
+	bldc_init(&bldc);
+	// on startup speed and duty
+	bldc_setSpeed(&bldc, 1000);
+	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
 
 	// runtime globals
 	uint32_t tck = 0;
@@ -168,11 +216,30 @@ ISR(TCC0_OVF_vect){
 	pin_toggle(&hi1);
 }
 
+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
 ISR(TCD0_OVF_vect){
 	// commutate?
-	//pin_toggle(&tstpin1);
+	(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 
+				 );
 }
 
+// acceleration timer
 ISR(TCD1_OVF_vect){
 	//pin_toggle(&tstpin2);
 }