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:
emh203
Date:
Wed Jul 17 19:30:14 2013 +0000
Revision:
1:6f37253dab87
Child:
3:23cce037011f
Pulled in code from the TFC library.  This will now be the official spot for FRDM-TFC Code

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