UT CS Bootcamp code for creating a secret knock
Dependencies: MMA8451Q mbed tsi_sensor
Fork of UTCSBootcamp by
Revision 0:2010bcffbae0, committed 2013-08-22
- Comitter:
- ccoleman
- Date:
- Thu Aug 22 20:50:08 2013 +0000
- Child:
- 1:8408853a700c
- Commit message:
- Wrapped Freescale Cup code.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Accelerometer.lib Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/emilmont/code/MMA8451Q/#c4d879a39775
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CarAPI.cpp Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,136 @@ +#include "CarAPI.h" +#include "CarBaseAPI.h" + +/******************************** Init and Finish ********************************/ + +void init(){ + _initialize(); +} + +void finish(){ + _finish(); +} + +/******************************** Wheels and Motor ********************************/ + +/* turn the car. turnAngle should be between [-1,1] */ +void turn(float turnAngle){ + turn(0,turnAngle); +} + +/** move forward with the given power, turn angle, for a specified time */ +void move(float power, float seconds){ + move (power,power,seconds); +} + +/** move forward with the given powers for each wheel, turn angle, for a specified time */ +void move(float leftWheelPower,float rightWheelPower, float seconds){ + if(debug) pc.printf("move(%f,%f,%f)",leftWheelPower,rightWheelPower,seconds); + TFC_SetMotorPWM(leftWheelPower,rightWheelPower); // power for n seconds with both wheels the same power + wait(seconds); + TFC_SetMotorPWM(0,0); // turn off power to both wheels + wait(0.05); //need a wait to register or sebsequent calls to this method won't spin the wheel; hardware can't detect instaneous input? +} + +/** lock the wheels*/ +void parkingBrake(){ + if(debug) pc.printf("parkingBrake()"); + TFC_SetMotorPWM(0.1,0.1); //slight spinning of wheel + wait(0.1); +} + +/******************************** INPUTS AND OUTPUTS ********************************/ +/** check to see if the car is crashing into something */ +bool checkIsCrashing(){ + if(debug) pc.printf("checkIsCrashing()"); + return abs(accelerometer.getAccX()) >= crashSensitivity; +} + +/** Return the line direction + line to the left of center. return [-1,0 + line to the right of center. return (0,1] + line in center. return 0 +*/ +float lineDirection(){ + return 0; +} + +/* toggle led 0 */ +void toggleLED0(){ + if(debug) pc.printf("toggleLED0()"); + TFC_BAT_LED0_TOGGLE; +} + +/* toggle led 1 */ +void toggleLED1(){ + if(debug) pc.printf("toggleLED1()"); + TFC_BAT_LED1_TOGGLE; +} + +/* toggle led 2 */ +void toggleLED2(){ + if(debug) pc.printf("toggleLED2()"); + TFC_BAT_LED2_TOGGLE; +} + +/* toggle led 3 */ +void toggleLED3(){ + if(debug) pc.printf("toggleLED3()"); + TFC_BAT_LED3_TOGGLE; +} + +/** is Button B pressed */ +bool isButtonBPressed(){ + if(debug) pc.printf("isButtonBPressed()=",TFC_PUSH_BUTTON_1_PRESSED); + return TFC_PUSH_BUTTON_1_PRESSED; +} + +/** read Potentiometer 0. returns [-1,1] */ +float getPot0(){ + if(debug) pc.printf("getPot0()= %f", TFC_ReadPot(0)); + return TFC_ReadPot(0); +} + +/** read Potentiometer 1. returns [-1,1] */ +float getPot1(){ + if(debug) pc.printf("getPot1()= %f", TFC_ReadPot(1)); + return TFC_ReadPot(1); +} + +/** How much batter remains. returns [0,1] */ +float batteryLife(){ + if(debug) pc.printf("batteryLife()= %f", TFC_ReadBatteryVoltage()); + return TFC_ReadBatteryVoltage(); +} + +/******************************** Changing Variables ********************************/ + +/** set the base turn offset*/ +void setOffset(float _turnOffset){ + if(debug) pc.printf("setOffset()= %f", _turnOffset); + turnOffset = _turnOffset; +} + +/** get the base turn offset */ +float getOffset(){ + if(debug) pc.printf("getOffset()= %f", turnOffset); + return turnOffset; +} + +/** set the base crash sensitivity*/ +void setCrashSensitivity(float _sensitivity){ + if(debug) pc.printf("setCrashSensitivity()= %f", _sensitivity); + crashSensitivity = _sensitivity; +} + +/** return the crash sensitivity */ +float getCrashSensitivity(){ + if(debug) pc.printf("getCrashSensitivity()= %f", crashSensitivity); + return crashSensitivity; +} + +/** turn on debugging*/ +void setDebug(bool _debug){ + if(debug) pc.printf("setDebug()= %d", _debug); + debug = _debug; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CarAPI.h Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,75 @@ +#ifndef CAR_API_0yx22l34755 +#define CAR_API_0yx22l34755 + +/******************************** Init and Finish ********************************/ +void init(); + +void finish(); + +/******************************** Wheels and Motor ********************************/ + +/* turn the car. turnAngle should be between [-1,1] */ +void turn(float turnAngle); + +/** move forward with the given power, turn angle, for a specified time */ +void move(float power, float seconds); + +/** move forward with the given powers for each wheel, turn angle, for a specified time */ +void move(float leftWheelPower, float rightWheelPower, float seconds); + +/** lock the wheels*/ +void parkingBrake(); + +/******************************** INPUTS AND OUTPUTS ********************************/ +/** check to see if the car is crashing into something */ +bool checkIsCrashing(); + +/** Return the line direction + line to the left of center. return [-1,0 + line to the right of center. return (0,1] + line in center. return 0 +*/ +float lineDirection(); + +/* toggle led 0 */ +void toggleLED0(); + +/* toggle led 1 */ +void toggleLED1(); + +/* toggle led 2 */ +void toggleLED2(); + +/* toggle led 3 */ +void toggleLED3(); + +/** is Button B pressed */ +bool isButtonBPressed(); + +/** read Potentiometer 0. returns [-1,1] */ +float getPot0(); + +/** read Potentiometer 1. returns [-1,1] */ +float getPot1(); + +/** How much battery remains. returns [0,1] */ +float batteryLife(); + +/******************************** Changing Variables ********************************/ +/** set the base turn offset*/ +void setOffset(float _turnOffset); + +/** get the base turn offset */ +float getOffset(); + +/** set the base crash sensitivity*/ +void setCrashSensitivity(float _sensitivity); + +/** return the crash sensitivity */ +float getCrashSensitivity(); + +/** turn on debugging. prints each method call to the serial port*/ +void setDebug(bool _debug); + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CarBaseAPI.h Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,158 @@ +#ifndef CAR_BASE_API_046o73i4277823 +#define CAR_BASE_API_046o73i4277823 + +#include "mbed.h" +#include "TFC.h" +#include <MMA8451Q.h> + + +Ticker TFC_TickerObj; +Serial pc(USBTX,USBRX); +// AnalogIn pot (p15); + +#define NUM_TFC_TICKERS 4 +#define MMA8451_I2C_ADDRESS (0x1d<<1) +// Define serial ports +volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS]; + + +float turnOffset = 0.002;// the turn turnOffset +float crashSensitivity = 0.5; // crash sensitivity +bool debug = false; + +MMA8451Q accelerometer(PTE25,PTE24, MMA8451_I2C_ADDRESS); + +void TFC_TickerUpdate() +{ + int i; + for(i=0; i<NUM_TFC_TICKERS; i++) + { + if(TFC_Ticker[i]<0xFFFFFFFF) + { + TFC_Ticker[0]++; + } + } +} + + +void flushSerialBuffer(void) { while (pc.readable()) { pc.getc(); } return; } + +void _blinkSequence(bool left){ + static float w = 0.125; + if (left) { + TFC_BAT_LED0_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED0_TOGGLE; + TFC_BAT_LED1_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED1_TOGGLE; + TFC_BAT_LED2_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED2_TOGGLE; + TFC_BAT_LED3_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED3_TOGGLE; + } else { + TFC_BAT_LED3_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED3_TOGGLE; + TFC_BAT_LED2_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED2_TOGGLE; + TFC_BAT_LED1_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED1_TOGGLE; + TFC_BAT_LED0_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED0_TOGGLE; + } +} + +void blinkSequence(){ + _blinkSequence(false); + _blinkSequence(true); +} + +void blinkSequence2(){ + float w = 0.125; + TFC_BAT_LED0_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED1_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED2_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED3_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED3_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED2_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED1_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); + TFC_BAT_LED0_TOGGLE; + if (TFC_PUSH_BUTTON_0_PRESSED) return; + wait(w); +} +/* turn the car */ +void turn(float d, float turnAngle){ + if(debug) pc.printf("turn(%f)",turnAngle); + TFC_SetServo(d,turnAngle + turnOffset); +} + +void _initialize(){ + if(debug) pc.printf("initialize()"); + //TFC_TickerObj.attach_us(&TFC_TickerUpdate,1000); //Things go to heck if this is enabled + TFC_Init(); + + // Initialize Baud Rate for PC Console + pc.baud(38400); + + //flash startup + while(!TFC_PUSH_BUTTON_0_PRESSED){ + blinkSequence(); + } + wait(2); + //starts power to back motor - hear high frequency pitch + TFC_HBRIDGE_ENABLE; +} + +void _finish(){ + if(debug) pc.printf("finish()"); + //parking brake + //need to keep spinning wheel slightly or the car will come crashing down backwards the ramp b/c of gravity + //slight spin is not enough to move the car (even on flat surface) + //press button 0 to stop parking brake and turn off motor - goes into wait period w/ LED1 blinking + while (!TFC_PUSH_BUTTON_0_PRESSED){ + /// sharon's parking break code + TFC_SetMotorPWM(0.1,0.1); //slight spinning of wheel + wait(0.1); + } + + //reset to straight direction and stop spinning motor + TFC_SetMotorPWM(0,0); + + //stops the power to back motor - stop hearing the high pitch frequency + TFC_HBRIDGE_DISABLE; + + while(1){ + blinkSequence2(); + } +} + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFC.cpp Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,988 @@ +#include "mbed.h" +#include "TFC.h" + +#define FTM1_CLK_PRESCALE 6// Prescale Selector value - see comments in Status Control (SC) section for more details +#define SERVO_DEFAULT_PERIOD (float)(.020) // Desired Frequency of PWM Signal - Here 50Hz => 20ms period +// use these to dial in servo steering to your particular servo +#define SERVO_MIN_PULSE_WIDTH_DEFAULT (float)(.0005) // The number here should be be *pulse width* in seconds to move servo to its left limit +#define SERVO_MAX_PULSE_WIDTH_DEFAULT (float)(.002) // The number here should be be *pulse width* in seconds to move servo to its left limit + + +#define FTM0_CLOCK (SystemCoreClock/2) +#define FTM0_CLK_PRESCALE (0) // Prescale Selector value - see comments in Status Control (SC) section for more details +#define FTM0_DEFAULT_SWITCHING_FREQUENCY (4000.0) + +#define ADC_MAX_CODE (255) + +#define TAOS_CLK_HIGH PTE->PSOR = (1<<1) +#define TAOS_CLK_LOW PTE->PCOR = (1<<1) +#define TAOS_SI_HIGH PTD->PSOR = (1<<7) +#define TAOS_SI_LOW PTD->PCOR = (1<<7) + +#define ADC_STATE_INIT 0 +#define ADC_STATE_CAPTURE_POT_0 1 +#define ADC_STATE_CAPTURE_POT_1 2 +#define ADC_STATE_CAPTURE_BATTERY_LEVEL 3 +#define ADC_STATE_CAPTURE_LINE_SCAN 4 + + +#define TFC_POT_0_ADC_CHANNEL 13 +#define TFC_POT_1_ADC_CHANNEL 12 +#define TFC_BAT_SENSE_CHANNEL 4 +#define TFC_LINESCAN0_ADC_CHANNEL 6 +#define TFC_LINESCAN1_ADC_CHANNEL 7 + + +#define ADC0_irq_no 57 +#define ADC1_irq_no 58 + +#define ADC0_CHANA 19 // set to desired ADC0 channel trigger A +#define ADC0_CHANB 20 // set to desired ADC0 channel trigger B + +#define ADC1_CHANA 20 // set to desired ADC1 channel trigger A 20 defaults to potentiometer in TWRK60 +#define ADC1_CHANB 20 // set to desired ADC1 channel trigger B + +#define ADC0_DLYA 0x2000 // ADC0 trigger A delay +#define ADC0_DLYB 0x4000 // ADC0 trigger B delay +#define ADC1_DLYA 0x6000 // ADC1 trigger A delay +#define ADC1_DLYB 0x7fff // ADC1 trigger B delay + + +#define ADC0A_DONE 0x01 +#define ADC0B_DONE 0x02 +#define ADC1A_DONE 0x04 +#define ADC1B_DONE 0x08 + + +// Bit shifting of bitfiled is already taken into account so +// bitfiled values are always represented as relative to their position. + +/************************* #Defines ******************************************/ + +#define A 0x0 +#define B 0x1 + +/////// NOTE: the following defines relate to the ADC register definitions +/////// and the content follows the reference manual, using the same symbols. + + +//// ADCSC1 (register) + +// Conversion Complete (COCO) mask +#define COCO_COMPLETE ADC_SC1_COCO_MASK +#define COCO_NOT 0x00 + +// ADC interrupts: enabled, or disabled. +#define AIEN_ON ADC_SC1_AIEN_MASK +#define AIEN_OFF 0x00 + +// Differential or Single ended ADC input +#define DIFF_SINGLE 0x00 +#define DIFF_DIFFERENTIAL ADC_SC1_DIFF_MASK + +//// ADCCFG1 + +// Power setting of ADC +#define ADLPC_LOW ADC_CFG1_ADLPC_MASK +#define ADLPC_NORMAL 0x00 + +// Clock divisor +#define ADIV_1 0x00 +#define ADIV_2 0x01 +#define ADIV_4 0x02 +#define ADIV_8 0x03 + +// Long samle time, or Short sample time +#define ADLSMP_LONG ADC_CFG1_ADLSMP_MASK +#define ADLSMP_SHORT 0x00 + +// How many bits for the conversion? 8, 12, 10, or 16 (single ended). +#define MODE_8 0x00 +#define MODE_12 0x01 +#define MODE_10 0x02 +#define MODE_16 0x03 + + + +// ADC Input Clock Source choice? Bus clock, Bus clock/2, "altclk", or the +// ADC's own asynchronous clock for less noise +#define ADICLK_BUS 0x00 +#define ADICLK_BUS_2 0x01 +#define ADICLK_ALTCLK 0x02 +#define ADICLK_ADACK 0x03 + +//// ADCCFG2 + +// Select between B or A channels +#define MUXSEL_ADCB ADC_CFG2_MUXSEL_MASK +#define MUXSEL_ADCA 0x00 + +// Ansync clock output enable: enable, or disable the output of it +#define ADACKEN_ENABLED ADC_CFG2_ADACKEN_MASK +#define ADACKEN_DISABLED 0x00 + +// High speed or low speed conversion mode +#define ADHSC_HISPEED ADC_CFG2_ADHSC_MASK +#define ADHSC_NORMAL 0x00 + +// Long Sample Time selector: 20, 12, 6, or 2 extra clocks for a longer sample time +#define ADLSTS_20 0x00 +#define ADLSTS_12 0x01 +#define ADLSTS_6 0x02 +#define ADLSTS_2 0x03 + +////ADCSC2 + +// Read-only status bit indicating conversion status +#define ADACT_ACTIVE ADC_SC2_ADACT_MASK +#define ADACT_INACTIVE 0x00 + +// Trigger for starting conversion: Hardware trigger, or software trigger. +// For using PDB, the Hardware trigger option is selected. +#define ADTRG_HW ADC_SC2_ADTRG_MASK +#define ADTRG_SW 0x00 + +// ADC Compare Function Enable: Disabled, or Enabled. +#define ACFE_DISABLED 0x00 +#define ACFE_ENABLED ADC_SC2_ACFE_MASK + +// Compare Function Greater Than Enable: Greater, or Less. +#define ACFGT_GREATER ADC_SC2_ACFGT_MASK +#define ACFGT_LESS 0x00 + +// Compare Function Range Enable: Enabled or Disabled. +#define ACREN_ENABLED ADC_SC2_ACREN_MASK +#define ACREN_DISABLED 0x00 + +// DMA enable: enabled or disabled. +#define DMAEN_ENABLED ADC_SC2_DMAEN_MASK +#define DMAEN_DISABLED 0x00 + +// Voltage Reference selection for the ADC conversions +// (***not*** the PGA which uses VREFO only). +// VREFH and VREFL (0) , or VREFO (1). + +#define REFSEL_EXT 0x00 +#define REFSEL_ALT 0x01 +#define REFSEL_RES 0x02 /* reserved */ +#define REFSEL_RES_EXT 0x03 /* reserved but defaults to Vref */ + +////ADCSC3 + +// Calibration begin or off +#define CAL_BEGIN ADC_SC3_CAL_MASK +#define CAL_OFF 0x00 + +// Status indicating Calibration failed, or normal success +#define CALF_FAIL ADC_SC3_CALF_MASK +#define CALF_NORMAL 0x00 + +// ADC to continously convert, or do a sinle conversion +#define ADCO_CONTINUOUS ADC_SC3_ADCO_MASK +#define ADCO_SINGLE 0x00 + +// Averaging enabled in the ADC, or not. +#define AVGE_ENABLED ADC_SC3_AVGE_MASK +#define AVGE_DISABLED 0x00 + +// How many to average prior to "interrupting" the MCU? 4, 8, 16, or 32 +#define AVGS_4 0x00 +#define AVGS_8 0x01 +#define AVGS_16 0x02 +#define AVGS_32 0x03 + +////PGA + +// PGA enabled or not? +#define PGAEN_ENABLED ADC_PGA_PGAEN_MASK +#define PGAEN_DISABLED 0x00 + +// Chopper stabilization of the amplifier, or not. +#define PGACHP_CHOP ADC_PGA_PGACHP_MASK +#define PGACHP_NOCHOP 0x00 + +// PGA in low power mode, or normal mode. +#define PGALP_LOW ADC_PGA_PGALP_MASK +#define PGALP_NORMAL 0x00 + +// Gain of PGA. Selectable from 1 to 64. +#define PGAG_1 0x00 +#define PGAG_2 0x01 +#define PGAG_4 0x02 +#define PGAG_8 0x03 +#define PGAG_16 0x04 +#define PGAG_32 0x05 +#define PGAG_64 0x06 + + +#define ADC_STATE_INIT 0 +#define ADC_STATE_CAPTURE_POT_0 1 +#define ADC_STATE_CAPTURE_POT_1 2 +#define ADC_STATE_CAPTURE_BATTERY_LEVEL 3 +#define ADC_STATE_CAPTURE_LINE_SCAN 4 + + +/////////// The above values fit into the structure below to select ADC/PGA +/////////// configuration desired: + +typedef struct adc_cfg { + uint8_t CONFIG1; + uint8_t CONFIG2; + uint16_t COMPARE1; + uint16_t COMPARE2; + uint8_t STATUS2; + uint8_t STATUS3; + uint8_t STATUS1A; + uint8_t STATUS1B; + uint32_t PGA; +} *tADC_ConfigPtr, tADC_Config ; + + +#define CAL_BLK_NUMREC 18 + +typedef struct adc_cal { + + uint16_t OFS; + uint16_t PG; + uint16_t MG; + uint8_t CLPD; + uint8_t CLPS; + uint16_t CLP4; + uint16_t CLP3; + uint8_t CLP2; + uint8_t CLP1; + uint8_t CLP0; + uint8_t dummy; + uint8_t CLMD; + uint8_t CLMS; + uint16_t CLM4; + uint16_t CLM3; + uint8_t CLM2; + uint8_t CLM1; + uint8_t CLM0; +} tADC_Cal_Blk ; + +typedef struct ADC_MemMap { + uint32_t SC1[2]; /**< ADC Status and Control Registers 1, array offset: 0x0, array step: 0x4 */ + uint32_t CFG1; /**< ADC Configuration Register 1, offset: 0x8 */ + uint32_t CFG2; /**< ADC Configuration Register 2, offset: 0xC */ + uint32_t R[2]; /**< ADC Data Result Register, array offset: 0x10, array step: 0x4 */ + uint32_t CV1; /**< Compare Value Registers, offset: 0x18 */ + uint32_t CV2; /**< Compare Value Registers, offset: 0x1C */ + uint32_t SC2; /**< Status and Control Register 2, offset: 0x20 */ + uint32_t SC3; /**< Status and Control Register 3, offset: 0x24 */ + uint32_t OFS; /**< ADC Offset Correction Register, offset: 0x28 */ + uint32_t PG; /**< ADC Plus-Side Gain Register, offset: 0x2C */ + uint32_t MG; /**< ADC Minus-Side Gain Register, offset: 0x30 */ + uint32_t CLPD; /**< ADC Plus-Side General Calibration Value Register, offset: 0x34 */ + uint32_t CLPS; /**< ADC Plus-Side General Calibration Value Register, offset: 0x38 */ + uint32_t CLP4; /**< ADC Plus-Side General Calibration Value Register, offset: 0x3C */ + uint32_t CLP3; /**< ADC Plus-Side General Calibration Value Register, offset: 0x40 */ + uint32_t CLP2; /**< ADC Plus-Side General Calibration Value Register, offset: 0x44 */ + uint32_t CLP1; /**< ADC Plus-Side General Calibration Value Register, offset: 0x48 */ + uint32_t CLP0; /**< ADC Plus-Side General Calibration Value Register, offset: 0x4C */ + uint8_t RESERVED_0[4]; + uint32_t CLMD; /**< ADC Minus-Side General Calibration Value Register, offset: 0x54 */ + uint32_t CLMS; /**< ADC Minus-Side General Calibration Value Register, offset: 0x58 */ + uint32_t CLM4; /**< ADC Minus-Side General Calibration Value Register, offset: 0x5C */ + uint32_t CLM3; /**< ADC Minus-Side General Calibration Value Register, offset: 0x60 */ + uint32_t CLM2; /**< ADC Minus-Side General Calibration Value Register, offset: 0x64 */ + uint32_t CLM1; /**< ADC Minus-Side General Calibration Value Register, offset: 0x68 */ + uint32_t CLM0; /**< ADC Minus-Side General Calibration Value Register, offset: 0x6C */ +} volatile *ADC_MemMapPtr; + + + +/* ADC - Register accessors */ +#define ADC_SC1_REG(base,index) ((base)->SC1[index]) +#define ADC_CFG1_REG(base) ((base)->CFG1) +#define ADC_CFG2_REG(base) ((base)->CFG2) +#define ADC_R_REG(base,index) ((base)->R[index]) +#define ADC_CV1_REG(base) ((base)->CV1) +#define ADC_CV2_REG(base) ((base)->CV2) +#define ADC_SC2_REG(base) ((base)->SC2) +#define ADC_SC3_REG(base) ((base)->SC3) +#define ADC_OFS_REG(base) ((base)->OFS) +#define ADC_PG_REG(base) ((base)->PG) +#define ADC_MG_REG(base) ((base)->MG) +#define ADC_CLPD_REG(base) ((base)->CLPD) +#define ADC_CLPS_REG(base) ((base)->CLPS) +#define ADC_CLP4_REG(base) ((base)->CLP4) +#define ADC_CLP3_REG(base) ((base)->CLP3) +#define ADC_CLP2_REG(base) ((base)->CLP2) +#define ADC_CLP1_REG(base) ((base)->CLP1) +#define ADC_CLP0_REG(base) ((base)->CLP0) +#define ADC_CLMD_REG(base) ((base)->CLMD) +#define ADC_CLMS_REG(base) ((base)->CLMS) +#define ADC_CLM4_REG(base) ((base)->CLM4) +#define ADC_CLM3_REG(base) ((base)->CLM3) +#define ADC_CLM2_REG(base) ((base)->CLM2) +#define ADC_CLM1_REG(base) ((base)->CLM1) +#define ADC_CLM0_REG(base) ((base)->CLM0) + +#define ADC0_BASE_PTR ((ADC_MemMapPtr)0x4003B000u) +/** Array initializer of ADC peripheral base pointers */ +#define ADC_BASE_PTRS { ADC0_BASE_PTR } + + +float _ServoDutyCycleMin; +float _ServoDutyCycleMax; +float _ServoPeriod; + +volatile uint16_t QueuedServo0Val; +volatile uint16_t QueuedServo1Val; + +volatile uint8_t TFC_LineScanDataReady; +volatile uint8_t *LineScanImage0WorkingBuffer; +volatile uint8_t *LineScanImage1WorkingBuffer; + +volatile uint8_t LineScanImage0Buffer[2][128]; +volatile uint8_t LineScanImage1Buffer[2][128]; +volatile uint8_t LineScanWorkingBuffer; + +volatile uint8_t PotADC_Value[2]; +volatile uint8_t BatSenseADC_Value; +volatile uint8_t CurrentADC_State; +volatile uint8_t CurrentLineScanPixel; +volatile uint8_t CurrentLineScanChannel; +volatile uint32_t TFC_ServoTicker; +volatile uint8_t * TFC_LineScanCameraData[2]; + +void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle); +void TFC_InitLineScanCamera(); +uint8_t ADC_Cal(ADC_MemMapPtr adcmap); +void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr); +void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk); +void TFC_InitADC0(); +void TFC_InitADC_System(); +void TFC_GPIO_Init(); +void ADC0_Handler(); +void TPM1_Handler(); + + +void TFC_Init() +{ + + TFC_GPIO_Init(); + + TFC_InitADC_System(); // Always call this before the Servo init function.... The IRQ for the Servo code modifies ADC registers and the clocks need enable to the ADC peripherals 1st! + + TFC_InitLineScanCamera(); + + TFC_InitServos(SERVO_MIN_PULSE_WIDTH_DEFAULT , SERVO_MAX_PULSE_WIDTH_DEFAULT, SERVO_DEFAULT_PERIOD); + + TFC_ServoTicker = 0; + + TFC_InitMotorPWM(FTM0_DEFAULT_SWITCHING_FREQUENCY); + +} + + +void TFC_GPIO_Init() +{ + + //enable Clocks to all ports + + SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK; + + //Setup Pins as GPIO + PORTE->PCR[21] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; + PORTE->PCR[20] = PORT_PCR_MUX(1); + + //Port for Pushbuttons + PORTC->PCR[13] = PORT_PCR_MUX(1); + PORTC->PCR[17] = PORT_PCR_MUX(1); + + + //Ports for DIP Switches + PORTE->PCR[2] = PORT_PCR_MUX(1); + PORTE->PCR[3] = PORT_PCR_MUX(1); + PORTE->PCR[4] = PORT_PCR_MUX(1); + PORTE->PCR[5] = PORT_PCR_MUX(1); + + //Ports for LEDs + PORTB->PCR[8] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; + PORTB->PCR[9] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; + PORTB->PCR[10] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; + PORTB->PCR[11] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; + + + //Setup the output pins + PTE->PDDR = TFC_HBRIDGE_EN_LOC; + PTB->PDDR = TFC_BAT_LED0_LOC | TFC_BAT_LED1_LOC | TFC_BAT_LED2_LOC | TFC_BAT_LED3_LOC; + + TFC_SetBatteryLED(0); + TFC_HBRIDGE_DISABLE; +} + +void TFC_SetBatteryLED(uint8_t Value) +{ + if(Value & 0x01) + TFC_BAT_LED0_ON; + else + TFC_BAT_LED0_OFF; + + if(Value & 0x02) + TFC_BAT_LED1_ON; + else + TFC_BAT_LED1_OFF; + + if(Value & 0x04) + TFC_BAT_LED2_ON; + else + TFC_BAT_LED2_OFF; + + if(Value & 0x08) + TFC_BAT_LED3_ON; + else + TFC_BAT_LED3_OFF; +} + +uint8_t TFC_GetDIP_Switch() +{ + uint8_t DIP_Val=0; + + DIP_Val = (PTE->PDIR>>2) & 0xF; + + return DIP_Val; +} + +uint8_t TFC_ReadPushButton(uint8_t Index) +{ + if(Index == 0) { + return TFC_PUSH_BUTTON_0_PRESSED; + } else { + return TFC_PUSH_BUTTON_1_PRESSED; + } +} + +extern "C" void TPM1_IRQHandler() +{ + //Clear the overflow mask if set. According to the reference manual, we clear by writing a logic one! + if(TPM1->SC & TPM_SC_TOF_MASK) + TPM1->SC |= TPM_SC_TOF_MASK; + + //Dump the queued values to the timer channels + TPM1->CONTROLS[0].CnV = QueuedServo0Val; + TPM1->CONTROLS[1].CnV = QueuedServo1Val; + + + //Prime the next ADC capture cycle + TAOS_SI_HIGH; + //Prime the ADC pump and start capturing POT 0 + CurrentADC_State = ADC_STATE_CAPTURE_POT_0; + + ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux + ADC0->SC1[0] = TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; //Start the State machine at POT0 + + //Flag that a new cervo cycle will start + if (TFC_ServoTicker < 0xffffffff)//if servo tick less than max value, count up... + TFC_ServoTicker++; + +} + + +void TFC_InitServos(float PulseWidthMin, float PulseWidthMax, float ServoPeriod) +{ + + _ServoPeriod = ServoPeriod; + _ServoDutyCycleMin = PulseWidthMin/ServoPeriod; + _ServoDutyCycleMax = PulseWidthMax/ServoPeriod; + + //Clock Setup for the TPM requires a couple steps. + SIM->SCGC6 &= ~SIM_SCGC6_TPM1_MASK; + //1st, set the clock mux + //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 + SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) + SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); + SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); + + //Enable the Clock to the FTM0 Module + //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 + SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK; + + //The TPM Module has Clock. Now set up the peripheral + + //Blow away the control registers to ensure that the counter is not running + TPM1->SC = 0; + TPM1->CONF = 0; + + //While the counter is disabled we can setup the prescaler + + TPM1->SC = TPM_SC_PS(FTM1_CLK_PRESCALE); + TPM1->SC |= TPM_SC_TOIE_MASK; //Enable Interrupts for the Timer Overflow + + //Setup the mod register to get the correct PWM Period + + TPM1->MOD = (SystemCoreClock/(1<<(FTM1_CLK_PRESCALE))) * _ServoPeriod; + //Setup Channels 0 and 1 + + TPM1->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; + TPM1->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; + + + //Set the Default duty cycle to servo neutral + TFC_SetServo(0, 0.0); + TFC_SetServo(1, 0.0); + + //Enable the TPM COunter + TPM1->SC |= TPM_SC_CMOD(1); + + //Enable TPM1 IRQ on the NVIC + + //NVIC_SetVector(TPM1_IRQn,(uint32_t)TPM1_Handler); + NVIC_EnableIRQ(TPM1_IRQn); + + //Enable the FTM functions on the the port + + PORTB->PCR[0] = PORT_PCR_MUX(3); + PORTB->PCR[1] = PORT_PCR_MUX(3); + +} + + +void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle) +{ + switch(ServoNumber) { + default: + case 0: + + QueuedServo0Val = TPM1->MOD * DutyCycle; + + break; + + case 1: + + QueuedServo1Val = TPM1->MOD * DutyCycle; + + break; + } +} + +void TFC_SetServo(uint8_t ServoNumber, float Position) +{ + TFC_SetServoDutyCycle(ServoNumber , + ((Position + 1.0)/2) * ((_ServoDutyCycleMax - _ServoDutyCycleMin)+_ServoDutyCycleMin) ); + +} + +//******************************************************************************************************** +//******************************************************************************************************** +//******************************************************************************************************** +// _____ _____ ______ _ _ _ _ _____ _______ _____ ____ _ _ _____ +// /\ | __ \ / ____| | ____| | | | \ | |/ ____|__ __|_ _/ __ \| \ | |/ ____| +// / \ | | | | | | |__ | | | | \| | | | | | || | | | \| | (___ +// / /\ \ | | | | | | __| | | | | . ` | | | | | || | | | . ` |\___ \ +// / ____ \| |__| | |____ | | | |__| | |\ | |____ | | _| || |__| | |\ |____) | +// /_/ \_\_____/ \_____| |_| \____/|_| \_|\_____| |_| |_____\____/|_| \_|_____/ +// ******************************************************************************************************** +// ******************************************************************************************************** +// ******************************************************************************************************** + + + + + +uint8_t ADC_Cal(ADC_MemMapPtr adcmap) +{ + + uint16_t cal_var; + + ADC_SC2_REG(adcmap) &= ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0); + ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing + ADC_SC3_REG(adcmap) |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) ); // Turn averaging ON and set at max value ( 32 ) + + + ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ; // Start CAL + while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end + + if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL ) { + return(1); // Check for Calibration fail error and return + } + // Calculate plus-side calibration + cal_var = 0x00; + + cal_var = ADC_CLP0_REG(adcmap); + cal_var += ADC_CLP1_REG(adcmap); + cal_var += ADC_CLP2_REG(adcmap); + cal_var += ADC_CLP3_REG(adcmap); + cal_var += ADC_CLP4_REG(adcmap); + cal_var += ADC_CLPS_REG(adcmap); + + cal_var = cal_var/2; + cal_var |= 0x8000; // Set MSB + + ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var); + + + // Calculate minus-side calibration + cal_var = 0x00; + + cal_var = ADC_CLM0_REG(adcmap); + cal_var += ADC_CLM1_REG(adcmap); + cal_var += ADC_CLM2_REG(adcmap); + cal_var += ADC_CLM3_REG(adcmap); + cal_var += ADC_CLM4_REG(adcmap); + cal_var += ADC_CLMS_REG(adcmap); + + cal_var = cal_var/2; + + cal_var |= 0x8000; // Set MSB + + ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var); + + ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */ + + return(0); +} + + +void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr) +{ + ADC_CFG1_REG(adcmap) = ADC_CfgPtr->CONFIG1; + ADC_CFG2_REG(adcmap) = ADC_CfgPtr->CONFIG2; + ADC_CV1_REG(adcmap) = ADC_CfgPtr->COMPARE1; + ADC_CV2_REG(adcmap) = ADC_CfgPtr->COMPARE2; + ADC_SC2_REG(adcmap) = ADC_CfgPtr->STATUS2; + ADC_SC3_REG(adcmap) = ADC_CfgPtr->STATUS3; +//ADC_PGA_REG(adcmap) = ADC_CfgPtr->PGA; + ADC_SC1_REG(adcmap,A)= ADC_CfgPtr->STATUS1A; + ADC_SC1_REG(adcmap,B)= ADC_CfgPtr->STATUS1B; +} + + +void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk) +{ + blk->OFS = ADC_OFS_REG(adcmap); + blk->PG = ADC_PG_REG(adcmap); + blk->MG = ADC_MG_REG(adcmap); + blk->CLPD = ADC_CLPD_REG(adcmap); + blk->CLPS = ADC_CLPS_REG(adcmap); + blk->CLP4 = ADC_CLP4_REG(adcmap); + blk->CLP3 = ADC_CLP3_REG(adcmap); + blk->CLP2 = ADC_CLP2_REG(adcmap); + blk->CLP1 = ADC_CLP1_REG(adcmap); + blk->CLP0 = ADC_CLP0_REG(adcmap); + blk->CLMD = ADC_CLMD_REG(adcmap); + blk->CLMS = ADC_CLMS_REG(adcmap); + blk->CLM4 = ADC_CLM4_REG(adcmap); + blk->CLM3 = ADC_CLM3_REG(adcmap); + blk->CLM2 = ADC_CLM2_REG(adcmap); + blk->CLM1 = ADC_CLM1_REG(adcmap); + blk->CLM0 = ADC_CLM0_REG(adcmap); + +} + + +void TFC_InitADC0() +{ + tADC_Config Master_Adc0_Config; + + + SIM->SCGC6 |= (SIM_SCGC6_ADC0_MASK); + + //Lets calibrate the ADC. 1st setup how the channel will be used. + + + Master_Adc0_Config.CONFIG1 = ADLPC_NORMAL //No low power mode + | ADC_CFG1_ADIV(ADIV_4) //divide input by 4 + | ADLSMP_LONG //long sample time + | ADC_CFG1_MODE(MODE_8)//single ended 8-bit conversion + | ADC_CFG1_ADICLK(ADICLK_BUS); + + Master_Adc0_Config.CONFIG2 = MUXSEL_ADCA // select the A side of the ADC channel. + | ADACKEN_DISABLED + | ADHSC_HISPEED + | ADC_CFG2_ADLSTS(ADLSTS_2);//Extra long sample Time (20 extra clocks) + + + Master_Adc0_Config.COMPARE1 = 00000; // Comparators don't matter for calibration + Master_Adc0_Config.COMPARE1 = 0xFFFF; + + Master_Adc0_Config.STATUS2 = ADTRG_HW //hardware triggers for calibration + | ACFE_DISABLED //disable comparator + | ACFGT_GREATER + | ACREN_ENABLED + | DMAEN_DISABLED //Disable DMA + | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference + + Master_Adc0_Config.STATUS3 = CAL_OFF + | ADCO_SINGLE + | AVGE_ENABLED + | ADC_SC3_AVGS(AVGS_4); + + Master_Adc0_Config.PGA = 0; // Disable the PGA + + + // Configure ADC as it will be used, but because ADC_SC1_ADCH is 31, + // the ADC will be inactive. Channel 31 is just disable function. + // There really is no channel 31. + + Master_Adc0_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31); + + + ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config); // config ADC + + // Calibrate the ADC in the configuration in which it will be used: + ADC_Cal(ADC0_BASE_PTR); // do the calibration + + + Master_Adc0_Config.STATUS2 = ACFE_DISABLED //disable comparator + | ACFGT_GREATER + | ACREN_ENABLED + | DMAEN_DISABLED //Disable DMA + | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference + + Master_Adc0_Config.STATUS3 = CAL_OFF + | ADCO_SINGLE; + + + + ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config); +} + + +void TFC_InitADC_System() +{ + + TFC_InitADC0(); + + + //All Adc processing of the Pots and linescan will be done in the ADC0 IRQ! + //A state machine will scan through the channels. + //This is done to automate the linescan capture on Channel 0 to ensure that timing is very even + CurrentADC_State = ADC_STATE_INIT; + + //The pump will be primed with the TPM1 interrupt. upon timeout/interrupt it will set the SI signal high + //for the camera and then start the conversions for the pots. + + // NVIC_SetVector(ADC0_IRQn,(uint32_t)ADC0_Handler); + NVIC_EnableIRQ(ADC0_IRQn); + +} + +extern "C" void ADC0_IRQHandler() +{ + uint8_t Junk; + + switch(CurrentADC_State) { + default: + Junk = ADC0->R[0]; + break; + + case ADC_STATE_CAPTURE_POT_0: + + PotADC_Value[0] = ADC0->R[0]; + ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux + ADC0->SC1[0] = TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK; + CurrentADC_State = ADC_STATE_CAPTURE_POT_1; + + break; + + case ADC_STATE_CAPTURE_POT_1: + + PotADC_Value[1] = ADC0->R[0]; + ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux + ADC0->SC1[0] = TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK; + CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL; + + break; + + case ADC_STATE_CAPTURE_BATTERY_LEVEL: + + BatSenseADC_Value = ADC0->R[0]; + + //Now we will start the sequence for the Linescan camera + + TAOS_CLK_HIGH; + + for(Junk = 0; Junk<50; Junk++) { + } + + TAOS_SI_LOW; + + + CurrentLineScanPixel = 0; + CurrentLineScanChannel = 0; + CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN; + ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux + ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; + + break; + + case ADC_STATE_CAPTURE_LINE_SCAN: + + if(CurrentLineScanPixel<129) { + if(CurrentLineScanChannel == 0) { + LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0]; + ADC0->SC1[0] = TFC_LINESCAN1_ADC_CHANNEL | ADC_SC1_AIEN_MASK; + CurrentLineScanChannel = 1; + + } else { + LineScanImage1WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0]; + ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; + CurrentLineScanChannel = 0; + CurrentLineScanPixel++; + + TAOS_CLK_LOW; + for(Junk = 0; Junk<50; Junk++) { + } + TAOS_CLK_HIGH; + + } + + } else { + // done with the capture sequence. we can wait for the PIT0 IRQ to restart + + TAOS_CLK_HIGH; + + for(Junk = 0; Junk<50; Junk++) { + } + + TAOS_CLK_LOW; + CurrentADC_State = ADC_STATE_INIT; + + //swap the buffer + + if(LineScanWorkingBuffer == 0) { + LineScanWorkingBuffer = 1; + + LineScanImage0WorkingBuffer = &LineScanImage0Buffer[1][0]; + LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0]; + + TFC_LineScanCameraData[0] = &LineScanImage0Buffer[0][0]; + TFC_LineScanCameraData[1] = &LineScanImage1Buffer[0][0]; + } else { + LineScanWorkingBuffer = 0; + LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0]; + LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0]; + + TFC_LineScanCameraData[0] = &LineScanImage0Buffer[1][0]; + TFC_LineScanCameraData[1] = &LineScanImage1Buffer[1][0]; + } + + TFC_LineScanDataReady++; + } + + break; + } + +} + +void TFC_InitLineScanCamera() +{ + SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTD_MASK; //Make sure the clock is enabled for PORTE; + PORTE->PCR[1] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for the CLOCK Signal + PORTD->PCR[7] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for SI signal + + PORTD->PCR[5] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input + PORTD->PCR[6] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input + + //Make sure the Clock and SI pins are outputs + PTD->PDDR |= (1<<7); + PTE->PDDR |= (1<<1); + + TAOS_CLK_LOW; + TAOS_SI_LOW; + + LineScanWorkingBuffer = 0; + + LineScanImage0WorkingBuffer = &LineScanImage0Buffer[LineScanWorkingBuffer][0]; + LineScanImage1WorkingBuffer = &LineScanImage1Buffer[LineScanWorkingBuffer][0]; + + TFC_LineScanCameraData[0] = &LineScanImage0Buffer[1][0]; + TFC_LineScanCameraData[1] = &LineScanImage1Buffer[1][0]; +} + + + + + +/** Initialized TPM0 to be used for generating PWM signals for the the dual drive motors. This method is called in the TFC constructor with a default value of 4000.0Hz +* +* @param SwitchingFrequency PWM Switching Frequency in floating point format. Pick something between 1000 and 9000. Maybe you can modulate it and make a tune. +*/ +void TFC_InitMotorPWM(float SwitchingFrequency) +{ + //Clock Setup for the TPM requires a couple steps. + + + //1st, set the clock mux + //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 + // SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) + // SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK); + // SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1); //We want the MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012) + + + //Enable the Clock to the FTM0 Module + //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012 + SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK; + + //The TPM Module has Clock. Now set up the peripheral + + //Blow away the control registers to ensure that the counter is not running + TPM0->SC = 0; + TPM0->CONF = 0; + + //While the counter is disabled we can setup the prescaler + + TPM0->SC = TPM_SC_PS(FTM0_CLK_PRESCALE); + + //Setup the mod register to get the correct PWM Period + + TPM0->MOD = (uint32_t)((float)(FTM0_CLOCK/(1<<FTM0_CLK_PRESCALE))/SwitchingFrequency); + + //Setup Channels 0,1,2,3 + TPM0->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; + TPM0->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output; + TPM0->CONTROLS[2].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK; + TPM0->CONTROLS[3].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output; + + //Enable the Counter + + //Set the Default duty cycle to 50% duty cycle + TFC_SetMotorPWM(0.0,0.0); + + //Enable the TPM COunter + TPM0->SC |= TPM_SC_CMOD(1); + + //Enable the FTM functions on the the port + PORTC->PCR[1] = PORT_PCR_MUX(4); + PORTC->PCR[2] = PORT_PCR_MUX(4); + PORTC->PCR[3] = PORT_PCR_MUX(4); + PORTC->PCR[4] = PORT_PCR_MUX(4); + +} + +void TFC_SetMotorPWM(float MotorA , float MotorB) +{ + if(MotorA>1.0) + MotorA = 1.0; + else if(MotorA<-1.0) + MotorA = -1.0; + + if(MotorB>1.0) + MotorB = 1.0; + else if(MotorB<-1.0) + MotorB = -1.0; + + TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0)); + TPM0->CONTROLS[3].CnV = TPM0->CONTROLS[2].CnV; + TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorB + 1.0)/2.0)); + TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV; + +} + +//Pot Reading is Scaled to return a value of -1.0 to 1.0 +float TFC_ReadPot(uint8_t Channel) +{ + if(Channel == 0) + return ((float)PotADC_Value[0]/-127.5)+1.0; + else + return ((float)PotADC_Value[1]/-127.5)+1.0;; +} + +float TFC_ReadBatteryVoltage() +{ + return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFC.h Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,238 @@ + +#include "mbed.h" + +/** @file test.h*/ + +/** + * @defgroup FRDM-TFC_API FRDM-TFC_API + * + * @{ + */ + + +/** + +@addtogroup FRDM-TFC_API + +@{ + +Resources used by the TFC Library\n + +I/O:\n +-------------------------------------------------------------------------------------------------\n + + PTB0 (Servo Channel 0 - TPM1)\n + PTB1 (Servo Channel 1 - TPM1)\n +\n + PTB8 (Battery LED0)\n + PTB9 (Battery LED1)\n + PTB10 (Battery LED2)\n + PTB11 (Battery LED3)\n +\n + PTD7 (Camera SI)\n + PTE0 (Camera CLK)\n + PTD5 (Camera A0 - ADC_SE6b)\n + PTD6 (Camera A1 - ADC_SE7b)\n +\n + PTE2 DIP Switch 0\n + PTE3 DIP Switch 1\n + PTE4 DIP Switch 2\n + PTE5 DIP Switch 3\n + + PTC13 Pushbutton SW1\n + PTC17 Pushbutton SW2\n + + PTC3 H-Bridge A - 1 FTM0_CH3\n + PTC4 H-Bridge A - 2 FTM0_CH4\n + PTC1 H-Bridge B - 1 FTM0_CH1\n + PTC2 H-Bridge B - 2 FTM0_CH2\n + + PTE21 H-Bridge Enable\n + PTE20 H-Bridge Fault\n + + PTE23 H-Bridge A - IFB\n + PTE22 H-Bridge B - IFB\n + + } +*/ + + + +#ifndef _TFC_H +#define _TFC_H + +#define TFC_HBRIDGE_EN_LOC (uint32_t)(1<<21) +#define TFC_HBRIDGE_FAULT_LOC (uint32_t)(1<<20) + +#define TFC_HBRIDGE_ENABLE PTE->PSOR = TFC_HBRIDGE_EN_LOC +#define TFC_HBRIDGE_DISABLE PTE->PCOR = TFC_HBRIDGE_EN_LOC + +#define TFC_DIP_SWITCH0_LOC ((uint32_t)(1<<2)) +#define TFC_DIP_SWITCH1_LOC ((uint32_t)(1<<3)) +#define TFC_DIP_SWITCH2_LOC ((uint32_t)(1<<4)) +#define TFC_DIP_SWITCH3_LOC ((uint32_t)(1<<5)) + +#define TFC_PUSH_BUTT0N0_LOC ((uint32_t)(1<<13)) +#define TFC_PUSH_BUTT0N1_LOC ((uint32_t)(1<<17)) + +#define TFC_BAT_LED0_LOC ((uint32_t)(1<<11)) +#define TFC_BAT_LED1_LOC ((uint32_t)(1<<10)) +#define TFC_BAT_LED2_LOC ((uint32_t)(1<<9)) +#define TFC_BAT_LED3_LOC ((uint32_t)(1<<8)) + +#define TAOS_CLK_HIGH PTE->PSOR = (1<<1) +#define TAOS_CLK_LOW PTE->PCOR = (1<<1) +#define TAOS_SI_HIGH PTD->PSOR = (1<<7) +#define TAOS_SI_LOW PTD->PCOR = (1<<7) + + +/** + +@addtogroup FRDM-TFC_API +@{ +*/ + +/**Macro to turn on LED 0 in the battery indicator array*/ +#define TFC_BAT_LED0_ON PTB->PSOR = TFC_BAT_LED0_LOC +/** Macro to turn on LED 1 in the battery indicator array*/ +#define TFC_BAT_LED1_ON PTB->PSOR = TFC_BAT_LED1_LOC +/** Macro to turn on LED 2 in the battery indicator array*/ +#define TFC_BAT_LED2_ON PTB->PSOR = TFC_BAT_LED2_LOC +/** Macro to turn on LED 3 in the battery indicator array*/ +#define TFC_BAT_LED3_ON PTB->PSOR = TFC_BAT_LED3_LOC + + +/** Macro to turn off LED 0 in the battery indicator array*/ +#define TFC_BAT_LED0_OFF PTB->PCOR = TFC_BAT_LED0_LOC +/** Macro to turn off LED 1 in the battery indicator array*/ +#define TFC_BAT_LED1_OFF PTB->PCOR = TFC_BAT_LED1_LOC +/** Macro to turn off LED 2 in the battery indicator array*/ +#define TFC_BAT_LED2_OFF PTB->PCOR = TFC_BAT_LED2_LOC +/** Macro to turn off LED 3 in the battery indicator array*/ +#define TFC_BAT_LED3_OFF PTB->PCOR = TFC_BAT_LED3_LOC + + +/** Macro to toggle LED 0 in the battery indicator array*/ +#define TFC_BAT_LED0_TOGGLE PTB->PTOR = TFC_BAT_LED0_LOC +/** Macro to toggle LED 1 in the battery indicator array*/ +#define TFC_BAT_LED1_TOGGLE PTB->PTOR = TFC_BAT_LED1_LOC +/** Macro to toggle LED 2 in the battery indicator array*/ +#define TFC_BAT_LED2_TOGGLE PTB->PTOR = TFC_BAT_LED2_LOC +/** Macro to toggle LED 3 in the battery indicator array*/ +#define TFC_BAT_LED3_TOGGLE PTB->PTOR = TFC_BAT_LED3_LOC + + +/** Macro to read the state of the pushbutton SW1*/ +#define TFC_PUSH_BUTTON_0_PRESSED ((PTC->PDIR&TFC_PUSH_BUTT0N0_LOC)>0) +/** Macro to read the state of the pushbutton SW1*/ +#define TFC_PUSH_BUTTON_1_PRESSED ((PTC->PDIR&TFC_PUSH_BUTT0N1_LOC)>0) + +/** Macro to read the state of switch 0 in the 4 position DIP switch*/ +#define TFC_DIP_SWITCH_0_ON ((TFC_GetDIP_Switch()&0x01)>0) + +/** Macro to read the state of switch 1 in the 4 position DIP switch*/ +#define TFC_DIP_SWITCH_1_ON ((TFC_GetDIP_Switch()&0x02)>0) + +/** Macro to read the state of switch 2 in the 4 position DIP switch*/ +#define TFC_DIP_SWITCH_2_ON ((TFC_GetDIP_Switch()&0x04)>0) + +/** Macro to read the state of switch 3 in the 4 position DIP switch*/ +#define TFC_DIP_SWITCH_3_ON ((TFC_GetDIP_Switch()&0x08)>0) + + +/** Initialized the TFC API. Call before using any other API calls. +* +*/ +void TFC_Init(); + +/** ServoTicker will increment once every servo cycle. +* It can be used to synchronize events to the start of a servo cycle. ServoTicker is a volatile uint32_t and is updated in the TPM1 overlflow interrupt. This means you will see ServoTicker increment on the rising edge of the servo PWM signal +* +*/ +extern volatile uint32_t TFC_ServoTicker; + + +/** Gets the state of the 4-positiomn DIP switch on the FRDM-TFC +* +* @returns The lower 4-bits of the return value map to the 4-bits of the DIP switch +*/ +uint8_t TFC_GetDIP_Switch(); + + +/** Reads the state of the pushbuttons (SW1, SW2) on the FRDM-TFC +* @param Index Selects the pushbutton (0 for SW1 and 1 for SW2) +* @returns A non-zero value if the button is pushed +*/ +uint8_t TFC_ReadPushButton(uint8_t Index); + + +/** Controls the 4 battery level LEDs on the FRDM-TFC boards. +* +* @param Value The lower 4-bits of the parameter maps to the 4 LEDs. +*/ +void TFC_SetBatteryLED(uint8_t Value); + + +/** Sets the servo channels +* +* @param ServoNumber Which servo channel on the FRDM-TFC to use (0 or 1). 0 is the default channel for steering +* @param Position Angle setting for servo in a normalized (-1.0 to 1.0) form. The range of the servo can be changed with the InitServos function. +* This is called in the TFC constructor with some useful default values--> 20mSec period, 0.5mS min and 2.0mSec max. you may need to adjust these for your own particular setup. +*/ +void TFC_SetServo(uint8_t ServoNumber, float Position); + +/** Initializes TPM for the servoes. It also sets the max and min ranges +* +* @param ServoPulseWidthMin Minimum pulse width (in seconds) for the servo. The value of -1.0 in SetServo is mapped to this pulse width. I.E. .001 +* @param ServoPulseWidthMax Maximum pulse width (in seconds) for the servo. The value of +1.0 in SetServo is mapped to this pulse width. I.E. .002 +* @param ServoPeriod Period of the servo pulses (in seconds). I.e. .020 for 20mSec +*/ + +void TFC_InitServos(float ServoPulseWidthMin, float ServoPulseWidthMax, float ServoPeriod); + + +/** Initialized TPM0 to be used for generating PWM signals for the the dual drive motors. This method is called in the TFC constructor with a default value of 4000.0Hz +* +* @param SwitchingFrequency PWM Switching Frequency in floating point format. Pick something between 1000 and 9000. Maybe you can modulate it and make a tune. +*/ +void TFC_InitMotorPWM(float SwitchingFrequency); + +/** Sets the PWM value for each motor. +* +* @param MotorA The PWM value for HBridgeA. The value is normalized to the floating point range of -1.0 to +1.0. -1.0 is 0% (Full Reverse on the H-Bridge) and 1.0 is 100% (Full Forward on the H-Bridge) +* @param MotorB The PWM value for HBridgeB. The value is normalized to the floating point range of -1.0 to +1.0. -1.0 is 0% (Full Reverse on the H-Bridge) and 1.0 is 100% (Full Forward on the H-Bridge) +*/ +void TFC_SetMotorPWM(float MotorA ,float MotorB); + +/** Reads the potentiometers +* +* @param Channel Selects which pot is read. I.e. 0 for POT0 or 1 for POT1 +* @returns Pot value from -1.0 to 1.0 +*/ +float TFC_ReadPot(uint8_t Channel); + +/** Gets the current battery voltage +* +* @returns Battery voltage in floating point form. +*/ +float TFC_ReadBatteryVoltage(); + + +/** Pointer to two channels of line scan camera data. Each channel is 128 points of uint8_t's. Note that the underlying implementation is ping-pong buffer These pointers will point to the +*inactive buffer. +* +*/ + +extern volatile uint8_t * TFC_LineScanCameraData[2]; + +/** This flag will increment when a new frame is ready. Check for a non zero value (and reset to zero!) when you want to read the camera(s) +* +*/ + +extern volatile uint8_t TFC_LineScanCameraDataReady; + + +/** @} */ + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,9 @@ +#include "CarAPI.h" + +int main() { + init(); + + // your code here + + finish(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Aug 22 20:50:08 2013 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9c8f0e3462fb \ No newline at end of file