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:
Thu Aug 15 23:26:19 2013 +0000
Revision:
3:23cce037011f
Parent:
1:6f37253dab87
Child:
7:b34924a05d60
Child:
8:24430a0d7fd8
1.) Fixed issue with Servo duty cycle calculation
; 2.) Verified Case 0,1 2 of the test program (servo steering and drive). The Camera code is OK but there seems to be an issue on my machine with the KL25Z virtual MBED serial port.

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 uint16_t *LineScanImage0WorkingBuffer;
emh203 1:6f37253dab87 336 volatile uint16_t *LineScanImage1WorkingBuffer;
emh203 1:6f37253dab87 337
emh203 1:6f37253dab87 338 volatile uint16_t LineScanImage0Buffer[2][128];
emh203 1:6f37253dab87 339 volatile uint16_t LineScanImage1Buffer[2][128];
emh203 1:6f37253dab87 340 volatile uint8_t LineScanWorkingBuffer;
emh203 1:6f37253dab87 341
emh203 3:23cce037011f 342 volatile uint16_t * TFC_LineScanImage0;
emh203 3:23cce037011f 343 volatile uint16_t * TFC_LineScanImage1;
emh203 3:23cce037011f 344 volatile uint8_t TFC_LineScanImageReady;
emh203 3:23cce037011f 345
emh203 1:6f37253dab87 346 volatile uint16_t PotADC_Value[2];
emh203 1:6f37253dab87 347 volatile uint16_t BatSenseADC_Value;
emh203 1:6f37253dab87 348 volatile uint16_t CurrentADC_State;
emh203 1:6f37253dab87 349 volatile uint8_t CurrentLineScanPixel;
emh203 1:6f37253dab87 350 volatile uint8_t CurrentLineScanChannel;
emh203 1:6f37253dab87 351 volatile uint32_t TFC_ServoTicker;
emh203 3:23cce037011f 352
emh203 1:6f37253dab87 353
emh203 1:6f37253dab87 354 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle);
emh203 1:6f37253dab87 355 void TFC_InitLineScanCamera();
emh203 1:6f37253dab87 356 uint8_t ADC_Cal(ADC_MemMapPtr adcmap);
emh203 1:6f37253dab87 357 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr);
emh203 1:6f37253dab87 358 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk);
emh203 1:6f37253dab87 359 void TFC_InitADC0();
emh203 1:6f37253dab87 360 void TFC_InitADC_System();
emh203 1:6f37253dab87 361 void TFC_GPIO_Init();
emh203 1:6f37253dab87 362 void ADC0_Handler();
emh203 1:6f37253dab87 363 void TPM1_Handler();
emh203 1:6f37253dab87 364
emh203 1:6f37253dab87 365
emh203 1:6f37253dab87 366 void TFC_Init()
emh203 1:6f37253dab87 367 {
emh203 1:6f37253dab87 368
emh203 1:6f37253dab87 369 TFC_GPIO_Init();
emh203 1:6f37253dab87 370
emh203 1:6f37253dab87 371 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 372
emh203 1:6f37253dab87 373 TFC_InitLineScanCamera();
emh203 1:6f37253dab87 374
emh203 1:6f37253dab87 375 TFC_InitServos(SERVO_MIN_PULSE_WIDTH_DEFAULT , SERVO_MAX_PULSE_WIDTH_DEFAULT, SERVO_DEFAULT_PERIOD);
emh203 1:6f37253dab87 376
emh203 1:6f37253dab87 377 TFC_ServoTicker = 0;
emh203 1:6f37253dab87 378
emh203 1:6f37253dab87 379 TFC_InitMotorPWM(FTM0_DEFAULT_SWITCHING_FREQUENCY);
emh203 1:6f37253dab87 380
emh203 1:6f37253dab87 381 }
emh203 1:6f37253dab87 382
emh203 1:6f37253dab87 383
emh203 1:6f37253dab87 384 void TFC_GPIO_Init()
emh203 1:6f37253dab87 385 {
emh203 1:6f37253dab87 386
emh203 1:6f37253dab87 387 //enable Clocks to all ports
emh203 1:6f37253dab87 388
emh203 1:6f37253dab87 389 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 390
emh203 1:6f37253dab87 391 //Setup Pins as GPIO
emh203 1:6f37253dab87 392 PORTE->PCR[21] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 393 PORTE->PCR[20] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 394
emh203 1:6f37253dab87 395 //Port for Pushbuttons
emh203 1:6f37253dab87 396 PORTC->PCR[13] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 397 PORTC->PCR[17] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 398
emh203 1:6f37253dab87 399
emh203 1:6f37253dab87 400 //Ports for DIP Switches
emh203 1:6f37253dab87 401 PORTE->PCR[2] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 402 PORTE->PCR[3] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 403 PORTE->PCR[4] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 404 PORTE->PCR[5] = PORT_PCR_MUX(1);
emh203 1:6f37253dab87 405
emh203 1:6f37253dab87 406 //Ports for LEDs
emh203 1:6f37253dab87 407 PORTB->PCR[8] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 408 PORTB->PCR[9] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 409 PORTB->PCR[10] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 410 PORTB->PCR[11] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;
emh203 1:6f37253dab87 411
emh203 1:6f37253dab87 412
emh203 1:6f37253dab87 413 //Setup the output pins
emh203 1:6f37253dab87 414 PTE->PDDR = TFC_HBRIDGE_EN_LOC;
emh203 1:6f37253dab87 415 PTB->PDDR = TFC_BAT_LED0_LOC | TFC_BAT_LED1_LOC | TFC_BAT_LED2_LOC | TFC_BAT_LED3_LOC;
emh203 1:6f37253dab87 416
emh203 1:6f37253dab87 417 TFC_SetBatteryLED(0);
emh203 1:6f37253dab87 418 TFC_HBRIDGE_DISABLE;
emh203 1:6f37253dab87 419 }
emh203 1:6f37253dab87 420
emh203 1:6f37253dab87 421 void TFC_SetBatteryLED(uint8_t Value)
emh203 1:6f37253dab87 422 {
emh203 1:6f37253dab87 423 if(Value & 0x01)
emh203 1:6f37253dab87 424 TFC_BAT_LED0_ON;
emh203 1:6f37253dab87 425 else
emh203 1:6f37253dab87 426 TFC_BAT_LED0_OFF;
emh203 1:6f37253dab87 427
emh203 1:6f37253dab87 428 if(Value & 0x02)
emh203 1:6f37253dab87 429 TFC_BAT_LED1_ON;
emh203 1:6f37253dab87 430 else
emh203 1:6f37253dab87 431 TFC_BAT_LED1_OFF;
emh203 1:6f37253dab87 432
emh203 1:6f37253dab87 433 if(Value & 0x04)
emh203 1:6f37253dab87 434 TFC_BAT_LED2_ON;
emh203 1:6f37253dab87 435 else
emh203 1:6f37253dab87 436 TFC_BAT_LED2_OFF;
emh203 1:6f37253dab87 437
emh203 1:6f37253dab87 438 if(Value & 0x08)
emh203 1:6f37253dab87 439 TFC_BAT_LED3_ON;
emh203 1:6f37253dab87 440 else
emh203 1:6f37253dab87 441 TFC_BAT_LED3_OFF;
emh203 1:6f37253dab87 442 }
emh203 1:6f37253dab87 443
emh203 1:6f37253dab87 444 uint8_t TFC_GetDIP_Switch()
emh203 1:6f37253dab87 445 {
emh203 1:6f37253dab87 446 uint8_t DIP_Val=0;
emh203 1:6f37253dab87 447
emh203 1:6f37253dab87 448 DIP_Val = (PTE->PDIR>>2) & 0xF;
emh203 1:6f37253dab87 449
emh203 1:6f37253dab87 450 return DIP_Val;
emh203 1:6f37253dab87 451 }
emh203 1:6f37253dab87 452
emh203 1:6f37253dab87 453 uint8_t TFC_ReadPushButton(uint8_t Index)
emh203 1:6f37253dab87 454 {
emh203 1:6f37253dab87 455 if(Index == 0) {
emh203 1:6f37253dab87 456 return TFC_PUSH_BUTTON_0_PRESSED;
emh203 1:6f37253dab87 457 } else {
emh203 1:6f37253dab87 458 return TFC_PUSH_BUTTON_1_PRESSED;
emh203 1:6f37253dab87 459 }
emh203 1:6f37253dab87 460 }
emh203 1:6f37253dab87 461
emh203 1:6f37253dab87 462 extern "C" void TPM1_IRQHandler()
emh203 1:6f37253dab87 463 {
emh203 1:6f37253dab87 464 //Clear the overflow mask if set. According to the reference manual, we clear by writing a logic one!
emh203 1:6f37253dab87 465 if(TPM1->SC & TPM_SC_TOF_MASK)
emh203 1:6f37253dab87 466 TPM1->SC |= TPM_SC_TOF_MASK;
emh203 1:6f37253dab87 467
emh203 1:6f37253dab87 468 //Dump the queued values to the timer channels
emh203 1:6f37253dab87 469 TPM1->CONTROLS[0].CnV = QueuedServo0Val;
emh203 1:6f37253dab87 470 TPM1->CONTROLS[1].CnV = QueuedServo1Val;
emh203 1:6f37253dab87 471
emh203 1:6f37253dab87 472
emh203 1:6f37253dab87 473 //Prime the next ADC capture cycle
emh203 1:6f37253dab87 474 TAOS_SI_HIGH;
emh203 1:6f37253dab87 475 //Prime the ADC pump and start capturing POT 0
emh203 1:6f37253dab87 476 CurrentADC_State = ADC_STATE_CAPTURE_POT_0;
emh203 1:6f37253dab87 477
emh203 1:6f37253dab87 478 ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
emh203 1:6f37253dab87 479 ADC0->SC1[0] = TFC_POT_0_ADC_CHANNEL | ADC_SC1_AIEN_MASK; //Start the State machine at POT0
emh203 1:6f37253dab87 480
emh203 1:6f37253dab87 481 //Flag that a new cervo cycle will start
emh203 1:6f37253dab87 482 if (TFC_ServoTicker < 0xffffffff)//if servo tick less than max value, count up...
emh203 1:6f37253dab87 483 TFC_ServoTicker++;
emh203 1:6f37253dab87 484
emh203 1:6f37253dab87 485 }
emh203 1:6f37253dab87 486
emh203 1:6f37253dab87 487
emh203 1:6f37253dab87 488 void TFC_InitServos(float PulseWidthMin, float PulseWidthMax, float ServoPeriod)
emh203 1:6f37253dab87 489 {
emh203 1:6f37253dab87 490
emh203 1:6f37253dab87 491 SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK;
emh203 1:6f37253dab87 492
emh203 1:6f37253dab87 493 _ServoPeriod = ServoPeriod;
emh203 1:6f37253dab87 494 _ServoDutyCycleMin = PulseWidthMin/ServoPeriod;
emh203 1:6f37253dab87 495 _ServoDutyCycleMax = PulseWidthMax/ServoPeriod;
emh203 1:6f37253dab87 496
emh203 1:6f37253dab87 497 //Clock Setup for the TPM requires a couple steps.
emh203 1:6f37253dab87 498 SIM->SCGC6 &= ~SIM_SCGC6_TPM1_MASK;
emh203 1:6f37253dab87 499 //1st, set the clock mux
emh203 1:6f37253dab87 500 //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 501 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 502 SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
emh203 1:6f37253dab87 503 SIM->SOPT2 |= SIM_SOPT2_TPMSRC(1);
emh203 1:6f37253dab87 504
emh203 1:6f37253dab87 505 //Enable the Clock to the FTM0 Module
emh203 1:6f37253dab87 506 //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 507 SIM->SCGC6 |= SIM_SCGC6_TPM1_MASK;
emh203 1:6f37253dab87 508
emh203 1:6f37253dab87 509 //The TPM Module has Clock. Now set up the peripheral
emh203 1:6f37253dab87 510
emh203 1:6f37253dab87 511 //Blow away the control registers to ensure that the counter is not running
emh203 1:6f37253dab87 512 TPM1->SC = 0;
emh203 1:6f37253dab87 513 TPM1->CONF = 0;
emh203 1:6f37253dab87 514
emh203 1:6f37253dab87 515 //While the counter is disabled we can setup the prescaler
emh203 1:6f37253dab87 516
emh203 1:6f37253dab87 517 TPM1->SC = TPM_SC_PS(FTM1_CLK_PRESCALE);
emh203 1:6f37253dab87 518 TPM1->SC |= TPM_SC_TOIE_MASK; //Enable Interrupts for the Timer Overflow
emh203 1:6f37253dab87 519
emh203 1:6f37253dab87 520 //Setup the mod register to get the correct PWM Period
emh203 1:6f37253dab87 521
emh203 1:6f37253dab87 522 TPM1->MOD = (SystemCoreClock/(1<<(FTM1_CLK_PRESCALE))) * _ServoPeriod;
emh203 1:6f37253dab87 523 //Setup Channels 0 and 1
emh203 1:6f37253dab87 524
emh203 1:6f37253dab87 525 TPM1->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 526 TPM1->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 527
emh203 1:6f37253dab87 528
emh203 1:6f37253dab87 529 //Set the Default duty cycle to servo neutral
emh203 1:6f37253dab87 530 TFC_SetServo(0, 0.0);
emh203 1:6f37253dab87 531 TFC_SetServo(1, 0.0);
emh203 1:6f37253dab87 532
emh203 1:6f37253dab87 533 //Enable the TPM COunter
emh203 1:6f37253dab87 534 TPM1->SC |= TPM_SC_CMOD(1);
emh203 1:6f37253dab87 535
emh203 1:6f37253dab87 536 //Enable TPM1 IRQ on the NVIC
emh203 1:6f37253dab87 537
emh203 1:6f37253dab87 538 //NVIC_SetVector(TPM1_IRQn,(uint32_t)TPM1_Handler);
emh203 1:6f37253dab87 539 NVIC_EnableIRQ(TPM1_IRQn);
emh203 1:6f37253dab87 540
emh203 1:6f37253dab87 541 //Enable the FTM functions on the the port
emh203 1:6f37253dab87 542
emh203 1:6f37253dab87 543 PORTB->PCR[0] = PORT_PCR_MUX(3);
emh203 1:6f37253dab87 544 PORTB->PCR[1] = PORT_PCR_MUX(3);
emh203 1:6f37253dab87 545
emh203 1:6f37253dab87 546 }
emh203 1:6f37253dab87 547
emh203 1:6f37253dab87 548
emh203 1:6f37253dab87 549 void TFC_SetServoDutyCycle(uint8_t ServoNumber, float DutyCycle)
emh203 1:6f37253dab87 550 {
emh203 1:6f37253dab87 551 switch(ServoNumber) {
emh203 1:6f37253dab87 552 default:
emh203 1:6f37253dab87 553 case 0:
emh203 1:6f37253dab87 554
emh203 1:6f37253dab87 555 QueuedServo0Val = TPM1->MOD * DutyCycle;
emh203 1:6f37253dab87 556
emh203 1:6f37253dab87 557 break;
emh203 1:6f37253dab87 558
emh203 1:6f37253dab87 559 case 1:
emh203 1:6f37253dab87 560
emh203 1:6f37253dab87 561 QueuedServo1Val = TPM1->MOD * DutyCycle;
emh203 1:6f37253dab87 562
emh203 1:6f37253dab87 563 break;
emh203 1:6f37253dab87 564 }
emh203 1:6f37253dab87 565 }
emh203 1:6f37253dab87 566
emh203 1:6f37253dab87 567 void TFC_SetServo(uint8_t ServoNumber, float Position)
emh203 1:6f37253dab87 568 {
emh203 1:6f37253dab87 569 TFC_SetServoDutyCycle(ServoNumber ,
emh203 3:23cce037011f 570 ((Position + 1.0)/2) * ((_ServoDutyCycleMax - _ServoDutyCycleMin))+_ServoDutyCycleMin) ;
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
emh203 1:6f37253dab87 589
emh203 1:6f37253dab87 590
emh203 1:6f37253dab87 591 uint8_t ADC_Cal(ADC_MemMapPtr adcmap)
emh203 1:6f37253dab87 592 {
emh203 1:6f37253dab87 593
emh203 1:6f37253dab87 594 uint16_t cal_var;
emh203 1:6f37253dab87 595
emh203 1:6f37253dab87 596 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 597 ADC_SC3_REG(adcmap) &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
emh203 1:6f37253dab87 598 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 599
emh203 1:6f37253dab87 600
emh203 1:6f37253dab87 601 ADC_SC3_REG(adcmap) |= ADC_SC3_CAL_MASK ; // Start CAL
emh203 1:6f37253dab87 602 while ( (ADC_SC1_REG(adcmap,A) & ADC_SC1_COCO_MASK ) == COCO_NOT ); // Wait calibration end
emh203 1:6f37253dab87 603
emh203 1:6f37253dab87 604 if ((ADC_SC3_REG(adcmap)& ADC_SC3_CALF_MASK) == CALF_FAIL ) {
emh203 1:6f37253dab87 605 return(1); // Check for Calibration fail error and return
emh203 1:6f37253dab87 606 }
emh203 1:6f37253dab87 607 // Calculate plus-side calibration
emh203 1:6f37253dab87 608 cal_var = 0x00;
emh203 1:6f37253dab87 609
emh203 1:6f37253dab87 610 cal_var = ADC_CLP0_REG(adcmap);
emh203 1:6f37253dab87 611 cal_var += ADC_CLP1_REG(adcmap);
emh203 1:6f37253dab87 612 cal_var += ADC_CLP2_REG(adcmap);
emh203 1:6f37253dab87 613 cal_var += ADC_CLP3_REG(adcmap);
emh203 1:6f37253dab87 614 cal_var += ADC_CLP4_REG(adcmap);
emh203 1:6f37253dab87 615 cal_var += ADC_CLPS_REG(adcmap);
emh203 1:6f37253dab87 616
emh203 1:6f37253dab87 617 cal_var = cal_var/2;
emh203 1:6f37253dab87 618 cal_var |= 0x8000; // Set MSB
emh203 1:6f37253dab87 619
emh203 1:6f37253dab87 620 ADC_PG_REG(adcmap) = ADC_PG_PG(cal_var);
emh203 1:6f37253dab87 621
emh203 1:6f37253dab87 622
emh203 1:6f37253dab87 623 // Calculate minus-side calibration
emh203 1:6f37253dab87 624 cal_var = 0x00;
emh203 1:6f37253dab87 625
emh203 1:6f37253dab87 626 cal_var = ADC_CLM0_REG(adcmap);
emh203 1:6f37253dab87 627 cal_var += ADC_CLM1_REG(adcmap);
emh203 1:6f37253dab87 628 cal_var += ADC_CLM2_REG(adcmap);
emh203 1:6f37253dab87 629 cal_var += ADC_CLM3_REG(adcmap);
emh203 1:6f37253dab87 630 cal_var += ADC_CLM4_REG(adcmap);
emh203 1:6f37253dab87 631 cal_var += ADC_CLMS_REG(adcmap);
emh203 1:6f37253dab87 632
emh203 1:6f37253dab87 633 cal_var = cal_var/2;
emh203 1:6f37253dab87 634
emh203 1:6f37253dab87 635 cal_var |= 0x8000; // Set MSB
emh203 1:6f37253dab87 636
emh203 1:6f37253dab87 637 ADC_MG_REG(adcmap) = ADC_MG_MG(cal_var);
emh203 1:6f37253dab87 638
emh203 1:6f37253dab87 639 ADC_SC3_REG(adcmap) &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
emh203 1:6f37253dab87 640
emh203 1:6f37253dab87 641 return(0);
emh203 1:6f37253dab87 642 }
emh203 1:6f37253dab87 643
emh203 1:6f37253dab87 644
emh203 1:6f37253dab87 645 void ADC_Config_Alt(ADC_MemMapPtr adcmap, tADC_ConfigPtr ADC_CfgPtr)
emh203 1:6f37253dab87 646 {
emh203 1:6f37253dab87 647 ADC_CFG1_REG(adcmap) = ADC_CfgPtr->CONFIG1;
emh203 1:6f37253dab87 648 ADC_CFG2_REG(adcmap) = ADC_CfgPtr->CONFIG2;
emh203 1:6f37253dab87 649 ADC_CV1_REG(adcmap) = ADC_CfgPtr->COMPARE1;
emh203 1:6f37253dab87 650 ADC_CV2_REG(adcmap) = ADC_CfgPtr->COMPARE2;
emh203 1:6f37253dab87 651 ADC_SC2_REG(adcmap) = ADC_CfgPtr->STATUS2;
emh203 1:6f37253dab87 652 ADC_SC3_REG(adcmap) = ADC_CfgPtr->STATUS3;
emh203 1:6f37253dab87 653 //ADC_PGA_REG(adcmap) = ADC_CfgPtr->PGA;
emh203 1:6f37253dab87 654 ADC_SC1_REG(adcmap,A)= ADC_CfgPtr->STATUS1A;
emh203 1:6f37253dab87 655 ADC_SC1_REG(adcmap,B)= ADC_CfgPtr->STATUS1B;
emh203 1:6f37253dab87 656 }
emh203 1:6f37253dab87 657
emh203 1:6f37253dab87 658
emh203 1:6f37253dab87 659 void ADC_Read_Cal(ADC_MemMapPtr adcmap, tADC_Cal_Blk *blk)
emh203 1:6f37253dab87 660 {
emh203 1:6f37253dab87 661 blk->OFS = ADC_OFS_REG(adcmap);
emh203 1:6f37253dab87 662 blk->PG = ADC_PG_REG(adcmap);
emh203 1:6f37253dab87 663 blk->MG = ADC_MG_REG(adcmap);
emh203 1:6f37253dab87 664 blk->CLPD = ADC_CLPD_REG(adcmap);
emh203 1:6f37253dab87 665 blk->CLPS = ADC_CLPS_REG(adcmap);
emh203 1:6f37253dab87 666 blk->CLP4 = ADC_CLP4_REG(adcmap);
emh203 1:6f37253dab87 667 blk->CLP3 = ADC_CLP3_REG(adcmap);
emh203 1:6f37253dab87 668 blk->CLP2 = ADC_CLP2_REG(adcmap);
emh203 1:6f37253dab87 669 blk->CLP1 = ADC_CLP1_REG(adcmap);
emh203 1:6f37253dab87 670 blk->CLP0 = ADC_CLP0_REG(adcmap);
emh203 1:6f37253dab87 671 blk->CLMD = ADC_CLMD_REG(adcmap);
emh203 1:6f37253dab87 672 blk->CLMS = ADC_CLMS_REG(adcmap);
emh203 1:6f37253dab87 673 blk->CLM4 = ADC_CLM4_REG(adcmap);
emh203 1:6f37253dab87 674 blk->CLM3 = ADC_CLM3_REG(adcmap);
emh203 1:6f37253dab87 675 blk->CLM2 = ADC_CLM2_REG(adcmap);
emh203 1:6f37253dab87 676 blk->CLM1 = ADC_CLM1_REG(adcmap);
emh203 1:6f37253dab87 677 blk->CLM0 = ADC_CLM0_REG(adcmap);
emh203 1:6f37253dab87 678
emh203 1:6f37253dab87 679 }
emh203 1:6f37253dab87 680
emh203 1:6f37253dab87 681
emh203 1:6f37253dab87 682 void TFC_InitADC0()
emh203 1:6f37253dab87 683 {
emh203 1:6f37253dab87 684 tADC_Config Master_Adc0_Config;
emh203 1:6f37253dab87 685
emh203 1:6f37253dab87 686
emh203 1:6f37253dab87 687 SIM->SCGC6 |= (SIM_SCGC6_ADC0_MASK);
emh203 1:6f37253dab87 688
emh203 1:6f37253dab87 689 //Lets calibrate the ADC. 1st setup how the channel will be used.
emh203 1:6f37253dab87 690
emh203 1:6f37253dab87 691
emh203 1:6f37253dab87 692 Master_Adc0_Config.CONFIG1 = ADLPC_NORMAL //No low power mode
emh203 1:6f37253dab87 693 | ADC_CFG1_ADIV(ADIV_4) //divide input by 4
emh203 1:6f37253dab87 694 | ADLSMP_LONG //long sample time
emh203 1:6f37253dab87 695 | ADC_CFG1_MODE(MODE_12)//single ended 8-bit conversion
emh203 1:6f37253dab87 696 | ADC_CFG1_ADICLK(ADICLK_BUS);
emh203 1:6f37253dab87 697
emh203 1:6f37253dab87 698 Master_Adc0_Config.CONFIG2 = MUXSEL_ADCA // select the A side of the ADC channel.
emh203 1:6f37253dab87 699 | ADACKEN_DISABLED
emh203 1:6f37253dab87 700 | ADHSC_HISPEED
emh203 1:6f37253dab87 701 | ADC_CFG2_ADLSTS(ADLSTS_2);//Extra long sample Time (20 extra clocks)
emh203 1:6f37253dab87 702
emh203 1:6f37253dab87 703
emh203 1:6f37253dab87 704 Master_Adc0_Config.COMPARE1 = 00000; // Comparators don't matter for calibration
emh203 1:6f37253dab87 705 Master_Adc0_Config.COMPARE1 = 0xFFFF;
emh203 1:6f37253dab87 706
emh203 1:6f37253dab87 707 Master_Adc0_Config.STATUS2 = ADTRG_HW //hardware triggers for calibration
emh203 1:6f37253dab87 708 | ACFE_DISABLED //disable comparator
emh203 1:6f37253dab87 709 | ACFGT_GREATER
emh203 1:6f37253dab87 710 | ACREN_ENABLED
emh203 1:6f37253dab87 711 | DMAEN_DISABLED //Disable DMA
emh203 1:6f37253dab87 712 | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
emh203 1:6f37253dab87 713
emh203 1:6f37253dab87 714 Master_Adc0_Config.STATUS3 = CAL_OFF
emh203 1:6f37253dab87 715 | ADCO_SINGLE
emh203 1:6f37253dab87 716 | AVGE_ENABLED;
emh203 1:6f37253dab87 717 // | ADC_SC3_AVGS(AVGS_4);
emh203 1:6f37253dab87 718
emh203 1:6f37253dab87 719 Master_Adc0_Config.PGA = 0; // Disable the PGA
emh203 1:6f37253dab87 720
emh203 1:6f37253dab87 721
emh203 1:6f37253dab87 722 // Configure ADC as it will be used, but because ADC_SC1_ADCH is 31,
emh203 1:6f37253dab87 723 // the ADC will be inactive. Channel 31 is just disable function.
emh203 1:6f37253dab87 724 // There really is no channel 31.
emh203 1:6f37253dab87 725
emh203 1:6f37253dab87 726 Master_Adc0_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(31);
emh203 1:6f37253dab87 727
emh203 1:6f37253dab87 728
emh203 1:6f37253dab87 729 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config); // config ADC
emh203 1:6f37253dab87 730
emh203 1:6f37253dab87 731 // Calibrate the ADC in the configuration in which it will be used:
emh203 1:6f37253dab87 732 ADC_Cal(ADC0_BASE_PTR); // do the calibration
emh203 1:6f37253dab87 733
emh203 1:6f37253dab87 734
emh203 1:6f37253dab87 735 Master_Adc0_Config.STATUS2 = ACFE_DISABLED //disable comparator
emh203 1:6f37253dab87 736 | ACFGT_GREATER
emh203 1:6f37253dab87 737 | ACREN_ENABLED
emh203 1:6f37253dab87 738 | DMAEN_DISABLED //Disable DMA
emh203 1:6f37253dab87 739 | ADC_SC2_REFSEL(REFSEL_EXT); //External Reference
emh203 1:6f37253dab87 740
emh203 1:6f37253dab87 741 Master_Adc0_Config.STATUS3 = CAL_OFF
emh203 1:6f37253dab87 742 | ADCO_SINGLE;
emh203 1:6f37253dab87 743
emh203 1:6f37253dab87 744
emh203 1:6f37253dab87 745
emh203 1:6f37253dab87 746 ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc0_Config);
emh203 1:6f37253dab87 747 }
emh203 1:6f37253dab87 748
emh203 1:6f37253dab87 749
emh203 1:6f37253dab87 750 void TFC_InitADC_System()
emh203 1:6f37253dab87 751 {
emh203 1:6f37253dab87 752
emh203 1:6f37253dab87 753 TFC_InitADC0();
emh203 1:6f37253dab87 754
emh203 1:6f37253dab87 755
emh203 1:6f37253dab87 756 //All Adc processing of the Pots and linescan will be done in the ADC0 IRQ!
emh203 1:6f37253dab87 757 //A state machine will scan through the channels.
emh203 1:6f37253dab87 758 //This is done to automate the linescan capture on Channel 0 to ensure that timing is very even
emh203 1:6f37253dab87 759 CurrentADC_State = ADC_STATE_INIT;
emh203 1:6f37253dab87 760
emh203 1:6f37253dab87 761 //The pump will be primed with the TPM1 interrupt. upon timeout/interrupt it will set the SI signal high
emh203 1:6f37253dab87 762 //for the camera and then start the conversions for the pots.
emh203 1:6f37253dab87 763
emh203 1:6f37253dab87 764 // NVIC_SetVector(ADC0_IRQn,(uint32_t)ADC0_Handler);
emh203 1:6f37253dab87 765 NVIC_EnableIRQ(ADC0_IRQn);
emh203 1:6f37253dab87 766
emh203 1:6f37253dab87 767 }
emh203 1:6f37253dab87 768
emh203 1:6f37253dab87 769 extern "C" void ADC0_IRQHandler()
emh203 1:6f37253dab87 770 {
emh203 1:6f37253dab87 771 uint8_t Junk;
emh203 1:6f37253dab87 772
emh203 1:6f37253dab87 773 switch(CurrentADC_State) {
emh203 1:6f37253dab87 774 default:
emh203 1:6f37253dab87 775 Junk = ADC0->R[0];
emh203 1:6f37253dab87 776 break;
emh203 1:6f37253dab87 777
emh203 1:6f37253dab87 778 case ADC_STATE_CAPTURE_POT_0:
emh203 1:6f37253dab87 779
emh203 1:6f37253dab87 780 PotADC_Value[0] = ADC0->R[0];
emh203 1:6f37253dab87 781 ADC0->CFG2 &= ~ADC_CFG2_MUXSEL_MASK; //Select the A side of the mux
emh203 1:6f37253dab87 782 ADC0->SC1[0] = TFC_POT_1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 783 CurrentADC_State = ADC_STATE_CAPTURE_POT_1;
emh203 1:6f37253dab87 784
emh203 1:6f37253dab87 785 break;
emh203 1:6f37253dab87 786
emh203 1:6f37253dab87 787 case ADC_STATE_CAPTURE_POT_1:
emh203 1:6f37253dab87 788
emh203 1:6f37253dab87 789 PotADC_Value[1] = ADC0->R[0];
emh203 1:6f37253dab87 790 ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
emh203 1:6f37253dab87 791 ADC0->SC1[0] = TFC_BAT_SENSE_CHANNEL| ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 792 CurrentADC_State = ADC_STATE_CAPTURE_BATTERY_LEVEL;
emh203 1:6f37253dab87 793
emh203 1:6f37253dab87 794 break;
emh203 1:6f37253dab87 795
emh203 1:6f37253dab87 796 case ADC_STATE_CAPTURE_BATTERY_LEVEL:
emh203 1:6f37253dab87 797
emh203 1:6f37253dab87 798 BatSenseADC_Value = ADC0->R[0];
emh203 1:6f37253dab87 799
emh203 1:6f37253dab87 800 //Now we will start the sequence for the Linescan camera
emh203 1:6f37253dab87 801
emh203 1:6f37253dab87 802 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 803
emh203 1:6f37253dab87 804 for(Junk = 0; Junk<50; Junk++) {
emh203 1:6f37253dab87 805 }
emh203 1:6f37253dab87 806
emh203 1:6f37253dab87 807 TAOS_SI_LOW;
emh203 1:6f37253dab87 808
emh203 1:6f37253dab87 809
emh203 1:6f37253dab87 810 CurrentLineScanPixel = 0;
emh203 1:6f37253dab87 811 CurrentLineScanChannel = 0;
emh203 1:6f37253dab87 812 CurrentADC_State = ADC_STATE_CAPTURE_LINE_SCAN;
emh203 1:6f37253dab87 813 ADC0->CFG2 |= ADC_CFG2_MUXSEL_MASK; //Select the B side of the mux
emh203 1:6f37253dab87 814 ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 815
emh203 1:6f37253dab87 816 break;
emh203 1:6f37253dab87 817
emh203 1:6f37253dab87 818 case ADC_STATE_CAPTURE_LINE_SCAN:
emh203 1:6f37253dab87 819
emh203 1:6f37253dab87 820 if(CurrentLineScanPixel<128) {
emh203 1:6f37253dab87 821 if(CurrentLineScanChannel == 0) {
emh203 1:6f37253dab87 822 LineScanImage0WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
emh203 1:6f37253dab87 823 ADC0->SC1[0] = TFC_LINESCAN1_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 824 CurrentLineScanChannel = 1;
emh203 1:6f37253dab87 825
emh203 1:6f37253dab87 826 } else {
emh203 1:6f37253dab87 827 LineScanImage1WorkingBuffer[CurrentLineScanPixel] = ADC0->R[0];
emh203 1:6f37253dab87 828 ADC0->SC1[0] = TFC_LINESCAN0_ADC_CHANNEL | ADC_SC1_AIEN_MASK;
emh203 1:6f37253dab87 829 CurrentLineScanChannel = 0;
emh203 1:6f37253dab87 830 CurrentLineScanPixel++;
emh203 1:6f37253dab87 831
emh203 1:6f37253dab87 832 TAOS_CLK_LOW;
emh203 1:6f37253dab87 833 for(Junk = 0; Junk<50; Junk++) {
emh203 1:6f37253dab87 834 }
emh203 1:6f37253dab87 835 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 836
emh203 1:6f37253dab87 837 }
emh203 1:6f37253dab87 838
emh203 1:6f37253dab87 839 } else {
emh203 1:6f37253dab87 840 // done with the capture sequence. we can wait for the PIT0 IRQ to restart
emh203 1:6f37253dab87 841
emh203 1:6f37253dab87 842 TAOS_CLK_HIGH;
emh203 1:6f37253dab87 843
emh203 1:6f37253dab87 844 for(Junk = 0; Junk<50; Junk++) {
emh203 1:6f37253dab87 845 }
emh203 1:6f37253dab87 846
emh203 1:6f37253dab87 847 TAOS_CLK_LOW;
emh203 1:6f37253dab87 848 CurrentADC_State = ADC_STATE_INIT;
emh203 1:6f37253dab87 849
emh203 1:6f37253dab87 850 //swap the buffer
emh203 1:6f37253dab87 851
emh203 1:6f37253dab87 852 if(LineScanWorkingBuffer == 0) {
emh203 1:6f37253dab87 853 LineScanWorkingBuffer = 1;
emh203 1:6f37253dab87 854
emh203 1:6f37253dab87 855 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[1][0];
emh203 1:6f37253dab87 856 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 857
emh203 3:23cce037011f 858 TFC_LineScanImage0 = &LineScanImage0Buffer[0][0];
emh203 3:23cce037011f 859 TFC_LineScanImage1 = &LineScanImage1Buffer[0][0];
emh203 1:6f37253dab87 860 } else {
emh203 1:6f37253dab87 861 LineScanWorkingBuffer = 0;
emh203 1:6f37253dab87 862 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[0][0];
emh203 1:6f37253dab87 863 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[0][0];
emh203 1:6f37253dab87 864
emh203 3:23cce037011f 865 TFC_LineScanImage0 = &LineScanImage0Buffer[1][0];
emh203 3:23cce037011f 866 TFC_LineScanImage1 = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 867 }
emh203 1:6f37253dab87 868
emh203 3:23cce037011f 869 TFC_LineScanImageReady++;
emh203 1:6f37253dab87 870 }
emh203 1:6f37253dab87 871
emh203 1:6f37253dab87 872 break;
emh203 1:6f37253dab87 873 }
emh203 1:6f37253dab87 874
emh203 1:6f37253dab87 875 }
emh203 1:6f37253dab87 876
emh203 1:6f37253dab87 877 void TFC_InitLineScanCamera()
emh203 1:6f37253dab87 878 {
emh203 1:6f37253dab87 879 SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK | SIM_SCGC5_PORTD_MASK; //Make sure the clock is enabled for PORTE;
emh203 1:6f37253dab87 880 PORTE->PCR[1] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for the CLOCK Signal
emh203 1:6f37253dab87 881 PORTD->PCR[7] = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; //Enable GPIO on on the pin for SI signal
emh203 1:6f37253dab87 882
emh203 1:6f37253dab87 883 PORTD->PCR[5] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
emh203 1:6f37253dab87 884 PORTD->PCR[6] = PORT_PCR_MUX(0); //Make sure AO signal goes to an analog input
emh203 1:6f37253dab87 885
emh203 1:6f37253dab87 886 //Make sure the Clock and SI pins are outputs
emh203 1:6f37253dab87 887 PTD->PDDR |= (1<<7);
emh203 1:6f37253dab87 888 PTE->PDDR |= (1<<1);
emh203 1:6f37253dab87 889
emh203 1:6f37253dab87 890 TAOS_CLK_LOW;
emh203 1:6f37253dab87 891 TAOS_SI_LOW;
emh203 1:6f37253dab87 892
emh203 1:6f37253dab87 893 LineScanWorkingBuffer = 0;
emh203 1:6f37253dab87 894
emh203 1:6f37253dab87 895 LineScanImage0WorkingBuffer = &LineScanImage0Buffer[LineScanWorkingBuffer][0];
emh203 1:6f37253dab87 896 LineScanImage1WorkingBuffer = &LineScanImage1Buffer[LineScanWorkingBuffer][0];
emh203 1:6f37253dab87 897
emh203 3:23cce037011f 898 TFC_LineScanImage0 = &LineScanImage0Buffer[1][0];
emh203 3:23cce037011f 899 TFC_LineScanImage1 = &LineScanImage1Buffer[1][0];
emh203 1:6f37253dab87 900 }
emh203 1:6f37253dab87 901
emh203 1:6f37253dab87 902
emh203 1:6f37253dab87 903
emh203 1:6f37253dab87 904
emh203 1:6f37253dab87 905
emh203 1:6f37253dab87 906 /** 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 907 *
emh203 1:6f37253dab87 908 * @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 909 */
emh203 1:6f37253dab87 910 void TFC_InitMotorPWM(float SwitchingFrequency)
emh203 1:6f37253dab87 911 {
emh203 1:6f37253dab87 912 //Clock Setup for the TPM requires a couple steps.
emh203 1:6f37253dab87 913
emh203 1:6f37253dab87 914 //1st, set the clock mux
emh203 1:6f37253dab87 915 //See Page 124 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 3:23cce037011f 916 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 917 SIM->SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
emh203 3:23cce037011f 918 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 919
emh203 1:6f37253dab87 920
emh203 1:6f37253dab87 921 //Enable the Clock to the FTM0 Module
emh203 1:6f37253dab87 922 //See Page 207 of f the KL25 Sub-Family Reference Manual, Rev. 3, September 2012
emh203 1:6f37253dab87 923 SIM->SCGC6 |= SIM_SCGC6_TPM0_MASK;
emh203 1:6f37253dab87 924
emh203 1:6f37253dab87 925 //The TPM Module has Clock. Now set up the peripheral
emh203 1:6f37253dab87 926
emh203 1:6f37253dab87 927 //Blow away the control registers to ensure that the counter is not running
emh203 1:6f37253dab87 928 TPM0->SC = 0;
emh203 1:6f37253dab87 929 TPM0->CONF = 0;
emh203 1:6f37253dab87 930
emh203 1:6f37253dab87 931 //While the counter is disabled we can setup the prescaler
emh203 1:6f37253dab87 932
emh203 1:6f37253dab87 933 TPM0->SC = TPM_SC_PS(FTM0_CLK_PRESCALE);
emh203 1:6f37253dab87 934
emh203 1:6f37253dab87 935 //Setup the mod register to get the correct PWM Period
emh203 1:6f37253dab87 936
emh203 1:6f37253dab87 937 TPM0->MOD = (uint32_t)((float)(FTM0_CLOCK/(1<<FTM0_CLK_PRESCALE))/SwitchingFrequency);
emh203 1:6f37253dab87 938
emh203 1:6f37253dab87 939 //Setup Channels 0,1,2,3
emh203 1:6f37253dab87 940 TPM0->CONTROLS[0].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 941 TPM0->CONTROLS[1].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
emh203 1:6f37253dab87 942 TPM0->CONTROLS[2].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK;
emh203 1:6f37253dab87 943 TPM0->CONTROLS[3].CnSC = TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK; // invert the second PWM signal for a complimentary output;
emh203 1:6f37253dab87 944
emh203 1:6f37253dab87 945 //Enable the Counter
emh203 1:6f37253dab87 946
emh203 1:6f37253dab87 947 //Set the Default duty cycle to 50% duty cycle
emh203 1:6f37253dab87 948 TFC_SetMotorPWM(0.0,0.0);
emh203 1:6f37253dab87 949
emh203 1:6f37253dab87 950 //Enable the TPM COunter
emh203 1:6f37253dab87 951 TPM0->SC |= TPM_SC_CMOD(1);
emh203 1:6f37253dab87 952
emh203 1:6f37253dab87 953 //Enable the FTM functions on the the port
emh203 1:6f37253dab87 954 PORTC->PCR[1] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 955 PORTC->PCR[2] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 956 PORTC->PCR[3] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 957 PORTC->PCR[4] = PORT_PCR_MUX(4);
emh203 1:6f37253dab87 958
emh203 1:6f37253dab87 959 }
emh203 1:6f37253dab87 960
emh203 1:6f37253dab87 961 void TFC_SetMotorPWM(float MotorA , float MotorB)
emh203 1:6f37253dab87 962 {
emh203 1:6f37253dab87 963 if(MotorA>1.0)
emh203 1:6f37253dab87 964 MotorA = 1.0;
emh203 1:6f37253dab87 965 else if(MotorA<-1.0)
emh203 1:6f37253dab87 966 MotorA = -1.0;
emh203 1:6f37253dab87 967
emh203 1:6f37253dab87 968 if(MotorB>1.0)
emh203 1:6f37253dab87 969 MotorB = 1.0;
emh203 1:6f37253dab87 970 else if(MotorB<-1.0)
emh203 1:6f37253dab87 971 MotorB = -1.0;
emh203 1:6f37253dab87 972
emh203 1:6f37253dab87 973 TPM0->CONTROLS[2].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorA + 1.0)/2.0));
emh203 1:6f37253dab87 974 TPM0->CONTROLS[3].CnV = TPM0->CONTROLS[2].CnV;
emh203 1:6f37253dab87 975 TPM0->CONTROLS[0].CnV = (uint16_t) ((float)TPM0->MOD * (float)((MotorB + 1.0)/2.0));
emh203 1:6f37253dab87 976 TPM0->CONTROLS[1].CnV = TPM0->CONTROLS[0].CnV;
emh203 1:6f37253dab87 977
emh203 1:6f37253dab87 978 }
emh203 1:6f37253dab87 979
emh203 1:6f37253dab87 980 //Pot Reading is Scaled to return a value of -1.0 to 1.0
emh203 1:6f37253dab87 981 float TFC_ReadPot(uint8_t Channel)
emh203 1:6f37253dab87 982 {
emh203 1:6f37253dab87 983 if(Channel == 0)
emh203 1:6f37253dab87 984 return ((float)PotADC_Value[0]/-((float)ADC_MAX_CODE/2.0))+1.0;
emh203 1:6f37253dab87 985 else
emh203 1:6f37253dab87 986 return ((float)PotADC_Value[1]/-((float)ADC_MAX_CODE/2.0))+1.0;
emh203 1:6f37253dab87 987 }
emh203 1:6f37253dab87 988
emh203 1:6f37253dab87 989 float TFC_ReadBatteryVoltage()
emh203 1:6f37253dab87 990 {
emh203 1:6f37253dab87 991 return (((float)BatSenseADC_Value/(float)(ADC_MAX_CODE)) * 3.0);// * ((47000.0+10000.0)/10000.0);
emh203 1:6f37253dab87 992 }
emh203 3:23cce037011f 993
emh203 3:23cce037011f 994
emh203 3:23cce037011f 995 void TFC_SetBatteryLED_Level(uint8_t BattLevel)
emh203 3:23cce037011f 996 {
emh203 3:23cce037011f 997 switch(BattLevel)
emh203 3:23cce037011f 998 {
emh203 3:23cce037011f 999 default:
emh203 3:23cce037011f 1000 case 0:
emh203 3:23cce037011f 1001 TFC_BAT_LED0_OFF;
emh203 3:23cce037011f 1002 TFC_BAT_LED1_OFF;
emh203 3:23cce037011f 1003 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1004 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1005 break;
emh203 3:23cce037011f 1006
emh203 3:23cce037011f 1007 case 1:
emh203 3:23cce037011f 1008 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1009 TFC_BAT_LED1_OFF;
emh203 3:23cce037011f 1010 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1011 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1012 break;
emh203 3:23cce037011f 1013
emh203 3:23cce037011f 1014 case 2:
emh203 3:23cce037011f 1015 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1016 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1017 TFC_BAT_LED2_OFF;
emh203 3:23cce037011f 1018 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1019 break;
emh203 3:23cce037011f 1020
emh203 3:23cce037011f 1021 case 3:
emh203 3:23cce037011f 1022 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1023 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1024 TFC_BAT_LED2_ON;
emh203 3:23cce037011f 1025 TFC_BAT_LED3_OFF;
emh203 3:23cce037011f 1026 break;
emh203 3:23cce037011f 1027
emh203 3:23cce037011f 1028 case 4:
emh203 3:23cce037011f 1029 TFC_BAT_LED0_ON;
emh203 3:23cce037011f 1030 TFC_BAT_LED1_ON;
emh203 3:23cce037011f 1031 TFC_BAT_LED2_ON;
emh203 3:23cce037011f 1032 TFC_BAT_LED3_ON;
emh203 3:23cce037011f 1033 break;
emh203 3:23cce037011f 1034
emh203 3:23cce037011f 1035 }
emh203 3:23cce037011f 1036 }