Official library for the FRDM-TFC shield

Dependents:   TFC-TEST TFC-RACING-DEMO TFC-RACING-DEMO TFC-RACING-FSLMENTORMATTERS ... more

Overview

This library is an example driver for the FRDM-TFC shield that can be used for with MBED compiler. Documentation for the hardware can be found here

https://community.freescale.com/docs/DOC-93914

Note that the current videos on that page pertain to the codewarrior example projects hosted on google code, not the library presented here. While the code is very similiar, there are some differences. New videos will be posted for the MBED libraries as the code bases will eventually merge

Also note that this is just the raw library. The example program that uses the code is here:

http://mbed.org/users/redxeth/code/TFC-TEST/

IMPORTANT

There is a bug with firmware "mbed_if_v2.0_frdm_kl25Z ". It seems to hold the I/O pin PORTC1 (FTM0 - Channel 0 on J10 Pin 12) high. This prevents the PWM signal for one of the motor drivers from working correctly.

Page 4 of the FRDM-LK25Z board shows the OpenSDA connected to this net via resistor R24. Remove this resistor on your freedom board.

This was verified to be in the SDA firmware as the debug firmware used for Codewarrior use (DEBUG-APP_Pemicro_v102.SDA) does not have this issue.

Example Main.cpp

#include "mbed.h"
#include "TFC.h"

 
//This macro is to maintain compatibility with Codewarrior version of the sample.   This version uses the MBED libraries for serial port access
Serial PC(USBTX,USBRX);

#define TERMINAL_PRINTF     PC.printf

 
 //This ticker code is used to maintain compability with the Codewarrior version of the sample.   This code uses an MBED Ticker for background timing.
 
#define NUM_TFC_TICKERS 4

Ticker TFC_TickerObj;
 
volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
 
void TFC_TickerUpdate()
{
    int i;
 
    for(i=0; i<NUM_TFC_TICKERS; i++)
     {
        if(TFC_Ticker[i]<0xFFFFFFFF) 
        {
            TFC_Ticker[i]++;
        }
    }
}
 
 
int main()
{
    uint32_t i,t = 0;
  
    PC.baud(115200);
    TFC_TickerObj.attach_us(&TFC_TickerUpdate,2000);
   
    TFC_Init();
    
    for(;;)
    {      
        //TFC_Task must be called in your main loop.  This keeps certain processing happy (I.E. Serial port queue check)
         //   TFC_Task();

            //This Demo program will look at the middle 2 switch to select one of 4 demo modes.
            //Let's look at the middle 2 switches
            switch((TFC_GetDIP_Switch()>>1)&0x03)
            {
            default:
            case 0 :
                //Demo mode 0 just tests the switches and LED's
                if(TFC_PUSH_BUTTON_0_PRESSED)
                    TFC_BAT_LED0_ON;
                else
                    TFC_BAT_LED0_OFF;
                
                if(TFC_PUSH_BUTTON_1_PRESSED)
                    TFC_BAT_LED3_ON;
                else
                    TFC_BAT_LED3_OFF;
                
                
                if(TFC_GetDIP_Switch()&0x01)
                    TFC_BAT_LED1_ON;
                else
                    TFC_BAT_LED1_OFF;
                
                if(TFC_GetDIP_Switch()&0x08)
                    TFC_BAT_LED2_ON;
                else
                    TFC_BAT_LED2_OFF;
                
                break;
                    
            case 1:
                
                //Demo mode 1 will just move the servos with the on-board potentiometers
                if(TFC_Ticker[0]>=20)
                {
                    TFC_Ticker[0] = 0; //reset the Ticker
                    //Every 20 mSeconds, update the Servos
                    TFC_SetServo(0,TFC_ReadPot(0));
                    TFC_SetServo(1,TFC_ReadPot(1));
                }
                //Let's put a pattern on the LEDs
                if(TFC_Ticker[1] >= 125)
                {
                    TFC_Ticker[1] = 0;
                    t++;
                    if(t>4)
                    {
                        t=0;
                    }           
                    TFC_SetBatteryLED_Level(t);
                }
                
                TFC_SetMotorPWM(0,0); //Make sure motors are off
                TFC_HBRIDGE_DISABLE;
            

                break;
                
            case 2 :
                
                //Demo Mode 2 will use the Pots to make the motors move
                TFC_HBRIDGE_ENABLE;
               
                TFC_SetMotorPWM(TFC_ReadPot(0),TFC_ReadPot(1));
                
                        
                //Let's put a pattern on the LEDs
                if(TFC_Ticker[1] >= 125)
                    {
                        TFC_Ticker[1] = 0;
                            t++;
                            if(t>4)
                            {
                                t=0;
                            }           
                        TFC_SetBatteryLED_Level(t);
                    }
                break;
            
            case 3 :
            
         
                //Demo Mode 3 will be in Freescale Garage Mode.  It will beam data from the Camera to the 
                //Labview Application
                
                
                if(TFC_Ticker[0]>50 && TFC_LineScanImageReady>0)
                    {
                     TFC_Ticker[0] = 0;
                     TFC_LineScanImageReady=0;
                     TERMINAL_PRINTF("\r\n");
                     TERMINAL_PRINTF("L:");
                     
                        if(t==0)
                            t=4;
                        else
                            t--;
                        
                         TFC_SetBatteryLED_Level(t);
                        
                         // camera 1
                         for(i=0;i<128;i++)
                         {
                               TERMINAL_PRINTF("%X,",TFC_LineScanImage0[i]);
                         }
                        
                        // camera 2
                         for(i=0;i<128;i++)
                         {
                                 if(i==127)
                                     TERMINAL_PRINTF("%X\r\n",TFC_LineScanImage1[i]);
                                 else
                                     TERMINAL_PRINTF("%X,",TFC_LineScanImage1[i]);
                           
                         }
                    }
                 
                break;
            }
    }
    
 
}

Implementation Notes

The goal of the this library was to provide an easy to use API for the FRDM-TFC hardware that would give one a good start in getting a car working. There are only a couple of function calls needed to make the components on the care work. The library is implemented as a standard C API. While most of the MBED code is provided as a C++, the decision to use a C only API was done for the following reasons:

  • Some of the advantages of a C++ class really don't apply in this case. Since there would only be a single instance of the class library, there is no reason to wrap the functions in a class.
  • The library tightly integrated to synchronized different components in the interrupts routines. I.E. Camera acquisition is synced to the servo period. To accomplished this we had to write the code in raw C and write our own interrupt routines. Tieing these to a c++ class really didn't make sense.
  • Since many users also use an "offline" compiler, (I.E. Codewarrior) it was a design requirement that the the same code/API could be easy moved to the Codewarrior environment.
  • Even though the MBED libraries provide classes for PWM that could be used for the servos and drive motor controller, we had to write our own code for the internal TPM units as we needed some special features (Different switching frequency on certain channels) that could not be accomplished with the libraries. This is transparent to the end user.

The library uses a number of of resources on the Freedom board. The list below show what the library uses. The user should not use the MBED libraries to talk to those ports/peripherals.

I/O: -

  • PTB0 (Servo Channel 0 - TPM1)
  • PTB1 (Servo Channel 1 - TPM1)
  • PTB8 (Battery LED0)
  • PTB9 (Battery LED1)
  • PTB10 (Battery LED2)
  • PTB11 (Battery LED3)
  • PTD7 (Camera SI)
  • PTE0 (Camera CLK)
  • PTD5 (Camera A0 - ADC_SE6b)
  • PTD6 (Camera A1 - ADC_SE7b)
  • PTE2 DIP Switch 0
  • PTE3 DIP Switch 1
  • PTE4 DIP Switch 2
  • PTE5 DIP Switch 3
  • PTC13 Pushbutton SW1
  • PTC17 Pushbutton SW2
  • PTC3 H-Bridge A - 1 FTM0_CH3
  • PTC4 H-Bridge A - 2 FTM0_CH4
  • PTC1 H-Bridge B - 1 FTM0_CH1
  • PTC2 H-Bridge B - 2 FTM0_CH2
  • PTE21 H-Bridge Enable
  • PTE20 H-Bridge Fault
  • PTE23 H-Bridge A - IFB
  • PTE22 H-Bridge B - IFB
Committer:
redxeth
Date:
Sun Apr 20 00:14:53 2014 +0000
Revision:
7:b34924a05d60
Parent:
3:23cce037011f
Updated SERVO_DEFAULT_PERIOD to be faster (10mS from 20mS) to permit racing.; ; Increase Clock period to compensate so integration time not impacted (from 100 cycles to 200 cycles)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emh203 1:6f37253dab87 1 #include "mbed.h"
emh203 1:6f37253dab87 2 #include "TFC.h"
emh203 1:6f37253dab87 3
redxeth 7:b34924a05d60 4 #define FTM1_CLK_PRESCALE 6 // Prescale Selector value - see comments in Status Control (SC) section for more details
redxeth 7:b34924a05d60 5 #define SERVO_DEFAULT_PERIOD (float)(.010) // Desired Frequency of PWM Signal - Here 50Hz => 20ms period
redxeth 7:b34924a05d60 6 #define TAOS_CLK_COUNT 200 // Number of cycles for CLK Signal on camera
redxeth 7:b34924a05d60 7
emh203 1:6f37253dab87 8 // use these to dial in servo steering to your particular servo
emh203 1:6f37253dab87 9 #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
redxeth 7:b34924a05d60 10 #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
emh203 1:6f37253dab87 11
emh203 1:6f37253dab87 12
emh203 1:6f37253dab87 13 #define FTM0_CLOCK (SystemCoreClock/2)
emh203 1:6f37253dab87 14 #define FTM0_CLK_PRESCALE (0) // Prescale Selector value - see comments in Status Control (SC) section for more details
emh203 1:6f37253dab87 15 #define FTM0_DEFAULT_SWITCHING_FREQUENCY (4000.0)
emh203 1:6f37253dab87 16
emh203 1:6f37253dab87 17 #define ADC_MAX_CODE (4095)
emh203 1:6f37253dab87 18
emh203 1:6f37253dab87 19 #define TAOS_CLK_HIGH PTE->PSOR = (1<<1)
emh203 1:6f37253dab87 20 #define TAOS_CLK_LOW PTE->PCOR = (1<<1)
emh203 1:6f37253dab87 21 #define TAOS_SI_HIGH PTD->PSOR = (1<<7)
emh203 1:6f37253dab87 22 #define TAOS_SI_LOW PTD->PCOR = (1<<7)
emh203 1:6f37253dab87 23
emh203 1:6f37253dab87 24 #define ADC_STATE_INIT 0
emh203 1:6f37253dab87 25 #define ADC_STATE_CAPTURE_POT_0 1
emh203 1:6f37253dab87 26 #define ADC_STATE_CAPTURE_POT_1 2
emh203 1:6f37253dab87 27 #define ADC_STATE_CAPTURE_BATTERY_LEVEL 3
emh203 1:6f37253dab87 28 #define ADC_STATE_CAPTURE_LINE_SCAN 4
emh203 1:6f37253dab87 29
emh203 1:6f37253dab87 30
emh203 1:6f37253dab87 31 #define TFC_POT_0_ADC_CHANNEL 13
emh203 1:6f37253dab87 32 #define TFC_POT_1_ADC_CHANNEL 12
emh203 1:6f37253dab87 33 #define TFC_BAT_SENSE_CHANNEL 4
emh203 1:6f37253dab87 34 #define TFC_LINESCAN0_ADC_CHANNEL 6
emh203 1:6f37253dab87 35 #define TFC_LINESCAN1_ADC_CHANNEL 7
emh203 1:6f37253dab87 36
emh203 1:6f37253dab87 37
emh203 1:6f37253dab87 38 #define ADC0_irq_no 57
emh203 1:6f37253dab87 39 #define ADC1_irq_no 58
emh203 1:6f37253dab87 40
emh203 1:6f37253dab87 41 #define ADC0_CHANA 19 // set to desired ADC0 channel trigger A
emh203 1:6f37253dab87 42 #define ADC0_CHANB 20 // set to desired ADC0 channel trigger B
emh203 1:6f37253dab87 43
emh203 1:6f37253dab87 44 #define ADC1_CHANA 20 // set to desired ADC1 channel trigger A 20 defaults to potentiometer in TWRK60
emh203 1:6f37253dab87 45 #define ADC1_CHANB 20 // set to desired ADC1 channel trigger B
emh203 1:6f37253dab87 46
emh203 1:6f37253dab87 47 #define ADC0_DLYA 0x2000 // ADC0 trigger A delay
emh203 1:6f37253dab87 48 #define ADC0_DLYB 0x4000 // ADC0 trigger B delay
emh203 1:6f37253dab87 49 #define ADC1_DLYA 0x6000 // ADC1 trigger A delay
emh203 1:6f37253dab87 50 #define ADC1_DLYB 0x7fff // ADC1 trigger B delay
emh203 1:6f37253dab87 51
emh203 1:6f37253dab87 52
emh203 1:6f37253dab87 53 #define ADC0A_DONE 0x01
emh203 1:6f37253dab87 54 #define ADC0B_DONE 0x02
emh203 1:6f37253dab87 55 #define ADC1A_DONE 0x04
emh203 1:6f37253dab87 56 #define ADC1B_DONE 0x08
emh203 1:6f37253dab87 57
emh203 1:6f37253dab87 58
emh203 1:6f37253dab87 59 // Bit shifting of bitfiled is already taken into account so
emh203 1:6f37253dab87 60 // bitfiled values are always represented as relative to their position.
emh203 1:6f37253dab87 61
emh203 1:6f37253dab87 62 /************************* #Defines ******************************************/
emh203 1:6f37253dab87 63
emh203 1:6f37253dab87 64 #define A 0x0
emh203 1:6f37253dab87 65 #define B 0x1
emh203 1:6f37253dab87 66
emh203 1:6f37253dab87 67 /////// NOTE: the following defines relate to the ADC register definitions
emh203 1:6f37253dab87 68 /////// and the content follows the reference manual, using the same symbols.
emh203 1:6f37253dab87 69
emh203 1:6f37253dab87 70
emh203 1:6f37253dab87 71 //// ADCSC1 (register)
emh203 1:6f37253dab87 72
emh203 1:6f37253dab87 73 // Conversion Complete (COCO) mask
emh203 1:6f37253dab87 74 #define COCO_COMPLETE ADC_SC1_COCO_MASK
emh203 1:6f37253dab87 75 #define COCO_NOT 0x00
emh203 1:6f37253dab87 76
emh203 1:6f37253dab87 77 // ADC interrupts: enabled, or disabled.
emh203 1:6f37253dab87 78 #define AIEN_ON ADC_SC1_AIEN_MASK
emh203 1:6f37253dab87 79 #define AIEN_OFF 0x00
emh203 1:6f37253dab87 80
emh203 1:6f37253dab87 81 // Differential or Single ended ADC input
emh203 1:6f37253dab87 82 #define DIFF_SINGLE 0x00
emh203 1:6f37253dab87 83 #define DIFF_DIFFERENTIAL ADC_SC1_DIFF_MASK
emh203 1:6f37253dab87 84
emh203 1:6f37253dab87 85 //// ADCCFG1
emh203 1:6f37253dab87 86
emh203 1:6f37253dab87 87 // Power setting of ADC
emh203 1:6f37253dab87 88 #define ADLPC_LOW ADC_CFG1_ADLPC_MASK
emh203 1:6f37253dab87 89 #define ADLPC_NORMAL 0x00
emh203 1:6f37253dab87 90
emh203 1:6f37253dab87 91 // Clock divisor
emh203 1:6f37253dab87 92 #define ADIV_1 0x00
emh203 1:6f37253dab87 93 #define ADIV_2 0x01
emh203 1:6f37253dab87 94 #define ADIV_4 0x02
emh203 1:6f37253dab87 95 #define ADIV_8 0x03
emh203 1:6f37253dab87 96
emh203 1:6f37253dab87 97 // Long samle time, or Short sample time
emh203 1:6f37253dab87 98 #define ADLSMP_LONG ADC_CFG1_ADLSMP_MASK
emh203 1:6f37253dab87 99 #define ADLSMP_SHORT 0x00
emh203 1:6f37253dab87 100
emh203 1:6f37253dab87 101 // How many bits for the conversion? 8, 12, 10, or 16 (single ended).
emh203 1:6f37253dab87 102 #define MODE_8 0x00
emh203 1:6f37253dab87 103 #define MODE_12 0x01
emh203 1:6f37253dab87 104 #define MODE_10 0x02
emh203 1:6f37253dab87 105 #define MODE_16 0x03
emh203 1:6f37253dab87 106
emh203 1:6f37253dab87 107
emh203 1:6f37253dab87 108
emh203 1:6f37253dab87 109 // ADC Input Clock Source choice? Bus clock, Bus clock/2, "altclk", or the
emh203 1:6f37253dab87 110 // ADC's own asynchronous clock for less noise
emh203 1:6f37253dab87 111 #define ADICLK_BUS 0x00
emh203 1:6f37253dab87 112 #define ADICLK_BUS_2 0x01
emh203 1:6f37253dab87 113 #define ADICLK_ALTCLK 0x02
emh203 1:6f37253dab87 114 #define ADICLK_ADACK 0x03
emh203 1:6f37253dab87 115
emh203 1:6f37253dab87 116 //// ADCCFG2
emh203 1:6f37253dab87 117
emh203 1:6f37253dab87 118 // Select between B or A channels
emh203 1:6f37253dab87 119 #define MUXSEL_ADCB ADC_CFG2_MUXSEL_MASK
emh203 1:6f37253dab87 120 #define MUXSEL_ADCA 0x00
emh203 1:6f37253dab87 121
emh203 1:6f37253dab87 122 // Ansync clock output enable: enable, or disable the output of it
emh203 1:6f37253dab87 123 #define ADACKEN_ENABLED ADC_CFG2_ADACKEN_MASK
emh203 1:6f37253dab87 124 #define ADACKEN_DISABLED 0x00
emh203 1:6f37253dab87 125
emh203 1:6f37253dab87 126 // High speed or low speed conversion mode
emh203 1:6f37253dab87 127 #define ADHSC_HISPEED ADC_CFG2_ADHSC_MASK
emh203 1:6f37253dab87 128 #define ADHSC_NORMAL 0x00
emh203 1:6f37253dab87 129
emh203 1:6f37253dab87 130 // Long Sample Time selector: 20, 12, 6, or 2 extra clocks for a longer sample time
emh203 1:6f37253dab87 131 #define ADLSTS_20 0x00
emh203 1:6f37253dab87 132 #define ADLSTS_12 0x01
emh203 1:6f37253dab87 133 #define ADLSTS_6 0x02
emh203 1:6f37253dab87 134 #define ADLSTS_2 0x03
emh203 1:6f37253dab87 135
emh203 1:6f37253dab87 136 ////ADCSC2
emh203 1:6f37253dab87 137
emh203 1:6f37253dab87 138 // Read-only status bit indicating conversion status
emh203 1:6f37253dab87 139 #define ADACT_ACTIVE ADC_SC2_ADACT_MASK
emh203 1:6f37253dab87 140 #define ADACT_INACTIVE 0x00
emh203 1:6f37253dab87 141
emh203 1:6f37253dab87 142 // Trigger for starting conversion: Hardware trigger, or software trigger.
emh203 1:6f37253dab87 143 // For using PDB, the Hardware trigger option is selected.
emh203 1:6f37253dab87 144 #define ADTRG_HW ADC_SC2_ADTRG_MASK
emh203 1:6f37253dab87 145 #define ADTRG_SW 0x00
emh203 1:6f37253dab87 146
emh203 1:6f37253dab87 147 // ADC Compare Function Enable: Disabled, or Enabled.
emh203 1:6f37253dab87 148 #define ACFE_DISABLED 0x00
emh203 1:6f37253dab87 149 #define ACFE_ENABLED ADC_SC2_ACFE_MASK
emh203 1:6f37253dab87 150
emh203 1:6f37253dab87 151 // Compare Function Greater Than Enable: Greater, or Less.
emh203 1:6f37253dab87 152 #define ACFGT_GREATER ADC_SC2_ACFGT_MASK
emh203 1:6f37253dab87 153 #define ACFGT_LESS 0x00
emh203 1:6f37253dab87 154
emh203 1:6f37253dab87 155 // Compare Function Range Enable: Enabled or Disabled.
emh203 1:6f37253dab87 156 #define ACREN_ENABLED ADC_SC2_ACREN_MASK
emh203 1:6f37253dab87 157 #define ACREN_DISABLED 0x00
emh203 1:6f37253dab87 158
emh203 1:6f37253dab87 159 // DMA enable: enabled or disabled.
emh203 1:6f37253dab87 160 #define DMAEN_ENABLED ADC_SC2_DMAEN_MASK
emh203 1:6f37253dab87 161 #define DMAEN_DISABLED 0x00
emh203 1:6f37253dab87 162
emh203 1:6f37253dab87 163 // Voltage Reference selection for the ADC conversions
emh203 1:6f37253dab87 164 // (***not*** the PGA which uses VREFO only).
emh203 1:6f37253dab87 165 // VREFH and VREFL (0) , or VREFO (1).
emh203 1:6f37253dab87 166
emh203 1:6f37253dab87 167 #define REFSEL_EXT 0x00
emh203 1:6f37253dab87 168 #define REFSEL_ALT 0x01
emh203 1:6f37253dab87 169 #define REFSEL_RES 0x02 /* reserved */
emh203 1:6f37253dab87 170 #define REFSEL_RES_EXT 0x03 /* reserved but defaults to Vref */
emh203 1:6f37253dab87 171
emh203 1:6f37253dab87 172 ////ADCSC3
emh203 1:6f37253dab87 173
emh203 1:6f37253dab87 174 // Calibration begin or off
emh203 1:6f37253dab87 175 #define CAL_BEGIN ADC_SC3_CAL_MASK
emh203 1:6f37253dab87 176 #define CAL_OFF 0x00
emh203 1:6f37253dab87 177
emh203 1:6f37253dab87 178 // Status indicating Calibration failed, or normal success
emh203 1:6f37253dab87 179 #define CALF_FAIL ADC_SC3_CALF_MASK
emh203 1:6f37253dab87 180 #define CALF_NORMAL 0x00
emh203 1:6f37253dab87 181
emh203 1:6f37253dab87 182 // ADC to continously convert, or do a sinle conversion
emh203 1:6f37253dab87 183 #define ADCO_CONTINUOUS ADC_SC3_ADCO_MASK
emh203 1:6f37253dab87 184 #define ADCO_SINGLE 0x00
emh203 1:6f37253dab87 185
emh203 1:6f37253dab87 186 // Averaging enabled in the ADC, or not.
emh203 1:6f37253dab87 187 #define AVGE_ENABLED ADC_SC3_AVGE_MASK
emh203 1:6f37253dab87 188 #define AVGE_DISABLED 0x00
emh203 1:6f37253dab87 189
emh203 1:6f37253dab87 190 // How many to average prior to "interrupting" the MCU? 4, 8, 16, or 32
emh203 1:6f37253dab87 191 #define AVGS_4 0x00
emh203 1:6f37253dab87 192 #define AVGS_8 0x01
emh203 1:6f37253dab87 193 #define AVGS_16 0x02
emh203 1:6f37253dab87 194 #define AVGS_32 0x03
emh203 1:6f37253dab87 195
emh203 1:6f37253dab87 196 ////PGA
emh203 1:6f37253dab87 197
emh203 1:6f37253dab87 198 // PGA enabled or not?
emh203 1:6f37253dab87 199 #define PGAEN_ENABLED ADC_PGA_PGAEN_MASK
emh203 1:6f37253dab87 200 #define PGAEN_DISABLED 0x00
emh203 1:6f37253dab87 201
emh203 1:6f37253dab87 202 // Chopper stabilization of the amplifier, or not.
emh203 1:6f37253dab87 203 #define PGACHP_CHOP ADC_PGA_PGACHP_MASK
emh203 1:6f37253dab87 204 #define PGACHP_NOCHOP 0x00
emh203 1:6f37253dab87 205
emh203 1:6f37253dab87 206 // PGA in low power mode, or normal mode.
emh203 1:6f37253dab87 207 #define PGALP_LOW ADC_PGA_PGALP_MASK
emh203 1:6f37253dab87 208 #define PGALP_NORMAL 0x00
emh203 1:6f37253dab87 209
emh203 1:6f37253dab87 210 // Gain of PGA. Selectable from 1 to 64.
emh203 1:6f37253dab87 211 #define PGAG_1 0x00
emh203 1:6f37253dab87 212 #define PGAG_2 0x01
emh203 1:6f37253dab87 213 #define PGAG_4 0x02
emh203 1:6f37253dab87 214 #define PGAG_8 0x03
emh203 1:6f37253dab87 215 #define PGAG_16 0x04
emh203 1:6f37253dab87 216 #define PGAG_32 0x05
emh203 1:6f37253dab87 217 #define PGAG_64 0x06
emh203 1:6f37253dab87 218
emh203 1:6f37253dab87 219
emh203 1:6f37253dab87 220 #define ADC_STATE_INIT 0
emh203 1:6f37253dab87 221 #define ADC_STATE_CAPTURE_POT_0 1
emh203 1:6f37253dab87 222 #define ADC_STATE_CAPTURE_POT_1 2
emh203 1:6f37253dab87 223 #define ADC_STATE_CAPTURE_BATTERY_LEVEL 3
emh203 1:6f37253dab87 224 #define ADC_STATE_CAPTURE_LINE_SCAN 4
emh203 1:6f37253dab87 225
emh203 1:6f37253dab87 226
emh203 1:6f37253dab87 227 /////////// The above values fit into the structure below to select ADC/PGA
emh203 1:6f37253dab87 228 /////////// configuration desired:
emh203 1:6f37253dab87 229
emh203 1:6f37253dab87 230 typedef struct adc_cfg {
emh203 1:6f37253dab87 231 uint8_t CONFIG1;
emh203 1:6f37253dab87 232 uint8_t CONFIG2;
emh203 1:6f37253dab87 233 uint16_t COMPARE1;
emh203 1:6f37253dab87 234 uint16_t COMPARE2;
emh203 1:6f37253dab87 235 uint8_t STATUS2;
emh203 1:6f37253dab87 236 uint8_t STATUS3;
emh203 1:6f37253dab87 237 uint8_t STATUS1A;
emh203 1:6f37253dab87 238 uint8_t STATUS1B;
emh203 1:6f37253dab87 239 uint32_t PGA;
emh203 1:6f37253dab87 240 } *tADC_ConfigPtr, tADC_Config ;
emh203 1:6f37253dab87 241
emh203 1:6f37253dab87 242
emh203 1:6f37253dab87 243 #define CAL_BLK_NUMREC 18
emh203 1:6f37253dab87 244
emh203 1:6f37253dab87 245 typedef struct adc_cal {
emh203 1:6f37253dab87 246
emh203 1:6f37253dab87 247 uint16_t OFS;
emh203 1:6f37253dab87 248 uint16_t PG;
emh203 1:6f37253dab87 249 uint16_t MG;
emh203 1:6f37253dab87 250 uint8_t CLPD;
emh203 1:6f37253dab87 251 uint8_t CLPS;
emh203 1:6f37253dab87 252 uint16_t CLP4;
emh203 1:6f37253dab87 253 uint16_t CLP3;
emh203 1:6f37253dab87 254 uint8_t CLP2;
emh203 1:6f37253dab87 255 uint8_t CLP1;
emh203 1:6f37253dab87 256 uint8_t CLP0;
emh203 1:6f37253dab87 257 uint8_t dummy;
emh203 1:6f37253dab87 258 uint8_t CLMD;
emh203 1:6f37253dab87 259 uint8_t CLMS;
emh203 1:6f37253dab87 260 uint16_t CLM4;
emh203 1:6f37253dab87 261 uint16_t CLM3;
emh203 1:6f37253dab87 262 uint8_t CLM2;
emh203 1:6f37253dab87 263 uint8_t CLM1;
emh203 1:6f37253dab87 264 uint8_t CLM0;
emh203 1:6f37253dab87 265 } tADC_Cal_Blk ;
emh203 1:6f37253dab87 266
emh203 1:6f37253dab87 267 typedef struct ADC_MemMap {
emh203 1:6f37253dab87 268 uint32_t SC1[2]; /**< ADC Status and Control Registers 1, array offset: 0x0, array step: 0x4 */
emh203 1:6f37253dab87 269 uint32_t CFG1; /**< ADC Configuration Register 1, offset: 0x8 */
emh203 1:6f37253dab87 270 uint32_t CFG2; /**< ADC Configuration Register 2, offset: 0xC */
emh203 1:6f37253dab87 271 uint32_t R[2]; /**< ADC Data Result Register, array offset: 0x10, array step: 0x4 */
emh203 1:6f37253dab87 272 uint32_t CV1; /**< Compare Value Registers, offset: 0x18 */
emh203 1:6f37253dab87 273 uint32_t CV2; /**< Compare Value Registers, offset: 0x1C */
emh203 1:6f37253dab87 274 uint32_t SC2; /**< Status and Control Register 2, offset: 0x20 */
emh203 1:6f37253dab87 275 uint32_t SC3; /**< Status and Control Register 3, offset: 0x24 */
emh203 1:6f37253dab87 276 uint32_t OFS; /**< ADC Offset Correction Register, offset: 0x28 */
emh203 1:6f37253dab87 277 uint32_t PG; /**< ADC Plus-Side Gain Register, offset: 0x2C */
emh203 1:6f37253dab87 278 uint32_t MG; /**< ADC Minus-Side Gain Register, offset: 0x30 */
emh203 1:6f37253dab87 279 uint32_t CLPD; /**< ADC Plus-Side General Calibration Value Register, offset: 0x34 */
emh203 1:6f37253dab87 280 uint32_t CLPS; /**< ADC Plus-Side General Calibration Value Register, offset: 0x38 */
emh203 1:6f37253dab87 281 uint32_t CLP4; /**< ADC Plus-Side General Calibration Value Register, offset: 0x3C */
emh203 1:6f37253dab87 282 uint32_t CLP3; /**< ADC Plus-Side General Calibration Value Register, offset: 0x40 */
emh203 1:6f37253dab87 283 uint32_t CLP2; /**< ADC Plus-Side General Calibration Value Register, offset: 0x44 */
emh203 1:6f37253dab87 284 uint32_t CLP1; /**< ADC Plus-Side General Calibration Value Register, offset: 0x48 */
emh203 1:6f37253dab87 285 uint32_t CLP0; /**< ADC Plus-Side General Calibration Value Register, offset: 0x4C */
emh203 1:6f37253dab87 286 uint8_t RESERVED_0[4];
emh203 1:6f37253dab87 287 uint32_t CLMD; /**< ADC Minus-Side General Calibration Value Register, offset: 0x54 */
emh203 1:6f37253dab87 288 uint32_t CLMS; /**< ADC Minus-Side General Calibration Value Register, offset: 0x58 */
emh203 1:6f37253dab87 289 uint32_t CLM4; /**< ADC Minus-Side General Calibration Value Register, offset: 0x5C */
emh203 1:6f37253dab87 290 uint32_t CLM3; /**< ADC Minus-Side General Calibration Value Register, offset: 0x60 */
emh203 1:6f37253dab87 291 uint32_t CLM2; /**< ADC Minus-Side General Calibration Value Register, offset: 0x64 */
emh203 1:6f37253dab87 292 uint32_t CLM1; /**< ADC Minus-Side General Calibration Value Register, offset: 0x68 */
emh203 1:6f37253dab87 293 uint32_t CLM0; /**< ADC Minus-Side General Calibration Value Register, offset: 0x6C */
emh203 1:6f37253dab87 294 } volatile *ADC_MemMapPtr;
emh203 1:6f37253dab87 295
emh203 1:6f37253dab87 296
emh203 1:6f37253dab87 297
emh203 1:6f37253dab87 298 /* ADC - Register accessors */
emh203 1:6f37253dab87 299 #define ADC_SC1_REG(base,index) ((base)->SC1[index])
emh203 1:6f37253dab87 300 #define ADC_CFG1_REG(base) ((base)->CFG1)
emh203 1:6f37253dab87 301 #define ADC_CFG2_REG(base) ((base)->CFG2)
emh203 1:6f37253dab87 302 #define ADC_R_REG(base,index) ((base)->R[index])
emh203 1:6f37253dab87 303 #define ADC_CV1_REG(base) ((base)->CV1)
emh203 1:6f37253dab87 304 #define ADC_CV2_REG(base) ((base)->CV2)
emh203 1:6f37253dab87 305 #define ADC_SC2_REG(base) ((base)->SC2)
emh203 1:6f37253dab87 306 #define ADC_SC3_REG(base) ((base)->SC3)
emh203 1:6f37253dab87 307 #define ADC_OFS_REG(base) ((base)->OFS)
emh203 1:6f37253dab87 308 #define ADC_PG_REG(base) ((base)->PG)
emh203 1:6f37253dab87 309 #define ADC_MG_REG(base) ((base)->MG)
emh203 1:6f37253dab87 310 #define ADC_CLPD_REG(base) ((base)->CLPD)
emh203 1:6f37253dab87 311 #define ADC_CLPS_REG(base) ((base)->CLPS)
emh203 1:6f37253dab87 312 #define ADC_CLP4_REG(base) ((base)->CLP4)
emh203 1:6f37253dab87 313 #define ADC_CLP3_REG(base) ((base)->CLP3)
emh203 1:6f37253dab87 314 #define ADC_CLP2_REG(base) ((base)->CLP2)
emh203 1:6f37253dab87 315 #define ADC_CLP1_REG(base) ((base)->CLP1)
emh203 1:6f37253dab87 316 #define ADC_CLP0_REG(base) ((base)->CLP0)
emh203 1:6f37253dab87 317 #define ADC_CLMD_REG(base) ((base)->CLMD)
emh203 1:6f37253dab87 318 #define ADC_CLMS_REG(base) ((base)->CLMS)
emh203 1:6f37253dab87 319 #define ADC_CLM4_REG(base) ((base)->CLM4)
emh203 1:6f37253dab87 320 #define ADC_CLM3_REG(base) ((base)->CLM3)
emh203 1:6f37253dab87 321 #define ADC_CLM2_REG(base) ((base)->CLM2)
emh203 1:6f37253dab87 322 #define ADC_CLM1_REG(base) ((base)->CLM1)
emh203 1:6f37253dab87 323 #define ADC_CLM0_REG(base) ((base)->CLM0)
emh203 1:6f37253dab87 324
emh203 1:6f37253dab87 325 #define ADC0_BASE_PTR ((ADC_MemMapPtr)0x4003B000u)
emh203 1:6f37253dab87 326 /** Array initializer of ADC peripheral base pointers */
emh203 1:6f37253dab87 327 #define ADC_BASE_PTRS { ADC0_BASE_PTR }
emh203 1:6f37253dab87 328
emh203 1:6f37253dab87 329
emh203 1:6f37253dab87 330 float _ServoDutyCycleMin;
emh203 1:6f37253dab87 331 float _ServoDutyCycleMax;
emh203 1:6f37253dab87 332 float _ServoPeriod;
emh203 1:6f37253dab87 333
emh203 1:6f37253dab87 334 volatile uint16_t QueuedServo0Val;
emh203 1:6f37253dab87 335 volatile uint16_t QueuedServo1Val;
emh203 1:6f37253dab87 336
emh203 1:6f37253dab87 337 volatile uint16_t *LineScanImage0WorkingBuffer;
emh203 1:6f37253dab87 338 volatile uint16_t *LineScanImage1WorkingBuffer;
emh203 1:6f37253dab87 339
emh203 1:6f37253dab87 340 volatile uint16_t LineScanImage0Buffer[2][128];
emh203 1:6f37253dab87 341 volatile uint16_t LineScanImage1Buffer[2][128];
emh203 1:6f37253dab87 342 volatile uint8_t LineScanWorkingBuffer;
emh203 1:6f37253dab87 343
emh203 3:23cce037011f 344 volatile uint16_t * TFC_LineScanImage0;
emh203 3:23cce037011f 345 volatile uint16_t * TFC_LineScanImage1;
emh203 3:23cce037011f 346 volatile uint8_t TFC_LineScanImageReady;
emh203 3:23cce037011f 347
emh203 1:6f37253dab87 348 volatile uint16_t PotADC_Value[2];
emh203 1:6f37253dab87 349 volatile uint16_t BatSenseADC_Value;
emh203 1:6f37253dab87 350 volatile uint16_t CurrentADC_State;
emh203 1:6f37253dab87 351 volatile uint8_t CurrentLineScanPixel;
emh203 1:6f37253dab87 352 volatile uint8_t CurrentLineScanChannel;
emh203 1:6f37253dab87 353 volatile uint32_t TFC_ServoTicker;
emh203 3:23cce037011f 354
emh203 1:6f37253dab87 355
emh203 1:6f37253dab87 356 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle);
emh203 1:6f37253dab87 357 void TFC_InitLineScanCamera();
emh203 1:6f37253dab87 358 uint8_t ADC_Cal(ADC_MemMapPtr adcmap);
emh203 1:6f37253dab87 359 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr);
emh203 1:6f37253dab87 360 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk);
emh203 1:6f37253dab87 361 void TFC_InitADC0();
emh203 1:6f37253dab87 362 void TFC_InitADC_System();
emh203 1:6f37253dab87 363 void TFC_GPIO_Init();
emh203 1:6f37253dab87 364 void ADC0_Handler();
emh203 1:6f37253dab87 365 void TPM1_Handler();
emh203 1:6f37253dab87 366
emh203 1:6f37253dab87 367
emh203 1:6f37253dab87 368 void TFC_Init()
emh203 1:6f37253dab87 369 {
emh203 1:6f37253dab87 370
emh203 1:6f37253dab87 371 TFC_GPIO_Init();
emh203 1:6f37253dab87 372
emh203 1:6f37253dab87 373 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!
emh203 1:6f37253dab87 374
emh203 1:6f37253dab87 375 TFC_InitLineScanCamera();
emh203 1:6f37253dab87 376
emh203 1:6f37253dab87 377 TFC_InitServos(SERVO_MIN_PULSE_WIDTH_DEFAULT , SERVO_MAX_PULSE_WIDTH_DEFAULT, SERVO_DEFAULT_PERIOD);
emh203 1:6f37253dab87 378
emh203 1:6f37253dab87 379 TFC_ServoTicker = 0;
emh203 1:6f37253dab87 380
emh203 1:6f37253dab87 381 TFC_InitMotorPWM(FTM0_DEFAULT_SWITCHING_FREQUENCY);
emh203 1:6f37253dab87 382
emh203 1:6f37253dab87 383 }
emh203 1:6f37253dab87 384
emh203 1:6f37253dab87 385
emh203 1:6f37253dab87 386 void TFC_GPIO_Init()
emh203 1:6f37253dab87 387 {
emh203 1:6f37253dab87 388
emh203 1:6f37253dab87 389 //enable Clocks to all ports
emh203 1:6f37253dab87 390
emh203 1:6f37253dab87 391 SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK | SIM_SCGC5_PORTC_MASK | SIM_SCGC5_PORTD_MASK | SIM_SCGC5_PORTE_MASK;
emh203 1:6f37253dab87 392
emh203 1:6f37253dab87 393 //Setup Pins as GPIO
emh203 1:6f37253dab87 394 PORTE->PCR[21] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 395 PORTE->PCR[20] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 396
emh203 1:6f37253dab87 397 //Port for Pushbuttons
emh203 1:6f37253dab87 398 PORTC->PCR[13] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 399 PORTC->PCR[17] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 400
emh203 1:6f37253dab87 401
emh203 1:6f37253dab87 402 //Ports for DIP Switches
emh203 1:6f37253dab87 403 PORTE->PCR[2] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 404 PORTE->PCR[3] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 405 PORTE->PCR[4] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 406 PORTE->PCR[5] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 407
emh203 1:6f37253dab87 408 //Ports for LEDs
emh203 1:6f37253dab87 409 PORTB->PCR[8] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 410 PORTB->PCR[9] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 411 PORTB->PCR[10] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 412 PORTB->PCR[11] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 413
emh203 1:6f37253dab87 414
emh203 1:6f37253dab87 415 //Setup the output pins
emh203 1:6f37253dab87 416 PTE->PDDR = TFC_HBRIDGE_EN_LOC;
emh203 1:6f37253dab87 417 PTB->PDDR = TFC_BAT_LED0_LOC | TFC_BAT_LED1_LOC | TFC_BAT_LED2_LOC | TFC_BAT_LED3_LOC;
emh203 1:6f37253dab87 418
emh203 1:6f37253dab87 419 TFC_SetBatteryLED(0);
emh203 1:6f37253dab87 420 TFC_HBRIDGE_DISABLE;
emh203 1:6f37253dab87 421 }
emh203 1:6f37253dab87 422
emh203 1:6f37253dab87 423 void TFC_SetBatteryLED(uint8_t Value)
emh203 1:6f37253dab87 424 {
emh203 1:6f37253dab87 425 if(Value & 0x01)
emh203 1:6f37253dab87 426 TFC_BAT_LED0_ON;
emh203 1:6f37253dab87 427 else
emh203 1:6f37253dab87 428 TFC_BAT_LED0_OFF;
emh203 1:6f37253dab87 429
emh203 1:6f37253dab87 430 if(Value & 0x02)
emh203 1:6f37253dab87 431 TFC_BAT_LED1_ON;
emh203 1:6f37253dab87 432 else
emh203 1:6f37253dab87 433 TFC_BAT_LED1_OFF;
emh203 1:6f37253dab87 434
emh203 1:6f37253dab87 435 if(Value & 0x04)
emh203 1:6f37253dab87 436 TFC_BAT_LED2_ON;
emh203 1:6f37253dab87 437 else
emh203 1:6f37253dab87 438 TFC_BAT_LED2_OFF;
emh203 1:6f37253dab87 439
emh203 1:6f37253dab87 440 if(Value & 0x08)
emh203 1:6f37253dab87 441 TFC_BAT_LED3_ON;
emh203 1:6f37253dab87 442 else
emh203 1:6f37253dab87 443 TFC_BAT_LED3_OFF;
emh203 1:6f37253dab87 444 }
emh203 1:6f37253dab87 445
emh203 1:6f37253dab87 446 uint8_t TFC_GetDIP_Switch()
emh203 1:6f37253dab87 447 {
emh203 1:6f37253dab87 448 uint8_t DIP_Val=0;
emh203 1:6f37253dab87 449
emh203 1:6f37253dab87 450 DIP_Val = (PTE->PDIR>>2) & 0xF;
emh203 1:6f37253dab87 451
emh203 1:6f37253dab87 452 return DIP_Val;
emh203 1:6f37253dab87 453 }
emh203 1:6f37253dab87 454
emh203 1:6f37253dab87 455 uint8_t TFC_ReadPushButton(uint8_t Index)
emh203 1:6f37253dab87 456 {
emh203 1:6f37253dab87 457 if(Index == 0) {
emh203 1:6f37253dab87 458 return TFC_PUSH_BUTTON_0_PRESSED;
emh203 1:6f37253dab87 459 } else {
emh203 1:6f37253dab87 460 return TFC_PUSH_BUTTON_1_PRESSED;
emh203 1:6f37253dab87 461 }
emh203 1:6f37253dab87 462 }
emh203 1:6f37253dab87 463
emh203 1:6f37253dab87 464 extern "C" void TPM1_IRQHandler()
emh203 1:6f37253dab87 465 {
emh203 1:6f37253dab87 466 //Clear the overflow mask if set. According to the reference manual, we clear by writing a logic one!
emh203 1:6f37253dab87 467 if(TPM1->SC & TPM_SC_TOF_MASK)
emh203 1:6f37253dab87 468 TPM1->SC |= TPM_SC_TOF_MASK;
emh203 1:6f37253dab87 469
emh203 1:6f37253dab87 470 //Dump the queued values to the timer channels
emh203 1:6f37253dab87 471 TPM1->CONTROLS[0].CnV = QueuedServo0Val;
emh203 1:6f37253dab87 472 TPM1->CONTROLS[1].CnV = QueuedServo1Val;
emh203 1:6f37253dab87 473
emh203 1:6f37253dab87 474
emh203 1:6f37253dab87 475 //Prime the next ADC capture cycle
emh203 1:6f37253dab87 476 TAOS_SI_HIGH;
emh203 1:6f37253dab87 477 //Prime the ADC pump and start capturing POT 0
emh203 1:6f37253dab87 478 CurrentADC_State = ADC_STATE_CAPTURE_POT_0;
emh203 1:6f37253dab87 479
emh203 1:6f37253dab87 480 ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
emh203 1:6f37253dab87 481 ADC0->SC1[0] = TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; //Start the State machine at POT0
emh203 1:6f37253dab87 482
emh203 1:6f37253dab87 483 //Flag that a new cervo cycle will start
emh203 1:6f37253dab87 484 if (TFC_ServoTicker < 0xffffffff)//if servo tick less than max value, count up...
emh203 1:6f37253dab87 485 TFC_ServoTicker++;
emh203 1:6f37253dab87 486
emh203 1:6f37253dab87 487 }
emh203 1:6f37253dab87 488
emh203 1:6f37253dab87 489
emh203 1:6f37253dab87 490 void TFC_InitServos(float PulseWidthMin, float PulseWidthMax, float ServoPeriod)
emh203 1:6f37253dab87 491 {
emh203 1:6f37253dab87 492
emh203 1:6f37253dab87 493 SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
emh203 1:6f37253dab87 494
emh203 1:6f37253dab87 495 _ServoPeriod = ServoPeriod;
emh203 1:6f37253dab87 496 _ServoDutyCycleMin = PulseWidthMin/ServoPeriod;
emh203 1:6f37253dab87 497 _ServoDutyCycleMax = PulseWidthMax/ServoPeriod;
emh203 1:6f37253dab87 498
emh203 1:6f37253dab87 499 //Clock Setup for the TPM requires a couple steps.
emh203 1:6f37253dab87 500 SIM->SCGC6 &= ~SIM_SCGC6_TPM1_MASK;
emh203 1:6f37253dab87 501 //1st, set the clock mux
emh203 1:6f37253dab87 502 //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 503 SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012)
emh203 1:6f37253dab87 504 SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
emh203 1:6f37253dab87 505 SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1);
emh203 1:6f37253dab87 506
emh203 1:6f37253dab87 507 //Enable the Clock to the FTM0 Module
emh203 1:6f37253dab87 508 //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 509 SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK;
emh203 1:6f37253dab87 510
emh203 1:6f37253dab87 511 //The TPM Module has Clock. Now set up the peripheral
emh203 1:6f37253dab87 512
emh203 1:6f37253dab87 513 //Blow away the control registers to ensure that the counter is not running
emh203 1:6f37253dab87 514 TPM1->SC = 0;
emh203 1:6f37253dab87 515 TPM1->CONF = 0;
emh203 1:6f37253dab87 516
emh203 1:6f37253dab87 517 //While the counter is disabled we can setup the prescaler
emh203 1:6f37253dab87 518
emh203 1:6f37253dab87 519 TPM1->SC = TPM_SC_PS(FTM1_CLK_PRESCALE);
emh203 1:6f37253dab87 520 TPM1->SC |= TPM_SC_TOIE_MASK; //Enable Interrupts for the Timer Overflow
emh203 1:6f37253dab87 521
emh203 1:6f37253dab87 522 //Setup the mod register to get the correct PWM Period
emh203 1:6f37253dab87 523
emh203 1:6f37253dab87 524 TPM1->MOD = (SystemCoreClock/(1<<(FTM1_CLK_PRESCALE))) * _ServoPeriod;
emh203 1:6f37253dab87 525 //Setup Channels 0 and 1
emh203 1:6f37253dab87 526
emh203 1:6f37253dab87 527 TPM1->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 528 TPM1->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 529
emh203 1:6f37253dab87 530
emh203 1:6f37253dab87 531 //Set the Default duty cycle to servo neutral
emh203 1:6f37253dab87 532 TFC_SetServo(0, 0.0);
emh203 1:6f37253dab87 533 TFC_SetServo(1, 0.0);
emh203 1:6f37253dab87 534
emh203 1:6f37253dab87 535 //Enable the TPM COunter
emh203 1:6f37253dab87 536 TPM1->SC |= TPM_SC_CMOD(1);
emh203 1:6f37253dab87 537
emh203 1:6f37253dab87 538 //Enable TPM1 IRQ on the NVIC
emh203 1:6f37253dab87 539
emh203 1:6f37253dab87 540 //NVIC_SetVector(TPM1_IRQn,(uint32_t)TPM1_Handler);
emh203 1:6f37253dab87 541 NVIC_EnableIRQ(TPM1_IRQn);
emh203 1:6f37253dab87 542
emh203 1:6f37253dab87 543 //Enable the FTM functions on the the port
emh203 1:6f37253dab87 544
emh203 1:6f37253dab87 545 PORTB->PCR[0] = PORT_PCR_MUX(3);
emh203 1:6f37253dab87 546 PORTB->PCR[1] = PORT_PCR_MUX(3);
emh203 1:6f37253dab87 547
emh203 1:6f37253dab87 548 }
emh203 1:6f37253dab87 549
emh203 1:6f37253dab87 550
emh203 1:6f37253dab87 551 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle)
emh203 1:6f37253dab87 552 {
emh203 1:6f37253dab87 553 switch(ServoNumber) {
emh203 1:6f37253dab87 554 default:
emh203 1:6f37253dab87 555 case 0:
emh203 1:6f37253dab87 556
emh203 1:6f37253dab87 557 QueuedServo0Val = TPM1->MOD * DutyCycle;
emh203 1:6f37253dab87 558
emh203 1:6f37253dab87 559 break;
emh203 1:6f37253dab87 560
emh203 1:6f37253dab87 561 case 1:
emh203 1:6f37253dab87 562
emh203 1:6f37253dab87 563 QueuedServo1Val = TPM1->MOD * DutyCycle;
emh203 1:6f37253dab87 564
emh203 1:6f37253dab87 565 break;
emh203 1:6f37253dab87 566 }
emh203 1:6f37253dab87 567 }
emh203 1:6f37253dab87 568
emh203 1:6f37253dab87 569 void TFC_SetServo(uint8_t ServoNumber, float Position)
emh203 1:6f37253dab87 570 {
emh203 1:6f37253dab87 571 TFC_SetServoDutyCycle(ServoNumber ,
emh203 3:23cce037011f 572 ((Position + 1.0)/2) * ((_ServoDutyCycleMax - _ServoDutyCycleMin))+_ServoDutyCycleMin) ;
emh203 1:6f37253dab87 573
emh203 1:6f37253dab87 574 }
emh203 1:6f37253dab87 575
emh203 1:6f37253dab87 576 //********************************************************************************************************
emh203 1:6f37253dab87 577 //********************************************************************************************************
emh203 1:6f37253dab87 578 //********************************************************************************************************
emh203 1:6f37253dab87 579 // _____ _____ ______ _ _ _ _ _____ _______ _____ ____ _ _ _____
emh203 1:6f37253dab87 580 // /\ | __ \ / ____| | ____| | | | \ | |/ ____|__ __|_ _/ __ \| \ | |/ ____|
emh203 1:6f37253dab87 581 // / \ | | | | | | |__ | | | | \| | | | | | || | | | \| | (___
emh203 1:6f37253dab87 582 // / /\ \ | | | | | | __| | | | | . ` | | | | | || | | | . ` |\___ \
emh203 1:6f37253dab87 583 // / ____ \| |__| | |____ | | | |__| | |\ | |____ | | _| || |__| | |\ |____) |
emh203 1:6f37253dab87 584 // /_/ \_\_____/ \_____| |_| \____/|_| \_|\_____| |_| |_____\____/|_| \_|_____/
emh203 1:6f37253dab87 585 // ********************************************************************************************************
emh203 1:6f37253dab87 586 // ********************************************************************************************************
emh203 1:6f37253dab87 587 // ********************************************************************************************************
emh203 1:6f37253dab87 588
emh203 1:6f37253dab87 589
emh203 1:6f37253dab87 590
emh203 1:6f37253dab87 591
emh203 1:6f37253dab87 592
emh203 1:6f37253dab87 593 uint8_t ADC_Cal(ADC_MemMapPtr adcmap)
emh203 1:6f37253dab87 594 {
emh203 1:6f37253dab87 595
emh203 1:6f37253dab87 596 uint16_t cal_var;
emh203 1:6f37253dab87 597
emh203 1:6f37253dab87 598 ADC_SC2_REG(adcmap) &= ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0);
emh203 1:6f37253dab87 599 ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
emh203 1:6f37253dab87 600 ADC_SC3_REG(adcmap) |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) ); // Turn averaging ON and set at max value ( 32 )
emh203 1:6f37253dab87 601
emh203 1:6f37253dab87 602
emh203 1:6f37253dab87 603 ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ; // Start CAL
emh203 1:6f37253dab87 604 while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end
emh203 1:6f37253dab87 605
emh203 1:6f37253dab87 606 if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL ) {
emh203 1:6f37253dab87 607 return(1); // Check for Calibration fail error and return
emh203 1:6f37253dab87 608 }
emh203 1:6f37253dab87 609 // Calculate plus-side calibration
emh203 1:6f37253dab87 610 cal_var = 0x00;
emh203 1:6f37253dab87 611
emh203 1:6f37253dab87 612 cal_var = ADC_CLP0_REG(adcmap);
emh203 1:6f37253dab87 613 cal_var += ADC_CLP1_REG(adcmap);
emh203 1:6f37253dab87 614 cal_var += ADC_CLP2_REG(adcmap);
emh203 1:6f37253dab87 615 cal_var += ADC_CLP3_REG(adcmap);
emh203 1:6f37253dab87 616 cal_var += ADC_CLP4_REG(adcmap);
emh203 1:6f37253dab87 617 cal_var += ADC_CLPS_REG(adcmap);
emh203 1:6f37253dab87 618
emh203 1:6f37253dab87 619 cal_var = cal_var/2;
emh203 1:6f37253dab87 620 cal_var |= 0x8000; // Set MSB
emh203 1:6f37253dab87 621
emh203 1:6f37253dab87 622 ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
emh203 1:6f37253dab87 623
emh203 1:6f37253dab87 624
emh203 1:6f37253dab87 625 // Calculate minus-side calibration
emh203 1:6f37253dab87 626 cal_var = 0x00;
emh203 1:6f37253dab87 627
emh203 1:6f37253dab87 628 cal_var = ADC_CLM0_REG(adcmap);
emh203 1:6f37253dab87 629 cal_var += ADC_CLM1_REG(adcmap);
emh203 1:6f37253dab87 630 cal_var += ADC_CLM2_REG(adcmap);
emh203 1:6f37253dab87 631 cal_var += ADC_CLM3_REG(adcmap);
emh203 1:6f37253dab87 632 cal_var += ADC_CLM4_REG(adcmap);
emh203 1:6f37253dab87 633 cal_var += ADC_CLMS_REG(adcmap);
emh203 1:6f37253dab87 634
emh203 1:6f37253dab87 635 cal_var = cal_var/2;
emh203 1:6f37253dab87 636
emh203 1:6f37253dab87 637 cal_var |= 0x8000; // Set MSB
emh203 1:6f37253dab87 638
emh203 1:6f37253dab87 639 ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var);
emh203 1:6f37253dab87 640
emh203 1:6f37253dab87 641 ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
emh203 1:6f37253dab87 642
emh203 1:6f37253dab87 643 return(0);
emh203 1:6f37253dab87 644 }
emh203 1:6f37253dab87 645
emh203 1:6f37253dab87 646
emh203 1:6f37253dab87 647 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr)
emh203 1:6f37253dab87 648 {
emh203 1:6f37253dab87 649 ADC_CFG1_REG(adcmap) = ADC_CfgPtr->CONFIG1;
emh203 1:6f37253dab87 650 ADC_CFG2_REG(adcmap) = ADC_CfgPtr->CONFIG2;
emh203 1:6f37253dab87 651 ADC_CV1_REG(adcmap) = ADC_CfgPtr->COMPARE1;
emh203 1:6f37253dab87 652 ADC_CV2_REG(adcmap) = ADC_CfgPtr->COMPARE2;
emh203 1:6f37253dab87 653 ADC_SC2_REG(adcmap) = ADC_CfgPtr->STATUS2;
emh203 1:6f37253dab87 654 ADC_SC3_REG(adcmap) = ADC_CfgPtr->STATUS3;
emh203 1:6f37253dab87 655 //ADC_PGA_REG(adcmap) = ADC_CfgPtr->PGA;
emh203 1:6f37253dab87 656 ADC_SC1_REG(adcmap,A)= ADC_CfgPtr->STATUS1A;
emh203 1:6f37253dab87 657 ADC_SC1_REG(adcmap,B)= ADC_CfgPtr->STATUS1B;
emh203 1:6f37253dab87 658 }
emh203 1:6f37253dab87 659
emh203 1:6f37253dab87 660
emh203 1:6f37253dab87 661 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk)
emh203 1:6f37253dab87 662 {
emh203 1:6f37253dab87 663 blk->OFS = ADC_OFS_REG(adcmap);
emh203 1:6f37253dab87 664 blk->PG = ADC_PG_REG(adcmap);
emh203 1:6f37253dab87 665 blk->MG = ADC_MG_REG(adcmap);
emh203 1:6f37253dab87 666 blk->CLPD = ADC_CLPD_REG(adcmap);
emh203 1:6f37253dab87 667 blk->CLPS = ADC_CLPS_REG(adcmap);
emh203 1:6f37253dab87 668 blk->CLP4 = ADC_CLP4_REG(adcmap);
emh203 1:6f37253dab87 669 blk->CLP3 = ADC_CLP3_REG(adcmap);
emh203 1:6f37253dab87 670 blk->CLP2 = ADC_CLP2_REG(adcmap);
emh203 1:6f37253dab87 671 blk->CLP1 = ADC_CLP1_REG(adcmap);
emh203 1:6f37253dab87 672 blk->CLP0 = ADC_CLP0_REG(adcmap);
emh203 1:6f37253dab87 673 blk->CLMD = ADC_CLMD_REG(adcmap);
emh203 1:6f37253dab87 674 blk->CLMS = ADC_CLMS_REG(adcmap);
emh203 1:6f37253dab87 675 blk->CLM4 = ADC_CLM4_REG(adcmap);
emh203 1:6f37253dab87 676 blk->CLM3 = ADC_CLM3_REG(adcmap);
emh203 1:6f37253dab87 677 blk->CLM2 = ADC_CLM2_REG(adcmap);
emh203 1:6f37253dab87 678 blk->CLM1 = ADC_CLM1_REG(adcmap);
emh203 1:6f37253dab87 679 blk->CLM0 = ADC_CLM0_REG(adcmap);
emh203 1:6f37253dab87 680
emh203 1:6f37253dab87 681 }
emh203 1:6f37253dab87 682
emh203 1:6f37253dab87 683
emh203 1:6f37253dab87 684 void TFC_InitADC0()
emh203 1:6f37253dab87 685 {
emh203 1:6f37253dab87 686 tADC_Config Master_Adc0_Config;
emh203 1:6f37253dab87 687
emh203 1:6f37253dab87 688
emh203 1:6f37253dab87 689 SIM->SCGC6 |= (SIM_SCGC6_ADC0_MASK);
emh203 1:6f37253dab87 690
emh203 1:6f37253dab87 691 //Lets calibrate the ADC. 1st setup how the channel will be used.
emh203 1:6f37253dab87 692
emh203 1:6f37253dab87 693
emh203 1:6f37253dab87 694 Master_Adc0_Config.CONFIG1 = ADLPC_NORMAL //No low power mode
emh203 1:6f37253dab87 695 | ADC_CFG1_ADIV(ADIV_4) //divide input by 4
emh203 1:6f37253dab87 696 | ADLSMP_LONG //long sample time
emh203 1:6f37253dab87 697 | ADC_CFG1_MODE(MODE_12)//single ended 8-bit conversion
emh203 1:6f37253dab87 698 | ADC_CFG1_ADICLK(ADICLK_BUS);
emh203 1:6f37253dab87 699
emh203 1:6f37253dab87 700 Master_Adc0_Config.CONFIG2 = MUXSEL_ADCA // select the A side of the ADC channel.
emh203 1:6f37253dab87 701 | ADACKEN_DISABLED
emh203 1:6f37253dab87 702 | ADHSC_HISPEED
emh203 1:6f37253dab87 703 | ADC_CFG2_ADLSTS(ADLSTS_2);//Extra long sample Time (20 extra clocks)
emh203 1:6f37253dab87 704
emh203 1:6f37253dab87 705
emh203 1:6f37253dab87 706 Master_Adc0_Config.COMPARE1 = 00000; // Comparators don't matter for calibration
emh203 1:6f37253dab87 707 Master_Adc0_Config.COMPARE1 = 0xFFFF;
emh203 1:6f37253dab87 708
emh203 1:6f37253dab87 709 Master_Adc0_Config.STATUS2 = ADTRG_HW //hardware triggers for calibration
emh203 1:6f37253dab87 710 | ACFE_DISABLED //disable comparator
emh203 1:6f37253dab87 711 | ACFGT_GREATER
emh203 1:6f37253dab87 712 | ACREN_ENABLED
emh203 1:6f37253dab87 713 | DMAEN_DISABLED //Disable DMA
emh203 1:6f37253dab87 714 | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
emh203 1:6f37253dab87 715
emh203 1:6f37253dab87 716 Master_Adc0_Config.STATUS3 = CAL_OFF
emh203 1:6f37253dab87 717 | ADCO_SINGLE
emh203 1:6f37253dab87 718 | AVGE_ENABLED;
emh203 1:6f37253dab87 719 // | ADC_SC3_AVGS(AVGS_4);
emh203 1:6f37253dab87 720
emh203 1:6f37253dab87 721 Master_Adc0_Config.PGA = 0; // Disable the PGA
emh203 1:6f37253dab87 722
emh203 1:6f37253dab87 723
emh203 1:6f37253dab87 724 // Configure ADC as it will be used, but because ADC_SC1_ADCH is 31,
emh203 1:6f37253dab87 725 // the ADC will be inactive. Channel 31 is just disable function.
emh203 1:6f37253dab87 726 // There really is no channel 31.
emh203 1:6f37253dab87 727
emh203 1:6f37253dab87 728 Master_Adc0_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31);
emh203 1:6f37253dab87 729
emh203 1:6f37253dab87 730
emh203 1:6f37253dab87 731 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config); // config ADC
emh203 1:6f37253dab87 732
emh203 1:6f37253dab87 733 // Calibrate the ADC in the configuration in which it will be used:
emh203 1:6f37253dab87 734 ADC_Cal(ADC0_BASE_PTR); // do the calibration
emh203 1:6f37253dab87 735
emh203 1:6f37253dab87 736
emh203 1:6f37253dab87 737 Master_Adc0_Config.STATUS2 = ACFE_DISABLED //disable comparator
emh203 1:6f37253dab87 738 | ACFGT_GREATER
emh203 1:6f37253dab87 739 | ACREN_ENABLED
emh203 1:6f37253dab87 740 | DMAEN_DISABLED //Disable DMA
emh203 1:6f37253dab87 741 | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
emh203 1:6f37253dab87 742
emh203 1:6f37253dab87 743 Master_Adc0_Config.STATUS3 = CAL_OFF
emh203 1:6f37253dab87 744 | ADCO_SINGLE;
emh203 1:6f37253dab87 745
emh203 1:6f37253dab87 746
emh203 1:6f37253dab87 747
emh203 1:6f37253dab87 748 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config);
emh203 1:6f37253dab87 749 }
emh203 1:6f37253dab87 750
emh203 1:6f37253dab87 751
emh203 1:6f37253dab87 752 void TFC_InitADC_System()
emh203 1:6f37253dab87 753 {
emh203 1:6f37253dab87 754
emh203 1:6f37253dab87 755 TFC_InitADC0();
emh203 1:6f37253dab87 756
emh203 1:6f37253dab87 757
emh203 1:6f37253dab87 758 //All Adc processing of the Pots and linescan will be done in the ADC0 IRQ!
emh203 1:6f37253dab87 759 //A state machine will scan through the channels.
emh203 1:6f37253dab87 760 //This is done to automate the linescan capture on Channel 0 to ensure that timing is very even
emh203 1:6f37253dab87 761 CurrentADC_State = ADC_STATE_INIT;
emh203 1:6f37253dab87 762
emh203 1:6f37253dab87 763 //The pump will be primed with the TPM1 interrupt. upon timeout/interrupt it will set the SI signal high
emh203 1:6f37253dab87 764 //for the camera and then start the conversions for the pots.
emh203 1:6f37253dab87 765
emh203 1:6f37253dab87 766 // NVIC_SetVector(ADC0_IRQn,(uint32_t)ADC0_Handler);
emh203 1:6f37253dab87 767 NVIC_EnableIRQ(ADC0_IRQn);
emh203 1:6f37253dab87 768
emh203 1:6f37253dab87 769 }
emh203 1:6f37253dab87 770
emh203 1:6f37253dab87 771 extern "C" void ADC0_IRQHandler()
emh203 1:6f37253dab87 772 {
emh203 1:6f37253dab87 773 uint8_t Junk;
emh203 1:6f37253dab87 774
emh203 1:6f37253dab87 775 switch(CurrentADC_State) {
emh203 1:6f37253dab87 776 default:
emh203 1:6f37253dab87 777 Junk = ADC0->R[0];
emh203 1:6f37253dab87 778 break;
emh203 1:6f37253dab87 779
emh203 1:6f37253dab87 780 case ADC_STATE_CAPTURE_POT_0:
emh203 1:6f37253dab87 781
emh203 1:6f37253dab87 782 PotADC_Value[0] = ADC0->R[0];
emh203 1:6f37253dab87 783 ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
emh203 1:6f37253dab87 784 ADC0->SC1[0] = TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 785 CurrentADC_State = ADC_STATE_CAPTURE_POT_1;
emh203 1:6f37253dab87 786
emh203 1:6f37253dab87 787 break;
emh203 1:6f37253dab87 788
emh203 1:6f37253dab87 789 case ADC_STATE_CAPTURE_POT_1:
emh203 1:6f37253dab87 790
emh203 1:6f37253dab87 791 PotADC_Value[1] = ADC0->R[0];
emh203 1:6f37253dab87 792 ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
emh203 1:6f37253dab87 793 ADC0->SC1[0] = TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 794 CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL;
emh203 1:6f37253dab87 795
emh203 1:6f37253dab87 796 break;
emh203 1:6f37253dab87 797
emh203 1:6f37253dab87 798 case ADC_STATE_CAPTURE_BATTERY_LEVEL:
emh203 1:6f37253dab87 799
emh203 1:6f37253dab87 800 BatSenseADC_Value = ADC0->R[0];
emh203 1:6f37253dab87 801
emh203 1:6f37253dab87 802 //Now we will start the sequence for the Linescan camera
emh203 1:6f37253dab87 803
emh203 1:6f37253dab87 804 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 805
redxeth 7:b34924a05d60 806 for(Junk = 0; Junk<TAOS_CLK_COUNT/2; Junk++) {
emh203 1:6f37253dab87 807 }
emh203 1:6f37253dab87 808
emh203 1:6f37253dab87 809 TAOS_SI_LOW;
emh203 1:6f37253dab87 810
emh203 1:6f37253dab87 811
emh203 1:6f37253dab87 812 CurrentLineScanPixel = 0;
emh203 1:6f37253dab87 813 CurrentLineScanChannel = 0;
emh203 1:6f37253dab87 814 CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN;
emh203 1:6f37253dab87 815 ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
emh203 1:6f37253dab87 816 ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 817
emh203 1:6f37253dab87 818 break;
emh203 1:6f37253dab87 819
emh203 1:6f37253dab87 820 case ADC_STATE_CAPTURE_LINE_SCAN:
emh203 1:6f37253dab87 821
emh203 1:6f37253dab87 822 if(CurrentLineScanPixel<128) {
emh203 1:6f37253dab87 823 if(CurrentLineScanChannel == 0) {
emh203 1:6f37253dab87 824 LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
emh203 1:6f37253dab87 825 ADC0->SC1[0] = TFC_LINESCAN1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 826 CurrentLineScanChannel = 1;
emh203 1:6f37253dab87 827
emh203 1:6f37253dab87 828 } else {
emh203 1:6f37253dab87 829 LineScanImage1WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
emh203 1:6f37253dab87 830 ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 831 CurrentLineScanChannel = 0;
emh203 1:6f37253dab87 832 CurrentLineScanPixel++;
emh203 1:6f37253dab87 833
emh203 1:6f37253dab87 834 TAOS_CLK_LOW;
redxeth 7:b34924a05d60 835 for(Junk = 0; Junk<TAOS_CLK_COUNT/2; Junk++) {
emh203 1:6f37253dab87 836 }
emh203 1:6f37253dab87 837 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 838
emh203 1:6f37253dab87 839 }
emh203 1:6f37253dab87 840
emh203 1:6f37253dab87 841 } else {
emh203 1:6f37253dab87 842 // done with the capture sequence. we can wait for the PIT0 IRQ to restart
emh203 1:6f37253dab87 843
emh203 1:6f37253dab87 844 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 845
redxeth 7:b34924a05d60 846 for(Junk = 0; Junk<TAOS_CLK_COUNT/2; Junk++) {
emh203 1:6f37253dab87 847 }
emh203 1:6f37253dab87 848
emh203 1:6f37253dab87 849 TAOS_CLK_LOW;
emh203 1:6f37253dab87 850 CurrentADC_State = ADC_STATE_INIT;
emh203 1:6f37253dab87 851
emh203 1:6f37253dab87 852 //swap the buffer
emh203 1:6f37253dab87 853
emh203 1:6f37253dab87 854 if(LineScanWorkingBuffer == 0) {
emh203 1:6f37253dab87 855 LineScanWorkingBuffer = 1;
emh203 1:6f37253dab87 856
emh203 1:6f37253dab87 857 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[1][0];
emh203 1:6f37253dab87 858 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 859
emh203 3:23cce037011f 860 TFC_LineScanImage0 = &LineScanImage0Buffer[0][0];
emh203 3:23cce037011f 861 TFC_LineScanImage1 = &LineScanImage1Buffer[0][0];
emh203 1:6f37253dab87 862 } else {
emh203 1:6f37253dab87 863 LineScanWorkingBuffer = 0;
emh203 1:6f37253dab87 864 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0];
emh203 1:6f37253dab87 865 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0];
emh203 1:6f37253dab87 866
emh203 3:23cce037011f 867 TFC_LineScanImage0 = &LineScanImage0Buffer[1][0];
emh203 3:23cce037011f 868 TFC_LineScanImage1 = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 869 }
emh203 1:6f37253dab87 870
emh203 3:23cce037011f 871 TFC_LineScanImageReady++;
emh203 1:6f37253dab87 872 }
emh203 1:6f37253dab87 873
emh203 1:6f37253dab87 874 break;
emh203 1:6f37253dab87 875 }
emh203 1:6f37253dab87 876
emh203 1:6f37253dab87 877 }
emh203 1:6f37253dab87 878
emh203 1:6f37253dab87 879 void TFC_InitLineScanCamera()
emh203 1:6f37253dab87 880 {
emh203 1:6f37253dab87 881 SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTD_MASK; //Make sure the clock is enabled for PORTE;
emh203 1:6f37253dab87 882 PORTE->PCR[1] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for the CLOCK Signal
emh203 1:6f37253dab87 883 PORTD->PCR[7] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for SI signal
emh203 1:6f37253dab87 884
emh203 1:6f37253dab87 885 PORTD->PCR[5] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
emh203 1:6f37253dab87 886 PORTD->PCR[6] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
emh203 1:6f37253dab87 887
emh203 1:6f37253dab87 888 //Make sure the Clock and SI pins are outputs
emh203 1:6f37253dab87 889 PTD->PDDR |= (1<<7);
emh203 1:6f37253dab87 890 PTE->PDDR |= (1<<1);
emh203 1:6f37253dab87 891
emh203 1:6f37253dab87 892 TAOS_CLK_LOW;
emh203 1:6f37253dab87 893 TAOS_SI_LOW;
emh203 1:6f37253dab87 894
emh203 1:6f37253dab87 895 LineScanWorkingBuffer = 0;
emh203 1:6f37253dab87 896
emh203 1:6f37253dab87 897 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[LineScanWorkingBuffer][0];
emh203 1:6f37253dab87 898 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[LineScanWorkingBuffer][0];
emh203 1:6f37253dab87 899
emh203 3:23cce037011f 900 TFC_LineScanImage0 = &LineScanImage0Buffer[1][0];
emh203 3:23cce037011f 901 TFC_LineScanImage1 = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 902 }
emh203 1:6f37253dab87 903
emh203 1:6f37253dab87 904
emh203 1:6f37253dab87 905
emh203 1:6f37253dab87 906
emh203 1:6f37253dab87 907
emh203 1:6f37253dab87 908 /** 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
emh203 1:6f37253dab87 909 *
emh203 1:6f37253dab87 910 * @param SwitchingFrequency PWM Switching Frequency in floating point format. Pick something between 1000 and 9000. Maybe you can modulate it and make a tune.
emh203 1:6f37253dab87 911 */
emh203 1:6f37253dab87 912 void TFC_InitMotorPWM(float SwitchingFrequency)
emh203 1:6f37253dab87 913 {
emh203 1:6f37253dab87 914 //Clock Setup for the TPM requires a couple steps.
emh203 1:6f37253dab87 915
emh203 1:6f37253dab87 916 //1st, set the clock mux
emh203 1:6f37253dab87 917 //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 3:23cce037011f 918 SIM->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;// We Want MCGPLLCLK/2 (See Page 196 of the KL25 Sub-Family Reference Manual, Rev. 3, September 2012)
emh203 3:23cce037011f 919 SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
emh203 3:23cce037011f 920 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)
emh203 1:6f37253dab87 921
emh203 1:6f37253dab87 922
emh203 1:6f37253dab87 923 //Enable the Clock to the FTM0 Module
emh203 1:6f37253dab87 924 //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 925 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;
emh203 1:6f37253dab87 926
emh203 1:6f37253dab87 927 //The TPM Module has Clock. Now set up the peripheral
emh203 1:6f37253dab87 928
emh203 1:6f37253dab87 929 //Blow away the control registers to ensure that the counter is not running
emh203 1:6f37253dab87 930 TPM0->SC = 0;
emh203 1:6f37253dab87 931 TPM0->CONF = 0;
emh203 1:6f37253dab87 932
emh203 1:6f37253dab87 933 //While the counter is disabled we can setup the prescaler
emh203 1:6f37253dab87 934
emh203 1:6f37253dab87 935 TPM0->SC = TPM_SC_PS(FTM0_CLK_PRESCALE);
emh203 1:6f37253dab87 936
emh203 1:6f37253dab87 937 //Setup the mod register to get the correct PWM Period
emh203 1:6f37253dab87 938
emh203 1:6f37253dab87 939 TPM0->MOD = (uint32_t)((float)(FTM0_CLOCK/(1<<FTM0_CLK_PRESCALE))/SwitchingFrequency);
emh203 1:6f37253dab87 940
emh203 1:6f37253dab87 941 //Setup Channels 0,1,2,3
emh203 1:6f37253dab87 942 TPM0->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 943 TPM0->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
emh203 1:6f37253dab87 944 TPM0->CONTROLS[2].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 945 TPM0->CONTROLS[3].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
emh203 1:6f37253dab87 946
emh203 1:6f37253dab87 947 //Enable the Counter
emh203 1:6f37253dab87 948
emh203 1:6f37253dab87 949 //Set the Default duty cycle to 50% duty cycle
emh203 1:6f37253dab87 950 TFC_SetMotorPWM(0.0,0.0);
emh203 1:6f37253dab87 951
emh203 1:6f37253dab87 952 //Enable the TPM COunter
emh203 1:6f37253dab87 953 TPM0->SC |= TPM_SC_CMOD(1);
emh203 1:6f37253dab87 954
emh203 1:6f37253dab87 955 //Enable the FTM functions on the the port
emh203 1:6f37253dab87 956 PORTC->PCR[1] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 957 PORTC->PCR[2] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 958 PORTC->PCR[3] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 959 PORTC->PCR[4] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 960
emh203 1:6f37253dab87 961 }
emh203 1:6f37253dab87 962
emh203 1:6f37253dab87 963 void TFC_SetMotorPWM(float MotorA , float MotorB)
emh203 1:6f37253dab87 964 {
emh203 1:6f37253dab87 965 if(MotorA>1.0)
emh203 1:6f37253dab87 966 MotorA = 1.0;
emh203 1:6f37253dab87 967 else if(MotorA<-1.0)
emh203 1:6f37253dab87 968 MotorA = -1.0;
emh203 1:6f37253dab87 969
emh203 1:6f37253dab87 970 if(MotorB>1.0)
emh203 1:6f37253dab87 971 MotorB = 1.0;
emh203 1:6f37253dab87 972 else if(MotorB<-1.0)
emh203 1:6f37253dab87 973 MotorB = -1.0;
emh203 1:6f37253dab87 974
emh203 1:6f37253dab87 975 TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0));
emh203 1:6f37253dab87 976 TPM0->CONTROLS[3].CnV = TPM0->CONTROLS[2].CnV;
emh203 1:6f37253dab87 977 TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorB + 1.0)/2.0));
emh203 1:6f37253dab87 978 TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV;
emh203 1:6f37253dab87 979
emh203 1:6f37253dab87 980 }
emh203 1:6f37253dab87 981
emh203 1:6f37253dab87 982 //Pot Reading is Scaled to return a value of -1.0 to 1.0
emh203 1:6f37253dab87 983 float TFC_ReadPot(uint8_t Channel)
emh203 1:6f37253dab87 984 {
emh203 1:6f37253dab87 985 if(Channel == 0)
emh203 1:6f37253dab87 986 return ((float)PotADC_Value[0]/-((float)ADC_MAX_CODE/2.0))+1.0;
emh203 1:6f37253dab87 987 else
emh203 1:6f37253dab87 988 return ((float)PotADC_Value[1]/-((float)ADC_MAX_CODE/2.0))+1.0;
emh203 1:6f37253dab87 989 }
emh203 1:6f37253dab87 990
emh203 1:6f37253dab87 991 float TFC_ReadBatteryVoltage()
emh203 1:6f37253dab87 992 {
emh203 1:6f37253dab87 993 return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0);
emh203 1:6f37253dab87 994 }
emh203 3:23cce037011f 995
emh203 3:23cce037011f 996
emh203 3:23cce037011f 997 void TFC_SetBatteryLED_Level(uint8_t BattLevel)
emh203 3:23cce037011f 998 {
emh203 3:23cce037011f 999 switch(BattLevel)
emh203 3:23cce037011f 1000 {
emh203 3:23cce037011f 1001 default:
emh203 3:23cce037011f 1002 case 0:
emh203 3:23cce037011f 1003 TFC_BAT_LED0_OFF;
emh203 3:23cce037011f 1004 TFC_BAT_LED1_OFF;
emh203 3:23cce037011f 1005 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1006 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1007 break;
emh203 3:23cce037011f 1008
emh203 3:23cce037011f 1009 case 1:
emh203 3:23cce037011f 1010 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1011 TFC_BAT_LED1_OFF;
emh203 3:23cce037011f 1012 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1013 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1014 break;
emh203 3:23cce037011f 1015
emh203 3:23cce037011f 1016 case 2:
emh203 3:23cce037011f 1017 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1018 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1019 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1020 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1021 break;
emh203 3:23cce037011f 1022
emh203 3:23cce037011f 1023 case 3:
emh203 3:23cce037011f 1024 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1025 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1026 TFC_BAT_LED2_ON;
emh203 3:23cce037011f 1027 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1028 break;
emh203 3:23cce037011f 1029
emh203 3:23cce037011f 1030 case 4:
emh203 3:23cce037011f 1031 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1032 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1033 TFC_BAT_LED2_ON;
emh203 3:23cce037011f 1034 TFC_BAT_LED3_ON;
emh203 3:23cce037011f 1035 break;
emh203 3:23cce037011f 1036
emh203 3:23cce037011f 1037 }
emh203 3:23cce037011f 1038 }