Fork of the official library for the FRDM-TFC shield to add measurement of H-bridge sense currents

Dependents:   telemetry_demo_FRDM-TFC

Fork of FRDM-TFC by Eli Hughes

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TFC.cpp Source File

TFC.cpp

00001 #include "mbed.h"
00002 #include "TFC.h"
00003 
00004 #define FTM1_CLK_PRESCALE                                                            6// Prescale Selector value - see comments in Status Control (SC) section for more details
00005 #define SERVO_DEFAULT_PERIOD                                                   (float)(.020)   // Desired Frequency of PWM Signal - Here 50Hz => 20ms period
00006 // use these to dial in servo steering to your particular servo
00007 #define SERVO_MIN_PULSE_WIDTH_DEFAULT                                          (float)(.00095)  // The number here should be be *pulse width* in seconds to move servo to its left limit
00008 #define SERVO_MAX_PULSE_WIDTH_DEFAULT                                          (float)(.00160)  // The number here should be be *pulse width* in seconds to move servo to its left limit 
00009 
00010 
00011 #define FTM0_CLOCK                                             (SystemCoreClock/2)
00012 #define FTM0_CLK_PRESCALE                                      (0)  // Prescale Selector value - see comments in Status Control (SC) section for more details
00013 #define FTM0_DEFAULT_SWITCHING_FREQUENCY                      (4000.0)
00014 
00015 #define ADC_MAX_CODE    (4095)
00016 
00017 #define TAOS_CLK_HIGH  PTE->PSOR = (1<<1)
00018 #define TAOS_CLK_LOW   PTE->PCOR = (1<<1)
00019 #define TAOS_SI_HIGH   PTD->PSOR = (1<<7)
00020 #define TAOS_SI_LOW    PTD->PCOR = (1<<7)
00021 
00022 #define ADC_STATE_INIT                          0
00023 #define ADC_STATE_CAPTURE_POT_0                 1
00024 #define ADC_STATE_CAPTURE_POT_1                 2
00025 #define ADC_STATE_CAPTURE_BATTERY_LEVEL         3
00026 #define ADC_STATE_CAPTURE_LINE_SCAN             4
00027 #define ADC_STATE_CAPTURE_I_HBRIDGE_A           5
00028 #define ADC_STATE_CAPTURE_I_HBRIDGE_B           6
00029 
00030 #define TFC_POT_0_ADC_CHANNEL       13
00031 #define TFC_POT_1_ADC_CHANNEL       12
00032 #define TFC_BAT_SENSE_CHANNEL       4
00033 #define TFC_LINESCAN0_ADC_CHANNEL   6 // Mux B
00034 #define TFC_LINESCAN1_ADC_CHANNEL   7 // Mux B
00035 // RAJOUTER UN CHANNEL ICI
00036 #define TFC_I_HBRIDGE_0_SENSE_ADC_CHANNEL 7 // Mux A
00037 #define TFC_I_HBRIDGE_1_SENSE_ADC_CHANNEL 3 // Mux A
00038 
00039 
00040 #define ADC0_irq_no   57
00041 #define ADC1_irq_no   58
00042 
00043 #define ADC0_CHANA    19                                    // set to desired ADC0 channel trigger A    
00044 #define ADC0_CHANB    20                                    // set to desired ADC0 channel trigger B    
00045 
00046 #define ADC1_CHANA    20                                    // set to desired ADC1 channel trigger A  20 defaults to potentiometer in TWRK60     
00047 #define ADC1_CHANB    20                                    // set to desired ADC1 channel trigger B
00048 
00049 #define ADC0_DLYA     0x2000                                // ADC0 trigger A delay 
00050 #define ADC0_DLYB     0x4000                                // ADC0 trigger B delay 
00051 #define ADC1_DLYA     0x6000                                // ADC1 trigger A delay
00052 #define ADC1_DLYB     0x7fff                                // ADC1 trigger B delay 
00053 
00054 
00055 #define ADC0A_DONE   0x01
00056 #define ADC0B_DONE   0x02
00057 #define ADC1A_DONE   0x04
00058 #define ADC1B_DONE   0x08
00059 
00060 
00061 // Bit shifting of bitfiled is already taken into account so
00062 // bitfiled values are always represented as relative to their position.
00063 
00064 /************************* #Defines ******************************************/
00065 
00066 #define A                 0x0
00067 #define B                 0x1
00068 
00069 /////// NOTE: the following defines relate to the ADC register definitions
00070 /////// and the content follows the reference manual, using the same symbols.
00071 
00072 
00073 //// ADCSC1 (register)
00074 
00075 // Conversion Complete (COCO) mask
00076 #define COCO_COMPLETE     ADC_SC1_COCO_MASK
00077 #define COCO_NOT          0x00
00078 
00079 // ADC interrupts: enabled, or disabled.
00080 #define AIEN_ON           ADC_SC1_AIEN_MASK
00081 #define AIEN_OFF          0x00
00082 
00083 // Differential or Single ended ADC input
00084 #define DIFF_SINGLE       0x00
00085 #define DIFF_DIFFERENTIAL ADC_SC1_DIFF_MASK
00086 
00087 //// ADCCFG1
00088 
00089 // Power setting of ADC
00090 #define ADLPC_LOW         ADC_CFG1_ADLPC_MASK
00091 #define ADLPC_NORMAL      0x00
00092 
00093 // Clock divisor
00094 #define ADIV_1            0x00
00095 #define ADIV_2            0x01
00096 #define ADIV_4            0x02
00097 #define ADIV_8            0x03
00098 
00099 // Long samle time, or Short sample time
00100 #define ADLSMP_LONG       ADC_CFG1_ADLSMP_MASK
00101 #define ADLSMP_SHORT      0x00
00102 
00103 // How many bits for the conversion?  8, 12, 10, or 16 (single ended).
00104 #define MODE_8            0x00
00105 #define MODE_12           0x01
00106 #define MODE_10           0x02
00107 #define MODE_16           0x03
00108 
00109 
00110 
00111 // ADC Input Clock Source choice? Bus clock, Bus clock/2, "altclk", or the
00112 //                                ADC's own asynchronous clock for less noise
00113 #define ADICLK_BUS        0x00
00114 #define ADICLK_BUS_2      0x01
00115 #define ADICLK_ALTCLK     0x02
00116 #define ADICLK_ADACK      0x03
00117 
00118 //// ADCCFG2
00119 
00120 // Select between B or A channels
00121 #define MUXSEL_ADCB       ADC_CFG2_MUXSEL_MASK
00122 #define MUXSEL_ADCA       0x00
00123 
00124 // Ansync clock output enable: enable, or disable the output of it
00125 #define ADACKEN_ENABLED   ADC_CFG2_ADACKEN_MASK
00126 #define ADACKEN_DISABLED  0x00
00127 
00128 // High speed or low speed conversion mode
00129 #define ADHSC_HISPEED     ADC_CFG2_ADHSC_MASK
00130 #define ADHSC_NORMAL      0x00
00131 
00132 // Long Sample Time selector: 20, 12, 6, or 2 extra clocks for a longer sample time
00133 #define ADLSTS_20          0x00
00134 #define ADLSTS_12          0x01
00135 #define ADLSTS_6           0x02
00136 #define ADLSTS_2           0x03
00137 
00138 ////ADCSC2
00139 
00140 // Read-only status bit indicating conversion status
00141 #define ADACT_ACTIVE       ADC_SC2_ADACT_MASK
00142 #define ADACT_INACTIVE     0x00
00143 
00144 // Trigger for starting conversion: Hardware trigger, or software trigger.
00145 // For using PDB, the Hardware trigger option is selected.
00146 #define ADTRG_HW           ADC_SC2_ADTRG_MASK
00147 #define ADTRG_SW           0x00
00148 
00149 // ADC Compare Function Enable: Disabled, or Enabled.
00150 #define ACFE_DISABLED      0x00
00151 #define ACFE_ENABLED       ADC_SC2_ACFE_MASK
00152 
00153 // Compare Function Greater Than Enable: Greater, or Less.
00154 #define ACFGT_GREATER      ADC_SC2_ACFGT_MASK
00155 #define ACFGT_LESS         0x00
00156 
00157 // Compare Function Range Enable: Enabled or Disabled.
00158 #define ACREN_ENABLED      ADC_SC2_ACREN_MASK
00159 #define ACREN_DISABLED     0x00
00160 
00161 // DMA enable: enabled or disabled.
00162 #define DMAEN_ENABLED      ADC_SC2_DMAEN_MASK
00163 #define DMAEN_DISABLED     0x00
00164 
00165 // Voltage Reference selection for the ADC conversions
00166 // (***not*** the PGA which uses VREFO only).
00167 // VREFH and VREFL (0) , or VREFO (1).
00168 
00169 #define REFSEL_EXT         0x00
00170 #define REFSEL_ALT         0x01
00171 #define REFSEL_RES         0x02     /* reserved */
00172 #define REFSEL_RES_EXT     0x03     /* reserved but defaults to Vref */
00173 
00174 ////ADCSC3
00175 
00176 // Calibration begin or off
00177 #define CAL_BEGIN          ADC_SC3_CAL_MASK
00178 #define CAL_OFF            0x00
00179 
00180 // Status indicating Calibration failed, or normal success
00181 #define CALF_FAIL          ADC_SC3_CALF_MASK
00182 #define CALF_NORMAL        0x00
00183 
00184 // ADC to continously convert, or do a sinle conversion
00185 #define ADCO_CONTINUOUS    ADC_SC3_ADCO_MASK
00186 #define ADCO_SINGLE        0x00
00187 
00188 // Averaging enabled in the ADC, or not.
00189 #define AVGE_ENABLED       ADC_SC3_AVGE_MASK
00190 #define AVGE_DISABLED      0x00
00191 
00192 // How many to average prior to "interrupting" the MCU?  4, 8, 16, or 32
00193 #define AVGS_4             0x00
00194 #define AVGS_8             0x01
00195 #define AVGS_16            0x02
00196 #define AVGS_32            0x03
00197 
00198 ////PGA
00199 
00200 // PGA enabled or not?
00201 #define PGAEN_ENABLED      ADC_PGA_PGAEN_MASK
00202 #define PGAEN_DISABLED     0x00
00203 
00204 // Chopper stabilization of the amplifier, or not.
00205 #define PGACHP_CHOP        ADC_PGA_PGACHP_MASK
00206 #define PGACHP_NOCHOP      0x00
00207 
00208 // PGA in low power mode, or normal mode.
00209 #define PGALP_LOW          ADC_PGA_PGALP_MASK
00210 #define PGALP_NORMAL       0x00
00211 
00212 // Gain of PGA.  Selectable from 1 to 64.
00213 #define PGAG_1             0x00
00214 #define PGAG_2             0x01
00215 #define PGAG_4             0x02
00216 #define PGAG_8             0x03
00217 #define PGAG_16            0x04
00218 #define PGAG_32            0x05
00219 #define PGAG_64            0x06
00220 
00221 /////////// The above values fit into the structure below to select ADC/PGA
00222 /////////// configuration desired:
00223 
00224 typedef struct adc_cfg {
00225     uint8_t  CONFIG1;
00226     uint8_t  CONFIG2;
00227     uint16_t COMPARE1;
00228     uint16_t COMPARE2;
00229     uint8_t  STATUS2;
00230     uint8_t  STATUS3;
00231     uint8_t  STATUS1A;
00232     uint8_t  STATUS1B;
00233     uint32_t PGA;
00234 } *tADC_ConfigPtr, tADC_Config ;
00235 
00236 
00237 #define CAL_BLK_NUMREC 18
00238 
00239 typedef struct adc_cal {
00240 
00241     uint16_t  OFS;
00242     uint16_t  PG;
00243     uint16_t  MG;
00244     uint8_t   CLPD;
00245     uint8_t   CLPS;
00246     uint16_t  CLP4;
00247     uint16_t  CLP3;
00248     uint8_t   CLP2;
00249     uint8_t   CLP1;
00250     uint8_t   CLP0;
00251     uint8_t   dummy;
00252     uint8_t   CLMD;
00253     uint8_t   CLMS;
00254     uint16_t  CLM4;
00255     uint16_t  CLM3;
00256     uint8_t   CLM2;
00257     uint8_t   CLM1;
00258     uint8_t   CLM0;
00259 } tADC_Cal_Blk ;
00260 
00261 typedef struct ADC_MemMap {
00262     uint32_t SC1[2];                                 /**< ADC Status and Control Registers 1, array offset: 0x0, array step: 0x4 */
00263     uint32_t CFG1;                                   /**< ADC Configuration Register 1, offset: 0x8 */
00264     uint32_t CFG2;                                   /**< ADC Configuration Register 2, offset: 0xC */
00265     uint32_t R[2];                                   /**< ADC Data Result Register, array offset: 0x10, array step: 0x4 */
00266     uint32_t CV1;                                    /**< Compare Value Registers, offset: 0x18 */
00267     uint32_t CV2;                                    /**< Compare Value Registers, offset: 0x1C */
00268     uint32_t SC2;                                    /**< Status and Control Register 2, offset: 0x20 */
00269     uint32_t SC3;                                    /**< Status and Control Register 3, offset: 0x24 */
00270     uint32_t OFS;                                    /**< ADC Offset Correction Register, offset: 0x28 */
00271     uint32_t PG;                                     /**< ADC Plus-Side Gain Register, offset: 0x2C */
00272     uint32_t MG;                                     /**< ADC Minus-Side Gain Register, offset: 0x30 */
00273     uint32_t CLPD;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x34 */
00274     uint32_t CLPS;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x38 */
00275     uint32_t CLP4;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x3C */
00276     uint32_t CLP3;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x40 */
00277     uint32_t CLP2;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x44 */
00278     uint32_t CLP1;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x48 */
00279     uint32_t CLP0;                                   /**< ADC Plus-Side General Calibration Value Register, offset: 0x4C */
00280     uint8_t RESERVED_0[4];
00281     uint32_t CLMD;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x54 */
00282     uint32_t CLMS;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x58 */
00283     uint32_t CLM4;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x5C */
00284     uint32_t CLM3;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x60 */
00285     uint32_t CLM2;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x64 */
00286     uint32_t CLM1;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x68 */
00287     uint32_t CLM0;                                   /**< ADC Minus-Side General Calibration Value Register, offset: 0x6C */
00288 } volatile *ADC_MemMapPtr;
00289 
00290 
00291 
00292 /* ADC - Register accessors */
00293 #define ADC_SC1_REG(base,index)                  ((base)->SC1[index])
00294 #define ADC_CFG1_REG(base)                       ((base)->CFG1)
00295 #define ADC_CFG2_REG(base)                       ((base)->CFG2)
00296 #define ADC_R_REG(base,index)                    ((base)->R[index])
00297 #define ADC_CV1_REG(base)                        ((base)->CV1)
00298 #define ADC_CV2_REG(base)                        ((base)->CV2)
00299 #define ADC_SC2_REG(base)                        ((base)->SC2)
00300 #define ADC_SC3_REG(base)                        ((base)->SC3)
00301 #define ADC_OFS_REG(base)                        ((base)->OFS)
00302 #define ADC_PG_REG(base)                         ((base)->PG)
00303 #define ADC_MG_REG(base)                         ((base)->MG)
00304 #define ADC_CLPD_REG(base)                       ((base)->CLPD)
00305 #define ADC_CLPS_REG(base)                       ((base)->CLPS)
00306 #define ADC_CLP4_REG(base)                       ((base)->CLP4)
00307 #define ADC_CLP3_REG(base)                       ((base)->CLP3)
00308 #define ADC_CLP2_REG(base)                       ((base)->CLP2)
00309 #define ADC_CLP1_REG(base)                       ((base)->CLP1)
00310 #define ADC_CLP0_REG(base)                       ((base)->CLP0)
00311 #define ADC_CLMD_REG(base)                       ((base)->CLMD)
00312 #define ADC_CLMS_REG(base)                       ((base)->CLMS)
00313 #define ADC_CLM4_REG(base)                       ((base)->CLM4)
00314 #define ADC_CLM3_REG(base)                       ((base)->CLM3)
00315 #define ADC_CLM2_REG(base)                       ((base)->CLM2)
00316 #define ADC_CLM1_REG(base)                       ((base)->CLM1)
00317 #define ADC_CLM0_REG(base)                       ((base)->CLM0)
00318 
00319 #define ADC0_BASE_PTR                            ((ADC_MemMapPtr)0x4003B000u)
00320 /** Array initializer of ADC peripheral base pointers */
00321 #define ADC_BASE_PTRS                            { ADC0_BASE_PTR }
00322 
00323 
00324 float _ServoDutyCycleMin;
00325 float _ServoDutyCycleMax;
00326 float _ServoPeriod;
00327 
00328 volatile uint16_t QueuedServo0Val;
00329 volatile uint16_t QueuedServo1Val;
00330 
00331 volatile uint16_t  *LineScanImage0WorkingBuffer;
00332 volatile uint16_t  *LineScanImage1WorkingBuffer;
00333 
00334 volatile uint16_t  LineScanImage0Buffer[2][128];
00335 volatile uint16_t  LineScanImage1Buffer[2][128];
00336 volatile uint8_t  LineScanWorkingBuffer;
00337 
00338 volatile uint16_t * TFC_LineScanImage0;
00339 volatile uint16_t * TFC_LineScanImage1;
00340 volatile uint8_t  TFC_LineScanImageReady;
00341 
00342 volatile uint16_t  PotADC_Value[2];
00343 volatile uint16_t  BatSenseADC_Value;
00344 volatile uint16_t  CurrentADC_State;
00345 volatile uint8_t  CurrentLineScanPixel;
00346 volatile uint8_t  CurrentLineScanChannel;
00347 volatile uint32_t TFC_ServoTicker;
00348 
00349 volatile uint16_t HBridge_0_current_value;
00350 volatile uint16_t HBridge_1_current_value;
00351 
00352 
00353 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle);
00354 void TFC_InitLineScanCamera();
00355 uint8_t ADC_Cal(ADC_MemMapPtr adcmap);
00356 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr);
00357 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk);
00358 void TFC_InitADC0();
00359 void TFC_InitADC_System();
00360 void TFC_GPIO_Init();
00361 void ADC0_Handler();
00362 void TPM1_Handler();
00363 
00364 
00365 void TFC_Init()
00366 {
00367 
00368     TFC_GPIO_Init();
00369 
00370     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!
00371 
00372     TFC_InitLineScanCamera();
00373 
00374     TFC_InitServos(SERVO_MIN_PULSE_WIDTH_DEFAULT , SERVO_MAX_PULSE_WIDTH_DEFAULT, SERVO_DEFAULT_PERIOD);
00375     
00376     TFC_ServoTicker = 0;
00377 
00378     TFC_InitMotorPWM(FTM0_DEFAULT_SWITCHING_FREQUENCY);
00379 
00380 }
00381 
00382 
00383 void TFC_GPIO_Init()
00384 {
00385 
00386     //enable Clocks to all ports
00387 
00388     SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK;
00389 
00390     //Setup Pins as GPIO
00391     PORTE->PCR[21] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
00392     PORTE->PCR[20] = PORT_PCR_MUX(1);
00393 
00394     //Port for Pushbuttons
00395     PORTC->PCR[13] = PORT_PCR_MUX(1);
00396     PORTC->PCR[17] = PORT_PCR_MUX(1);
00397 
00398 
00399     //Ports for DIP Switches
00400     PORTE->PCR[2] = PORT_PCR_MUX(1);
00401     PORTE->PCR[3] = PORT_PCR_MUX(1);
00402     PORTE->PCR[4] = PORT_PCR_MUX(1);
00403     PORTE->PCR[5] = PORT_PCR_MUX(1);
00404 
00405     //Ports for LEDs
00406     PORTB->PCR[8] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
00407     PORTB->PCR[9] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
00408     PORTB->PCR[10] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
00409     PORTB->PCR[11] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
00410 
00411 
00412     //Setup the output pins
00413     PTE->PDDR =  TFC_HBRIDGE_EN_LOC;
00414     PTB->PDDR =  TFC_BAT_LED0_LOC  | TFC_BAT_LED1_LOC | TFC_BAT_LED2_LOC | TFC_BAT_LED3_LOC;
00415 
00416     TFC_SetBatteryLED(0);
00417     TFC_HBRIDGE_DISABLE;
00418 }
00419 
00420 void TFC_SetBatteryLED(uint8_t Value)
00421 {
00422     if(Value & 0x01)
00423         TFC_BAT_LED0_ON;
00424     else
00425         TFC_BAT_LED0_OFF;
00426 
00427     if(Value & 0x02)
00428         TFC_BAT_LED1_ON;
00429     else
00430         TFC_BAT_LED1_OFF;
00431 
00432     if(Value & 0x04)
00433         TFC_BAT_LED2_ON;
00434     else
00435         TFC_BAT_LED2_OFF;
00436 
00437     if(Value & 0x08)
00438         TFC_BAT_LED3_ON;
00439     else
00440         TFC_BAT_LED3_OFF;
00441 }
00442 
00443 uint8_t TFC_GetDIP_Switch()
00444 {
00445     uint8_t DIP_Val=0;
00446 
00447     DIP_Val = (PTE->PDIR>>2) & 0xF;
00448 
00449     return DIP_Val;
00450 }
00451 
00452 uint8_t TFC_ReadPushButton(uint8_t Index)
00453 {
00454     if(Index == 0) {
00455         return TFC_PUSH_BUTTON_0_PRESSED;
00456     } else {
00457         return TFC_PUSH_BUTTON_1_PRESSED;
00458     }
00459 }
00460 
00461 extern "C" void TPM1_IRQHandler()
00462 {
00463     //Clear the overflow mask if set.   According to the reference manual, we clear by writing a logic one!
00464     if(TPM1->SC & TPM_SC_TOF_MASK)
00465         TPM1->SC |= TPM_SC_TOF_MASK;
00466 
00467     //Dump the queued values to the timer channels
00468     TPM1->CONTROLS[0].CnV = QueuedServo0Val;
00469     TPM1->CONTROLS[1].CnV = QueuedServo1Val;
00470 
00471 
00472     //Prime the next ADC capture cycle
00473     TAOS_SI_HIGH;
00474     //Prime the ADC pump and start capturing POT 0
00475     CurrentADC_State = ADC_STATE_CAPTURE_POT_0;
00476 
00477     ADC0->CFG2  &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
00478     ADC0->SC1[0]  =  TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;  //Start the State machine at POT0
00479 
00480     //Flag that a new cervo cycle will start
00481     if (TFC_ServoTicker < 0xffffffff)//if servo tick less than max value, count up...
00482         TFC_ServoTicker++;
00483 
00484 }
00485 
00486 
00487 void TFC_InitServos(float PulseWidthMin, float PulseWidthMax, float ServoPeriod)
00488 {
00489 
00490     SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; 
00491 
00492     _ServoPeriod = ServoPeriod;
00493     _ServoDutyCycleMin = PulseWidthMin/ServoPeriod;
00494     _ServoDutyCycleMax = PulseWidthMax/ServoPeriod;
00495 
00496     //Clock Setup for the TPM requires a couple steps.
00497     SIM->SCGC6 &= ~SIM_SCGC6_TPM1_MASK;
00498     //1st,  set the clock mux
00499     //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
00500     SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012)
00501     SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
00502     SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1);
00503 
00504     //Enable the Clock to the FTM0 Module
00505     //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
00506     SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK;
00507 
00508     //The TPM Module has Clock.  Now set up the peripheral
00509 
00510     //Blow away the control registers to ensure that the counter is not running
00511     TPM1->SC = 0;
00512     TPM1->CONF = 0;
00513 
00514     //While the counter is disabled we can setup the prescaler
00515 
00516     TPM1->SC = TPM_SC_PS(FTM1_CLK_PRESCALE);
00517     TPM1->SC |= TPM_SC_TOIE_MASK; //Enable Interrupts for the Timer Overflow
00518 
00519     //Setup the mod register to get the correct PWM Period
00520 
00521     TPM1->MOD = (SystemCoreClock/(1<<(FTM1_CLK_PRESCALE))) * _ServoPeriod;
00522     //Setup Channels 0 and 1
00523 
00524     TPM1->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
00525     TPM1->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
00526 
00527 
00528     //Set the Default duty cycle to servo neutral
00529     TFC_SetServo(0, 0.0);
00530     TFC_SetServo(1, 0.0);
00531 
00532     //Enable the TPM COunter
00533     TPM1->SC |= TPM_SC_CMOD(1);
00534 
00535     //Enable TPM1 IRQ on the NVIC
00536 
00537     //NVIC_SetVector(TPM1_IRQn,(uint32_t)TPM1_Handler);
00538     NVIC_EnableIRQ(TPM1_IRQn);
00539 
00540     //Enable the FTM functions on the the port
00541 
00542     PORTB->PCR[0] = PORT_PCR_MUX(3);
00543     PORTB->PCR[1] = PORT_PCR_MUX(3);
00544 
00545 }
00546 
00547 
00548 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle)
00549 {
00550     switch(ServoNumber) {
00551         default:
00552         case 0:
00553 
00554             QueuedServo0Val = TPM1->MOD * DutyCycle;
00555 
00556             break;
00557 
00558         case 1:
00559 
00560             QueuedServo1Val = TPM1->MOD * DutyCycle;
00561 
00562             break;
00563     }
00564 }
00565 
00566 void TFC_SetServo(uint8_t ServoNumber, float Position)
00567 {
00568     TFC_SetServoDutyCycle(ServoNumber ,
00569                           ((Position + 1.0)/2)    *   ((_ServoDutyCycleMax - _ServoDutyCycleMin))+_ServoDutyCycleMin) ;
00570 
00571 }
00572 
00573 //********************************************************************************************************
00574 //********************************************************************************************************
00575 //********************************************************************************************************
00576 //           _____   _____       ______ _    _ _   _  _____ _______ _____ ____  _   _  _____
00577 //     /\   |  __ \ / ____|     |  ____| |  | | \ | |/ ____|__   __|_   _/ __ \| \ | |/ ____|
00578 //    /  \  | |  | | |          | |__  | |  | |  \| | |       | |    | || |  | |  \| | (___
00579 //   / /\ \ | |  | | |          |  __| | |  | | . ` | |       | |    | || |  | | . ` |\___ \
00580 //  / ____ \| |__| | |____      | |    | |__| | |\  | |____   | |   _| || |__| | |\  |____) |
00581 // /_/    \_\_____/ \_____|     |_|     \____/|_| \_|\_____|  |_|  |_____\____/|_| \_|_____/
00582 // ********************************************************************************************************
00583 // ********************************************************************************************************
00584 // ********************************************************************************************************
00585 
00586 
00587 
00588 
00589 
00590 uint8_t ADC_Cal(ADC_MemMapPtr adcmap)
00591 {
00592 
00593     uint16_t cal_var;
00594 
00595     ADC_SC2_REG(adcmap) &=  ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process    - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0);
00596     ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
00597     ADC_SC3_REG(adcmap) |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) );  // Turn averaging ON and set at max value ( 32 )
00598 
00599 
00600     ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ;      // Start CAL
00601     while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end
00602 
00603     if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL ) {
00604         return(1);    // Check for Calibration fail error and return
00605     }
00606     // Calculate plus-side calibration
00607     cal_var = 0x00;
00608 
00609     cal_var =  ADC_CLP0_REG(adcmap);
00610     cal_var += ADC_CLP1_REG(adcmap);
00611     cal_var += ADC_CLP2_REG(adcmap);
00612     cal_var += ADC_CLP3_REG(adcmap);
00613     cal_var += ADC_CLP4_REG(adcmap);
00614     cal_var += ADC_CLPS_REG(adcmap);
00615 
00616     cal_var = cal_var/2;
00617     cal_var |= 0x8000; // Set MSB
00618 
00619     ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
00620 
00621 
00622     // Calculate minus-side calibration
00623     cal_var = 0x00;
00624 
00625     cal_var =  ADC_CLM0_REG(adcmap);
00626     cal_var += ADC_CLM1_REG(adcmap);
00627     cal_var += ADC_CLM2_REG(adcmap);
00628     cal_var += ADC_CLM3_REG(adcmap);
00629     cal_var += ADC_CLM4_REG(adcmap);
00630     cal_var += ADC_CLMS_REG(adcmap);
00631 
00632     cal_var = cal_var/2;
00633 
00634     cal_var |= 0x8000; // Set MSB
00635 
00636     ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var);
00637 
00638     ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
00639 
00640     return(0);
00641 }
00642 
00643 
00644 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr)
00645 {
00646     ADC_CFG1_REG(adcmap) = ADC_CfgPtr->CONFIG1;
00647     ADC_CFG2_REG(adcmap) = ADC_CfgPtr->CONFIG2;
00648     ADC_CV1_REG(adcmap)  = ADC_CfgPtr->COMPARE1;
00649     ADC_CV2_REG(adcmap)  = ADC_CfgPtr->COMPARE2;
00650     ADC_SC2_REG(adcmap)  = ADC_CfgPtr->STATUS2;
00651     ADC_SC3_REG(adcmap)  = ADC_CfgPtr->STATUS3;
00652 //ADC_PGA_REG(adcmap)  = ADC_CfgPtr->PGA;
00653     ADC_SC1_REG(adcmap,A)= ADC_CfgPtr->STATUS1A;
00654     ADC_SC1_REG(adcmap,B)= ADC_CfgPtr->STATUS1B;
00655 }
00656 
00657 
00658 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk)
00659 {
00660     blk->OFS  = ADC_OFS_REG(adcmap);
00661     blk->PG   = ADC_PG_REG(adcmap);
00662     blk->MG   = ADC_MG_REG(adcmap);
00663     blk->CLPD = ADC_CLPD_REG(adcmap);
00664     blk->CLPS = ADC_CLPS_REG(adcmap);
00665     blk->CLP4 = ADC_CLP4_REG(adcmap);
00666     blk->CLP3 = ADC_CLP3_REG(adcmap);
00667     blk->CLP2 = ADC_CLP2_REG(adcmap);
00668     blk->CLP1 = ADC_CLP1_REG(adcmap);
00669     blk->CLP0 = ADC_CLP0_REG(adcmap);
00670     blk->CLMD = ADC_CLMD_REG(adcmap);
00671     blk->CLMS = ADC_CLMS_REG(adcmap);
00672     blk->CLM4 = ADC_CLM4_REG(adcmap);
00673     blk->CLM3 = ADC_CLM3_REG(adcmap);
00674     blk->CLM2 = ADC_CLM2_REG(adcmap);
00675     blk->CLM1 = ADC_CLM1_REG(adcmap);
00676     blk->CLM0 = ADC_CLM0_REG(adcmap);
00677 
00678 }
00679 
00680 
00681 void TFC_InitADC0()
00682 {
00683     tADC_Config Master_Adc0_Config;
00684 
00685 
00686     SIM->SCGC6 |= (SIM_SCGC6_ADC0_MASK);
00687 
00688     //Lets calibrate the ADC. 1st setup how the channel will be used.
00689 
00690 
00691     Master_Adc0_Config.CONFIG1 = ADLPC_NORMAL           //No low power mode
00692                                  | ADC_CFG1_ADIV(ADIV_4) //divide input by 4
00693                                  | ADLSMP_LONG           //long sample time
00694                                  | ADC_CFG1_MODE(MODE_12)//single ended 8-bit conversion
00695                                  | ADC_CFG1_ADICLK(ADICLK_BUS);
00696 
00697     Master_Adc0_Config.CONFIG2 = MUXSEL_ADCA // select the A side of the ADC channel.
00698                                  | ADACKEN_DISABLED
00699                                  | ADHSC_HISPEED
00700                                  | ADC_CFG2_ADLSTS(ADLSTS_2);//Extra long sample Time (20 extra clocks)
00701 
00702 
00703     Master_Adc0_Config.COMPARE1 = 00000; // Comparators don't matter for calibration
00704     Master_Adc0_Config.COMPARE1 = 0xFFFF;
00705 
00706     Master_Adc0_Config.STATUS2  = ADTRG_HW //hardware triggers for calibration
00707                                   | ACFE_DISABLED //disable comparator
00708                                   | ACFGT_GREATER
00709                                   | ACREN_ENABLED
00710                                   | DMAEN_DISABLED //Disable DMA
00711                                   | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
00712 
00713     Master_Adc0_Config.STATUS3 = CAL_OFF
00714                                  | ADCO_SINGLE
00715                                  | AVGE_ENABLED;
00716                               //   | ADC_SC3_AVGS(AVGS_4);
00717 
00718     Master_Adc0_Config.PGA =     0; // Disable the PGA
00719 
00720 
00721     // Configure ADC as it will be used, but because ADC_SC1_ADCH is 31,
00722     // the ADC will be inactive.  Channel 31 is just disable function.
00723     // There really is no channel 31.
00724 
00725     Master_Adc0_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31);
00726 
00727 
00728     ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config);  // config ADC
00729 
00730     // Calibrate the ADC in the configuration in which it will be used:
00731     ADC_Cal(ADC0_BASE_PTR);                    // do the calibration
00732 
00733 
00734     Master_Adc0_Config.STATUS2  = ACFE_DISABLED //disable comparator
00735                                   | ACFGT_GREATER
00736                                   | ACREN_ENABLED
00737                                   | DMAEN_DISABLED //Disable DMA
00738                                   | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
00739 
00740     Master_Adc0_Config.STATUS3 = CAL_OFF
00741                                  | ADCO_SINGLE;
00742 
00743 
00744 
00745     ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config);
00746 }
00747 
00748 
00749 void TFC_InitADC_System()
00750 {
00751 
00752     TFC_InitADC0();
00753 
00754 
00755     //All Adc processing of the Pots and linescan will be done in the ADC0 IRQ!
00756     //A state machine will scan through the channels.
00757     //This is done to automate the linescan capture on Channel 0 to ensure that timing is very even
00758     CurrentADC_State =  ADC_STATE_INIT;
00759 
00760     //The pump will be primed with the TPM1 interrupt.  upon timeout/interrupt it will set the SI signal high
00761     //for the camera and then start the conversions for the pots.
00762 
00763    // NVIC_SetVector(ADC0_IRQn,(uint32_t)ADC0_Handler);
00764     NVIC_EnableIRQ(ADC0_IRQn);
00765 
00766 }
00767 
00768 extern "C" void ADC0_IRQHandler()
00769 {
00770     uint8_t Junk;
00771 
00772     switch(CurrentADC_State) {
00773         default:
00774             Junk =  ADC0->R[0];
00775             break;
00776 
00777         case ADC_STATE_CAPTURE_POT_0:
00778 
00779             PotADC_Value[0] = ADC0->R[0];
00780             ADC0->CFG2  &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
00781             ADC0->SC1[0]  =  TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
00782             CurrentADC_State = ADC_STATE_CAPTURE_POT_1;
00783 
00784             break;
00785 
00786         case ADC_STATE_CAPTURE_POT_1:
00787 
00788             PotADC_Value[1] = ADC0->R[0];
00789             
00790             CurrentADC_State = ADC_STATE_CAPTURE_I_HBRIDGE_A; 
00791             ADC0->CFG2  &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
00792             ADC0->SC1[0]  =  TFC_I_HBRIDGE_0_SENSE_ADC_CHANNEL | ADC_SC1_AIEN_MASK; // HBRIDGE channel
00793             break;
00794             
00795             
00796         // NEW STATES
00797         case ADC_STATE_CAPTURE_I_HBRIDGE_A:
00798             // Read ADC value 
00799             HBridge_0_current_value = ADC0->R[0];
00800             // Change the ADC active channel 
00801             ADC0->SC1[0]  =  TFC_I_HBRIDGE_1_SENSE_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
00802             // Update the state machine
00803             CurrentADC_State = ADC_STATE_CAPTURE_I_HBRIDGE_B;
00804             break;
00805             
00806         case ADC_STATE_CAPTURE_I_HBRIDGE_B:
00807             HBridge_1_current_value = ADC0->R[0];            
00808             ADC0->CFG2  |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
00809             ADC0->SC1[0]  =  TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK;
00810             CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL;
00811             break;
00812 
00813         case ADC_STATE_CAPTURE_BATTERY_LEVEL:
00814 
00815             BatSenseADC_Value = ADC0->R[0];
00816 
00817             //Now we will start the sequence for the Linescan camera
00818 
00819             TAOS_CLK_HIGH;
00820 
00821             for(Junk = 0; Junk<50; Junk++) {
00822             }
00823 
00824             TAOS_SI_LOW;
00825 
00826 
00827             CurrentLineScanPixel = 0;
00828             CurrentLineScanChannel = 0;
00829             CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN;
00830             ADC0->CFG2  |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
00831             ADC0->SC1[0] =  TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
00832 
00833             break;
00834 
00835         case ADC_STATE_CAPTURE_LINE_SCAN:
00836 
00837             if(CurrentLineScanPixel<128) {
00838                 if(CurrentLineScanChannel == 0) {
00839                     LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
00840                     ADC0->SC1[0]  =  TFC_LINESCAN1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
00841                     CurrentLineScanChannel = 1;
00842 
00843                 } else {
00844                     LineScanImage1WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
00845                     ADC0->SC1[0]  =  TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
00846                     CurrentLineScanChannel = 0;
00847                     CurrentLineScanPixel++;
00848 
00849                     TAOS_CLK_LOW;
00850                     for(Junk = 0; Junk<50; Junk++) {
00851                     }
00852                     TAOS_CLK_HIGH;
00853 
00854                 }
00855 
00856             } else {
00857                 // done with the capture sequence.  we can wait for the PIT0 IRQ to restart
00858 
00859                 TAOS_CLK_HIGH;
00860 
00861                 for(Junk = 0; Junk<50; Junk++) {
00862                 }
00863 
00864                 TAOS_CLK_LOW;
00865                 CurrentADC_State = ADC_STATE_INIT;
00866                 
00867                 //swap the buffer
00868 
00869                 if(LineScanWorkingBuffer == 0) {
00870                     LineScanWorkingBuffer = 1;
00871 
00872                     LineScanImage0WorkingBuffer = &LineScanImage0Buffer[1][0];
00873                     LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0];
00874 
00875                     TFC_LineScanImage0 = &LineScanImage0Buffer[0][0];
00876                     TFC_LineScanImage1 = &LineScanImage1Buffer[0][0];
00877                 } else {
00878                     LineScanWorkingBuffer = 0;
00879                     LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0];
00880                     LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0];
00881 
00882                     TFC_LineScanImage0  = &LineScanImage0Buffer[1][0];
00883                     TFC_LineScanImage1  = &LineScanImage1Buffer[1][0];
00884                 }
00885 
00886                 TFC_LineScanImageReady++;
00887             }
00888 
00889             break;
00890     }
00891 
00892 }
00893 
00894 void TFC_InitLineScanCamera()
00895 {
00896     SIM->SCGC5 |=   SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTD_MASK; //Make sure the clock is enabled for PORTE;
00897     PORTE->PCR[1] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;   //Enable GPIO on on the pin for the CLOCK Signal
00898     PORTD->PCR[7] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;   //Enable GPIO on on the pin for SI signal
00899 
00900     PORTD->PCR[5] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
00901     PORTD->PCR[6] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
00902 
00903     //Make sure the Clock and SI pins are outputs
00904     PTD->PDDR |= (1<<7);
00905     PTE->PDDR |= (1<<1);
00906 
00907     TAOS_CLK_LOW;
00908     TAOS_SI_LOW;
00909 
00910     LineScanWorkingBuffer = 0;
00911 
00912     LineScanImage0WorkingBuffer = &LineScanImage0Buffer[LineScanWorkingBuffer][0];
00913     LineScanImage1WorkingBuffer = &LineScanImage1Buffer[LineScanWorkingBuffer][0];
00914 
00915     TFC_LineScanImage0 = &LineScanImage0Buffer[1][0];
00916     TFC_LineScanImage1  = &LineScanImage1Buffer[1][0];
00917 }
00918 
00919 
00920 
00921 
00922 
00923 /** 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
00924 *
00925 *  @param SwitchingFrequency PWM Switching Frequency in floating point format.   Pick something between 1000 and 9000.   Maybe you can modulate it and make a tune.
00926 */
00927 void TFC_InitMotorPWM(float SwitchingFrequency)
00928 {
00929     //Clock Setup for the TPM requires a couple steps.
00930 
00931     //1st,  set the clock mux
00932     //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
00933     SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012)
00934     SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
00935     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)
00936 
00937 
00938     //Enable the Clock to the FTM0 Module
00939     //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
00940     SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;
00941 
00942     //The TPM Module has Clock.  Now set up the peripheral
00943 
00944     //Blow away the control registers to ensure that the counter is not running
00945     TPM0->SC = 0;
00946     TPM0->CONF = 0;
00947 
00948     //While the counter is disabled we can setup the prescaler
00949 
00950     TPM0->SC = TPM_SC_PS(FTM0_CLK_PRESCALE);
00951 
00952     //Setup the mod register to get the correct PWM Period
00953 
00954     TPM0->MOD = (uint32_t)((float)(FTM0_CLOCK/(1<<FTM0_CLK_PRESCALE))/SwitchingFrequency);
00955 
00956     //Setup Channels 0,1,2,3
00957     TPM0->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
00958     TPM0->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
00959     TPM0->CONTROLS[2].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
00960     TPM0->CONTROLS[3].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
00961 
00962     //Enable the Counter
00963 
00964     //Set the Default duty cycle to 50% duty cycle
00965     TFC_SetMotorPWM(0.0,0.0);
00966 
00967     //Enable the TPM COunter
00968     TPM0->SC |= TPM_SC_CMOD(1);
00969 
00970     //Enable the FTM functions on the the port
00971     PORTC->PCR[1] = PORT_PCR_MUX(4);
00972     PORTC->PCR[2] = PORT_PCR_MUX(4);
00973     PORTC->PCR[3] = PORT_PCR_MUX(4);
00974     PORTC->PCR[4] = PORT_PCR_MUX(4);
00975 
00976 }
00977 
00978 void TFC_SetMotorPWM(float MotorA , float MotorB)
00979 {
00980     if(MotorA>1.0)
00981         MotorA = 1.0;
00982     else if(MotorA<-1.0)
00983         MotorA = -1.0;
00984 
00985     if(MotorB>1.0)
00986         MotorB = 1.0;
00987     else if(MotorB<-1.0)
00988         MotorB = -1.0;
00989 
00990     TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0));
00991     TPM0->CONTROLS[3].CnV = TPM0->CONTROLS[2].CnV;
00992     TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorB + 1.0)/2.0));
00993     TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV;
00994 
00995 }
00996 
00997 //Pot Reading is Scaled to return a value of -1.0 to 1.0
00998 float TFC_ReadPot(uint8_t Channel)
00999 {
01000     if(Channel == 0)
01001         return ((float)PotADC_Value[0]/-((float)ADC_MAX_CODE/2.0))+1.0;
01002     else
01003         return ((float)PotADC_Value[1]/-((float)ADC_MAX_CODE/2.0))+1.0;
01004 }
01005 
01006 float TFC_ReadBatteryVoltage()
01007 {
01008     return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0);
01009 }
01010 
01011 float TFC_ReadMotorCurrent(uint8_t motorChannel)
01012 {
01013     if(motorChannel)
01014         return ((float)(HBridge_0_current_value)/(float)(ADC_MAX_CODE));//TODO : Coefficient ?
01015     else
01016         return ((float)(HBridge_1_current_value)/(float)(ADC_MAX_CODE));//TODO : Coefficient ?
01017 }
01018 
01019 
01020 void TFC_SetBatteryLED_Level(uint8_t BattLevel)
01021 {
01022     switch(BattLevel)
01023     {
01024         default:
01025         case 0:
01026             TFC_BAT_LED0_OFF;
01027             TFC_BAT_LED1_OFF; 
01028             TFC_BAT_LED2_OFF; 
01029             TFC_BAT_LED3_OFF;
01030         break;
01031     
01032         case 1:
01033             TFC_BAT_LED0_ON;
01034             TFC_BAT_LED1_OFF; 
01035             TFC_BAT_LED2_OFF; 
01036             TFC_BAT_LED3_OFF;
01037         break;
01038         
01039         case 2:
01040             TFC_BAT_LED0_ON;
01041             TFC_BAT_LED1_ON; 
01042             TFC_BAT_LED2_OFF; 
01043             TFC_BAT_LED3_OFF;
01044         break;
01045         
01046         case 3:
01047             TFC_BAT_LED0_ON;
01048             TFC_BAT_LED1_ON; 
01049             TFC_BAT_LED2_ON; 
01050             TFC_BAT_LED3_OFF;
01051         break;
01052         
01053         case 4:
01054             TFC_BAT_LED0_ON;
01055             TFC_BAT_LED1_ON; 
01056             TFC_BAT_LED2_ON; 
01057             TFC_BAT_LED3_ON;
01058         break;
01059         
01060     }
01061 }