Fix for hack that worked around iOS app

Revision:
0:8c0ecbdd3449
Child:
2:4f76784f8968
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Haptics.cpp	Tue Feb 02 22:00:49 2016 +0000
@@ -0,0 +1,232 @@
+/******************************************************************************
+ * Haptics.c
+ *
+ * Created on: Dec 16, 2011
+ * Board: DRV2603EVM-CT RevD
+ * Author: a0866685
+ *
+ * Description: This file contains the functions for sending haptics waveforms.
+ * 		Edit this file when changing actuators.
+ *
+ * @TODO - Update this file when changing between actuators types
+ * 			(ERM, LRA, Piezo)
+ *
+ ******************************************************************************/
+#include "Haptics.h"
+#include "Actuator_Waveforms.h"
+
+// private variables
+//static uint8_t  j,k;
+
+// public variables
+uint16_t Haptics_dumbModeTick = DUMBTICK;		// Sets the LRA Auto-resonance off frequency (use DUMBTICK above to set frequency)
+uint16_t Haptics_resonantModeTick;
+
+DigitalOut LRA_EN(P0_12);
+PwmOut LRA(P0_11);
+
+extern DigitalOut led1;
+
+Ticker hapticsTicker;
+volatile uint16_t lraPlaybackMode = 0;
+volatile int lraCurrent = 0;
+volatile int lraTarget = 0;
+volatile uint16_t lraDelay = 0;
+volatile uint16_t placeInWaveform = 0;
+volatile uint16_t waveformDelayCounter = 0;
+const Waveform* volatile waveform;
+const Waveform* volatile heartbeatWaveform = &lra_tick;
+
+
+// TODO: Support haptics modalities here: off, waveform, delayed waveform, ramp to target
+
+// Called every 5ms to update LRA amplitude based on desired haptics response
+void hapticsCallback() {
+	switch (lraPlaybackMode) {
+		case LRA_MODE_WAVEFORM:
+			// play the current amplitude
+			//led1 = 1;
+
+			if(waveform->data[placeInWaveform] == 0x80) {
+				LRA.pulsewidth_us(0);
+				LRA_EN = 0;
+			} else {
+				LRA_EN = 1;
+				//LRA.pulsewidth_us(90);
+				LRA.pulsewidth_us(((((uint16_t)waveform->data[placeInWaveform])*3) >> 3));  // mult by 3 shift right by 4 to get in range of 0..47
+				
+			}	
+
+			// run down the timer on this amplitude
+			waveformDelayCounter++;
+			if (waveformDelayCounter >= waveform->data[placeInWaveform+1]) {
+				// move to the next waveform entry and reset the timer when necessary
+				waveformDelayCounter=0;		
+				placeInWaveform += 2;
+				if (placeInWaveform >= waveform->length) {
+					//led1 = 0;
+					LRA.pulsewidth_us(0);
+					LRA_EN = 0;
+					placeInWaveform = 0;
+					waveformDelayCounter = 0;
+					lraPlaybackMode = LRA_MODE_OFF;
+				}
+			}	
+			break;
+		case LRA_MODE_DELAYED_WAVEFORM:
+			waveformDelayCounter+=5; // every tick is 5ms
+			if (waveformDelayCounter >= lraDelay) {
+				waveformDelayCounter = 0;
+				lraPlaybackMode = LRA_MODE_WAVEFORM;
+			}
+			break;
+		case LRA_MODE_RAMP_TO_TARGET:
+			// full ramp from 384 to 768 (threshold to full) takes 384*5 = 1920ms with step size = 1
+			if (lraTarget > lraCurrent) {
+				lraCurrent += 2;
+			} else {
+				lraCurrent -= 2;
+			}
+			LRA_EN = 1;
+			//led1 = 1;
+			LRA.pulsewidth_us((lraCurrent) >> 3);   //divide by 8 to get in range of 0..95
+			break;
+		case LRA_MODE_OFF:
+		default: 
+			// Do nothing
+			break;
+	}
+}
+	
+/**
+ * Haptics_Init - initialize haptics variables and settings
+ */
+void Haptics_Init(void)
+{
+	// mbed uses 4uS timer precision, so keep this as large as possible for better granularity
+	// 96 uS period means 96 is the maximum pulse width. So we need to scale from 256 to 96, or mult by 3, and shift right by 3.
+	LRA.period_us(96); // 96 uS -> 10.4 Khz (needs to be between 10Khz and 250Khz)
+
+	hapticsTicker.attach(&hapticsCallback, 0.005); // update haptics every 5 ms	    
+	
+	Haptics_resonantModeTick = (unsigned int) Haptics_dumbModeTick * 2;
+}
+
+
+/*
+ * Haptics_OutputWaveform - control the PWM output pattern
+ * @param struct Waveform - the waveform output type, length in bytes, and data
+ */
+void Haptics_OutputWaveform(const Waveform* newWaveform)
+{
+
+	if (lraPlaybackMode == LRA_MODE_OFF || lraPlaybackMode == LRA_MODE_RAMP_TO_TARGET) {
+		waveform = newWaveform;
+		lraPlaybackMode = LRA_MODE_WAVEFORM;
+	} else {
+		//printf("OutputWaveform: mode=%d, delay=%d, place=%d\n\r", lraPlaybackMode, waveformDelayCounter, placeInWaveform);
+	}
+}
+
+// Override any currently active haptic effect
+void Haptics_OverrideOutputWaveform(const Waveform* newWaveform)
+{
+	//led1 = !led1;
+	placeInWaveform = 0;
+	waveform = newWaveform;
+	LRA_EN = 1;
+	LRA.pulsewidth_us((((int)waveform->data[placeInWaveform])*3) >> 3);  // mult by 3 shift right by 2 to get in range of 0..95
+	lraPlaybackMode = LRA_MODE_WAVEFORM;
+}
+
+void Haptics_OutputDelayedHeartbeat(uint16_t delay) {
+	Haptics_OutputDelayedWaveform(heartbeatWaveform, delay); 
+}
+
+void Haptics_SetHeartbeatWaveform (int waveformNum) {
+	printf("SetHeartbeatWaveform to %d.\n\r", waveformNum);
+	
+	switch (waveformNum) {
+		case 1:
+			heartbeatWaveform = &lra_click_nobrake;
+			break;
+		case 2:
+			heartbeatWaveform = &lra_alert;
+			break;
+		case 3:
+			heartbeatWaveform = &lra_rampup;
+			break;
+		case 4:
+			heartbeatWaveform = &lra_rampdown;
+			break;
+		case 5:
+			heartbeatWaveform = &lra_softclick;
+			break;
+		case 6:
+			heartbeatWaveform = &lra_softbump;
+			break;						
+		case 7:
+			heartbeatWaveform = &lra_softalert;
+			break;
+		case 8:
+			heartbeatWaveform = &lra_rampupdoubleclick;
+			break;			
+		case 0:
+		default:
+			heartbeatWaveform = &lra_tick;
+	}
+}
+	
+void Haptics_OutputDelayedWaveform(const Waveform* newWaveform, uint16_t delay) {
+
+	if (lraPlaybackMode == LRA_MODE_OFF || lraPlaybackMode == LRA_MODE_RAMP_TO_TARGET) {
+		placeInWaveform = 0;
+		waveformDelayCounter = 0;
+		lraDelay = delay;
+		waveform = newWaveform;
+		lraPlaybackMode = LRA_MODE_DELAYED_WAVEFORM;
+	} else {
+		//printf("Haptics: mode=%d, delay=%d, until=%d, place=%d\n\r", lraPlaybackMode, waveformDelayCounter, lraDelay, placeInWaveform);
+	}
+}
+	
+// Ignored while waveform is playing or queued. Overridden by waveforms.
+void Haptics_SetRampTarget(float amplitude)
+{
+	if (lraPlaybackMode == LRA_MODE_OFF || lraPlaybackMode == LRA_MODE_RAMP_TO_TARGET) {
+		if (lraPlaybackMode == LRA_MODE_OFF) {
+			lraCurrent = 384; // reset to threshold off if this is the first ramp target
+		}
+		if (amplitude > 1.0) amplitude = 1.0;
+		if (amplitude < 0.0) amplitude = 0.0;
+		lraTarget = (int) (amplitude*768); // (96 * 8)
+		lraPlaybackMode = LRA_MODE_RAMP_TO_TARGET;
+		//printf("Ramp current=%d, target=%d\n\r", lraCurrent>>3, lraTarget>>3);
+	}
+}
+
+// Buzz this many times
+void Haptics_OutputCount (uint16_t count) {
+	switch (count) {
+		case 1:
+			Haptics_OutputWaveform(&lra_click_nobrake);
+			break;
+		case 2:
+			Haptics_OutputWaveform(&lra_doubleclick_nobrake);
+			break;
+		case 3:
+			Haptics_OutputWaveform(&lra_tripleclick_nobrake);
+			break;		
+	}
+}
+
+// Stop haptics regardless of mode
+void Haptics_Off()
+{
+	lraPlaybackMode = LRA_MODE_OFF;
+}
+
+bool isHapticsOff()
+{
+	return (lraPlaybackMode == LRA_MODE_OFF);
+}