Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Bov3 by
Revision 19:4869b10a962e, committed 2014-07-02
- Comitter:
- backman
- Date:
- Wed Jul 02 03:23:07 2014 +0000
- Parent:
- 18:eb675df59c7f
- Commit message:
- wang
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BX-adc.cpp Wed Jul 02 03:23:07 2014 +0000 @@ -0,0 +1,97 @@ +#ifdef TARGET_KLXX + +#include "BX-adc.h" +#include "clk_freqs.h" + +#define MAX_FADC 6000000 +#define CHANNELS_A_SHIFT 5 + +FastAnalogIn::FastAnalogIn(PinName pin, bool enabled) +{ + ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC); + if (ADCnumber == (ADCName)NC) { + error("ADC pin mapping failed"); + } + + SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; + + uint32_t port = (uint32_t)pin >> PORT_SHIFT; + SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port); + + uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK; + if (ADCnumber & (1 << CHANNELS_A_SHIFT)) { + cfg2_muxsel = 0; + } + + // bus clk + uint32_t PCLK = bus_frequency(); + uint32_t clkdiv; + for (clkdiv = 0; clkdiv < 4; clkdiv++) { + if ((PCLK >> clkdiv) <= MAX_FADC) + break; + } + if (clkdiv == 4) //Set max div + clkdiv = 0x7; + + ADC0->SC1[1] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); + + ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select: (Input Clock)/8 + | ADC_CFG1_MODE(3) // (16)bits Resolution + | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock: (Bus Clock)/2 + + ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels + | ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable + | ADC_CFG2_ADHSC_MASK; // High-Speed Configuration + + ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference + + pinmap_pinout(pin, PinMap_ADC); + + //Enable channel + running = false; + enable(enabled); +} + +void FastAnalogIn::enable(bool enabled) +{ + //If currently not running + if (!running) { + if (enabled) { + //Enable the ADC channel + ADC0->SC3 |= ADC_SC3_ADCO_MASK; // Enable continuous conversion + ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); //Start conversion + running = true; + } else + disable(); + } +} + +void FastAnalogIn::disable( void ) +{ + //If currently running + if (running) { + ADC0->SC3 &= ~ADC_SC3_ADCO_MASK; // Disable continuous conversion + } + running = false; +} + +uint16_t FastAnalogIn::read_u16() +{ + if (!running) + { + // start conversion + ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); + // Wait Conversion Complete + while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); + } + if(running && ((ADC0->SC1[0]&ADC_SC1_ADCH_MASK) != (ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT))))) + { + running = false; + enable(); + while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); + } + // Return value + return (uint16_t)ADC0->R[0]; +} + +#endif //defined TARGET_KLXX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BX-adc.h Wed Jul 02 03:23:07 2014 +0000 @@ -0,0 +1,117 @@ +#include "mbed.h" +#include "pinmap.h" + + + + /** A class similar to AnalogIn, only faster, for LPC1768, LPC408X and KLxx + * + * AnalogIn does a single conversion when you read a value (actually several conversions and it takes the median of that). + * This library runns the ADC conversion automatically in the background. + * When read is called, it immediatly returns the last sampled value. + * + * LPC1768 / LPC4088 + * Using more ADC pins in continuous mode will decrease the conversion rate (LPC1768:200kHz/LPC4088:400kHz). + * If you need to sample one pin very fast and sometimes also need to do AD conversions on another pin, + * you can disable the continuous conversion on that ADC channel and still read its value. + * + * KLXX + * Multiple Fast instances can be declared of which only ONE can be continuous (all others must be non-continuous). + * + * When continuous conversion is disabled, a read will block until the conversion is complete + * (much like the regular AnalogIn library does). + * Each ADC channel can be enabled/disabled separately. + * + * IMPORTANT : It does not play nicely with regular AnalogIn objects, so either use this library or AnalogIn, not both at the same time!! + * + * Example for the KLxx processors: + * @code + * // Print messages when the AnalogIn is greater than 50% + * + * #include "mbed.h" + * + * FastAnalogIn temperature(PTC2); //Fast continuous sampling on PTC2 + * FastAnalogIn speed(PTB3, 0); //Fast non-continuous sampling on PTB3 + * + * int main() { + * while(1) { + * if(temperature > 0.5) { + * printf("Too hot! (%f) at speed %f", temperature.read(), speed.read()); + * } + * } + * } + * @endcode + * Example for the LPC1768 processor: + * @code + * // Print messages when the AnalogIn is greater than 50% + * + * #include "mbed.h" + * + * FastAnalogIn temperature(p20); + * + * int main() { + * while(1) { + * if(temperature > 0.5) { + * printf("Too hot! (%f)", temperature.read()); + * } + * } + * } + * @endcode +*/ +class FastAnalogIn { + +public: + /** Create a FastAnalogIn, connected to the specified pin + * + * @param pin AnalogIn pin to connect to + * @param enabled Enable the ADC channel (default = true) + */ + FastAnalogIn( PinName pin, bool enabled = true ); + + ~FastAnalogIn( void ) + { + disable(); + } + + /** Enable the ADC channel + * + * @param enabled Bool that is true for enable, false is equivalent to calling disable + */ + void enable(bool enabled = true); + + /** Disable the ADC channel + * + * Disabling unused channels speeds up conversion in used channels. + * When disabled you can still call read, that will do a single conversion (actually two since the first one always returns 0 for unknown reason). + * Then the function blocks until the value is read. This is handy when you sometimes needs a single conversion besides the automatic conversion + */ + void disable( void ); + + /** Returns the raw value + * + * @param return Unsigned integer with converted value + */ + unsigned short read_u16( void ); + + /** Returns the scaled value + * + * @param return Float with scaled converted value to 0.0-1.0 + */ + float read( void ) + { + unsigned short value = read_u16(); + return (float)value * (1.0f/65535.0f); + } + + /** An operator shorthand for read() + */ + operator float() { + return read(); + } + + +private: + bool running; + char ADCnumber; + uint32_t *datareg; +}; + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFC.cpp Wed Jul 02 03:23:07 2014 +0000 @@ -0,0 +1,1038 @@ +#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)(.010) // Desired Frequency of PWM Signal - Here 50Hz => 20ms period +#define TAOS_CLK_COUNT 200 // Number of cycles for CLK Signal on camera + +// 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 (4095) + +#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 uint16_t *LineScanImage0WorkingBuffer; +volatile uint16_t *LineScanImage1WorkingBuffer; + +volatile uint16_t LineScanImage0Buffer[2][128]; +volatile uint16_t LineScanImage1Buffer[2][128]; +volatile uint8_t LineScanWorkingBuffer; + +volatile uint16_t * TFC_LineScanImage0; +volatile uint16_t * TFC_LineScanImage1; +volatile uint8_t TFC_LineScanImageReady; + +volatile uint16_t PotADC_Value[2]; +volatile uint16_t BatSenseADC_Value; +volatile uint16_t CurrentADC_State; +volatile uint8_t CurrentLineScanPixel; +volatile uint8_t CurrentLineScanChannel; +volatile uint32_t TFC_ServoTicker; + + +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) +{ + + SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; + + _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_12)//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<TAOS_CLK_COUNT/2; 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<128) { + 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<TAOS_CLK_COUNT/2; 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<TAOS_CLK_COUNT/2; 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_LineScanImage0 = &LineScanImage0Buffer[0][0]; + TFC_LineScanImage1 = &LineScanImage1Buffer[0][0]; + } else { + LineScanWorkingBuffer = 0; + LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0]; + LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0]; + + TFC_LineScanImage0 = &LineScanImage0Buffer[1][0]; + TFC_LineScanImage1 = &LineScanImage1Buffer[1][0]; + } + + TFC_LineScanImageReady++; + } + + 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_LineScanImage0 = &LineScanImage0Buffer[1][0]; + TFC_LineScanImage1 = &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]/-((float)ADC_MAX_CODE/2.0))+1.0; + else + return ((float)PotADC_Value[1]/-((float)ADC_MAX_CODE/2.0))+1.0; +} + +float TFC_ReadBatteryVoltage() +{ + return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0); +} + + +void TFC_SetBatteryLED_Level(uint8_t BattLevel) +{ + switch(BattLevel) + { + default: + case 0: + TFC_BAT_LED0_OFF; + TFC_BAT_LED1_OFF; + TFC_BAT_LED2_OFF; + TFC_BAT_LED3_OFF; + break; + + case 1: + TFC_BAT_LED0_ON; + TFC_BAT_LED1_OFF; + TFC_BAT_LED2_OFF; + TFC_BAT_LED3_OFF; + break; + + case 2: + TFC_BAT_LED0_ON; + TFC_BAT_LED1_ON; + TFC_BAT_LED2_OFF; + TFC_BAT_LED3_OFF; + break; + + case 3: + TFC_BAT_LED0_ON; + TFC_BAT_LED1_ON; + TFC_BAT_LED2_ON; + TFC_BAT_LED3_OFF; + break; + + case 4: + TFC_BAT_LED0_ON; + TFC_BAT_LED1_ON; + TFC_BAT_LED2_ON; + TFC_BAT_LED3_ON; + break; + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFC.h Wed Jul 02 03:23:07 2014 +0000 @@ -0,0 +1,252 @@ + +#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(); + + + +/** Sets the Battery level indiciate +* +* @param BattLevel A number betwween 0 and 4. This will light the bar from left to right with the specifified number of segments. +* +*/ +void TFC_SetBatteryLED_Level(uint8_t BattLevel); + + +/** 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 uint16_t * TFC_LineScanImage0; +extern volatile uint16_t * TFC_LineScanImage1; + + +/** 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_LineScanImageReady; + + + + + +/** @} */ + + +#endif
--- a/bx-adc.cpp Mon Jun 30 07:01:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -#include "bx-adc.h" -#include "clk_freqs.h" - -#define MAX_FADC 6000000 -#define CHANNELS_A_SHIFT 5 - -FastAnalogIn::FastAnalogIn(PinName pin, bool enabled) -{ - ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC); - if (ADCnumber == (ADCName)NC) { - error("ADC pin mapping failed"); - } - - SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK; - //----------------------------------------------------- - uint32_t port = (uint32_t)pin >> PORT_SHIFT; - SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port); - - uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK; - if (ADCnumber & (1 << CHANNELS_A_SHIFT)) { - cfg2_muxsel = 0; - } - //------------------------------------------------------ - // bus clk - uint32_t PCLK = bus_frequency(); - uint32_t clkdiv; - for (clkdiv = 0; clkdiv < 4; clkdiv++) { - if ((PCLK >> clkdiv) <= MAX_FADC) - break; - } - if (clkdiv == 4) //Set max div - clkdiv = 0x7; - - ADC0->SC1[1] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); - - ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv & 0x3) // Clock Divide Select: (Input Clock)/8 - | ADC_CFG1_MODE(3) // (16)bits Resolution - | ADC_CFG1_ADICLK(clkdiv >> 2); // Input Clock: (Bus Clock)/2 - - ADC0->CFG2 = cfg2_muxsel // ADxxb or ADxxa channels - | ADC_CFG2_ADACKEN_MASK // Asynchronous Clock Output Enable - | ADC_CFG2_ADHSC_MASK; // High-Speed Configuration - - ADC0->SC2 = ADC_SC2_REFSEL(0); // Default Voltage Reference - - pinmap_pinout(pin, PinMap_ADC); - - //Enable channel - running = false; - enable(enabled); -} - -void FastAnalogIn::enable(bool enabled) -{ - //If currently not running - if (!running) { - if (enabled) { - //Enable the ADC channel - ADC0->SC3 |= ADC_SC3_ADCO_MASK; // Enable continuous conversion - ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); //Start conversion - running = true; - } else - disable(); - } -} - -void FastAnalogIn::disable( void ) -{ - //If currently running - if (running) { - ADC0->SC3 &= ~ADC_SC3_ADCO_MASK; // Disable continuous conversion - } - running = false; -} - -uint16_t FastAnalogIn::read_u16() -{ - if (!running) - { - // start conversion - ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)); - // Wait Conversion Complete - while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); - } - if(running && ((ADC0->SC1[0]&ADC_SC1_ADCH_MASK) != (ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT))))) - { - running = false; - enable(); - while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK); - } - // Return value - return (uint16_t)ADC0->R[0]; -} - \ No newline at end of file
--- a/bx-adc.h Mon Jun 30 07:01:58 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -#include "mbed.h" -#include "pinmap.h" - - - - /** A class similar to AnalogIn, only faster, for LPC1768, LPC408X and KLxx - * - * AnalogIn does a single conversion when you read a value (actually several conversions and it takes the median of that). - * This library runns the ADC conversion automatically in the background. - * When read is called, it immediatly returns the last sampled value. - * - * LPC1768 / LPC4088 - * Using more ADC pins in continuous mode will decrease the conversion rate (LPC1768:200kHz/LPC4088:400kHz). - * If you need to sample one pin very fast and sometimes also need to do AD conversions on another pin, - * you can disable the continuous conversion on that ADC channel and still read its value. - * - * KLXX - * Multiple Fast instances can be declared of which only ONE can be continuous (all others must be non-continuous). - * - * When continuous conversion is disabled, a read will block until the conversion is complete - * (much like the regular AnalogIn library does). - * Each ADC channel can be enabled/disabled separately. - * - * IMPORTANT : It does not play nicely with regular AnalogIn objects, so either use this library or AnalogIn, not both at the same time!! - * - * Example for the KLxx processors: - * @code - * // Print messages when the AnalogIn is greater than 50% - * - * #include "mbed.h" - * - * FastAnalogIn temperature(PTC2); //Fast continuous sampling on PTC2 - * FastAnalogIn speed(PTB3, 0); //Fast non-continuous sampling on PTB3 - * - * int main() { - * while(1) { - * if(temperature > 0.5) { - * printf("Too hot! (%f) at speed %f", temperature.read(), speed.read()); - * } - * } - * } - * @endcode - * Example for the LPC1768 processor: - * @code - * // Print messages when the AnalogIn is greater than 50% - * - * #include "mbed.h" - * - * FastAnalogIn temperature(p20); - * - * int main() { - * while(1) { - * if(temperature > 0.5) { - * printf("Too hot! (%f)", temperature.read()); - * } - * } - * } - * @endcode -*/ -class FastAnalogIn { - -public: - /** Create a FastAnalogIn, connected to the specified pin - * - * @param pin AnalogIn pin to connect to - * @param enabled Enable the ADC channel (default = true) - */ - FastAnalogIn( PinName pin, bool enabled = true ); - - ~FastAnalogIn( void ) - { - disable(); - } - - /** Enable the ADC channel - * - * @param enabled Bool that is true for enable, false is equivalent to calling disable - */ - void enable(bool enabled = true); - - /** Disable the ADC channel - * - * Disabling unused channels speeds up conversion in used channels. - * When disabled you can still call read, that will do a single conversion (actually two since the first one always returns 0 for unknown reason). - * Then the function blocks until the value is read. This is handy when you sometimes needs a single conversion besides the automatic conversion - */ - void disable( void ); - - /** Returns the raw value - * - * @param return Unsigned integer with converted value - */ - unsigned short read_u16( void ); - - /** Returns the scaled value - * - * @param return Float with scaled converted value to 0.0-1.0 - */ - float read( void ) - { - unsigned short value = read_u16(); - return (float)value * (1.0f/65535.0f); - } - - /** An operator shorthand for read() - */ - operator float() { - return read(); - } - - -private: - bool running; - char ADCnumber; - uint32_t *datareg; -}; -
--- a/camera_api.cpp Mon Jun 30 07:01:58 2014 +0000 +++ b/camera_api.cpp Wed Jul 02 03:23:07 2014 +0000 @@ -1,18 +1,21 @@ #include "mbed.h" #include "camera_api.h" - +#include "TFC.h" #define clk 2 //ms +#define task_ma_time +#ifdef task_ma_time +DigitalOut cam_p(PTE5); +#endif BX_camera::BX_camera(int p) { - + line_CamR = new FastAnalogIn(PTD5); line_CamL= new FastAnalogIn(PTD6,0); cam_clk=new DigitalOut(PTE1); si=new DigitalOut(PTD7); padding = p; } - int BX_camera::black_centerR(void) { @@ -128,95 +131,134 @@ + void BX_camera::read(void) { - + w_f_vL=0x0000; b_f_vL=0xffff; - + w_f_vR=0x0000; b_f_vR=0xffff; - - - - + + + line_CamR->enable(); + *si=1; *cam_clk=1; - + wait_us(30); // tune here *si=0; *cam_clk=0; - - - - line_CamR->enable(); - line_CamL->enable(); - - + + + + + + //input 128 //both - + for(int i=0; i<128; i++) { *cam_clk=1; wait_us(5); - - + + line_imageR[i]=line_CamR->read_u16(); - line_imageL[i]=line_CamL->read_u16(); - + + + + + // big small if(line_imageR[i] > w_f_vR) w_f_vR=line_imageR[i]; else if(line_imageR[i] < b_f_vR ) b_f_vR = line_imageR[i]; - - + + + + + + *cam_clk=0; + wait_us(5); + + + } + line_CamR->disable(); + /* + *si=1; + *cam_clk=1; + + wait_us(30); // tune here + *si=0; + *cam_clk=0; + + + + cam_p=1; + line_CamL->enable(); + for(int i=0; i<128; i++) { + *cam_clk=1; + wait_us(5); + + + + + + + line_imageL[i]=line_CamL->read_u16(); + + // big small + + if(line_imageL[i] > w_f_vL) w_f_vL=line_imageL[i]; else if(line_imageL[i] < b_f_vL ) b_f_vL = line_imageL[i]; - - - - + + + + *cam_clk=0; wait_us(5); - - + + } - - - line_CamR->enable(); - line_CamL->enable(); - - + + + + + line_CamL->disable(); + cam_p=0; + */ //filter L R //may change - + for(int i=0; i<128; i++) { - - + + if( (line_imageR[i]-b_f_vR) < (w_f_vR - line_imageR[i] ) ) sign_line_imageR[i]=' '; else sign_line_imageR[i]='O'; - - + + if( (line_imageL[i]-b_f_vL) < (w_f_vL - line_imageL[i] ) ) sign_line_imageL[i]=' '; else sign_line_imageL[i]='O'; - - - - - + + + + + if(i==0) { sign_line_imageR[i]='X'; sign_line_imageL[i]='X'; } - - + + } - - - + + + } \ No newline at end of file
--- a/camera_api.h Mon Jun 30 07:01:58 2014 +0000 +++ b/camera_api.h Wed Jul 02 03:23:07 2014 +0000 @@ -1,9 +1,9 @@ -#include "bx-adc.h" +#include "BX-adc.h" #include "mbed.h" - - + + //cause same si and clk camR ,camL are synchronous - + class BX_camera{ public: @@ -47,7 +47,7 @@ int padding; - +
--- a/main.cpp Mon Jun 30 07:01:58 2014 +0000 +++ b/main.cpp Wed Jul 02 03:23:07 2014 +0000 @@ -9,11 +9,11 @@ #include "Stack.h" #define Debug_cam_uart -#define L_eye -//#define R_eye +//#define L_eye +#define R_eye #define motor_on #define Pcontroller -#define task_ma_time +//#define task_ma_time #define R_target 64 @@ -21,9 +21,9 @@ -#define t_cam 2 +#define t_cam 6 - +#define black_center 64 Serial pc(USBTX, USBRX); // tx, rx @@ -44,9 +44,10 @@ PID cam_to_M_ctrlr(10.0,118.0,0.046,0.083,0.083-0.046,0.00,0.00,10); #ifdef task_ma_time -DigitalOut cam_p(PTD1); //cam black -DigitalOut servo_p(PTA13); //servo coffee -DigitalOut de_p(PTD3); // red +DigitalOut cam_p(PTE5); //cam black +DigitalOut servo_p(PTE4); //servo coffee +DigitalOut idle_p (PTE3); +//DigitalOut de_p(PTD3); // red #endif TSISensor tsi; @@ -64,8 +65,7 @@ -static int b_r_c=64; -static int b_l_c=64; + static int pre_b_r_c; static double v_motor; @@ -80,37 +80,52 @@ while(true){ #ifdef task_ma_time cam_p=1; - #endif + #endif + cam.read(); - - b_r_c=cam.black_centerR(); - // b_l_c=cam.black_centerL(); - - points.push(b_r_c); - - + #ifdef task_ma_time cam_p=0; #endif + + int b_r_c,b_l_c; + + + b_r_c=cam.black_centerR(); + // b_l_c=cam.black_centerL(); + + //right + // printf("push :%d\r\n",b_r_c); + points.push(b_r_c); + + Thread::wait(t_cam); - + } } // function + + + + + + + + void de_thread(void const *args){ while(1){ #ifdef task_ma_time - de_p=0; + //de_p=0; #endif - + cam.read(); stdio_mutex.lock(); #ifdef Debug_cam_uart #ifdef L_eye @@ -145,18 +160,20 @@ pc.printf("\r\n Rcenter :%d Lcenter : %d servo: %f \r\n",cam.black_centerR(),cam.black_centerL(),v_servo); + pc.printf("stack n: %d",points.available()); + stdio_mutex.unlock(); #ifdef task_ma_time - de_p=1; + //de_p=1; #endif #endif - Thread::wait(1); + Thread::wait(10); } @@ -175,30 +192,44 @@ servo_p=1; #endif - int point; - - for(;points.available()!=0;){ - points.pop(&point); - + int point; + int sum_e=0; + int n_point=0; + n_point=points.available() ; + + for(int i=0;i<n_point;i++){ + points.pop(&point); //algorithm - + + sum_e+=point-black_center; + } - + printf("error :%d compute: %f\r\n",sum_e/n_point, cam_to_M_ctrlr.compute(black_center+sum_e/n_point,R_target)); + + + cam_to_M_ctrlr.compute(black_center+sum_e/n_point,R_target); + // pc.printf("expect :%d \r\n",black_center+sum_e/n_point ); + // pc.printf("angle :%f", cam_to_M_ctrlr.compute(black_center+sum_e/n_point,R_target) ); + servo.set_angle( cam_to_M_ctrlr.compute(black_center+sum_e/n_point,R_target) ); + + // pc.printf("dfdf"); //if(b_r_c!=-1) - v_servo=cam_to_M_ctrlr.compute(b_r_c,R_target); + // v_servo=cam_to_M_ctrlr.compute(b_r_c,R_target); //if(b_l_c!=-1) // v_servo=cam_to_M_ctrlr.compute(b_l_c,L_target); // v_servo=pot2.read(); - servo.set_angle(v_servo); + #ifdef task_ma_time servo_p=0; #endif - Thread::wait(20); + Thread::wait(20); + + } @@ -241,14 +272,21 @@ servo.set_angle(0.055); pc.baud(115200); - /* - while(1){ + + + + //while(1); + + + + + /* while(1){ if(tsi.readPercentage()>0.00011) break; } - */ - + + */ @@ -256,15 +294,27 @@ // Thread thread(ctrl_thread); Thread th_s(servo_thread); // Thread th_m(motor_thread); - // Thread th_de(de_thread); + // Thread th_de(de_thread); + + //Thread dddd(pin2_thread); while(1){ + #ifdef task_ma_time + idle_p=1; + #endif + + + + #ifdef task_ma_time + idle_p=0; + #endif + //idle // stdio_mutex.lock(); // printf("L: %d mid: %d R: %d\r\n",line3[0],line3[1],line3[2]); // stdio_mutex.unlock(); - // Thread::wait(2000); + Thread::wait(1000); }