Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Impedance_Fast_Circuitry by
main.cpp
- Committer:
- timmey9
- Date:
- 2015-01-28
- Revision:
- 38:ec3b16c130d7
- Parent:
- 37:8bdc71f3e874
- Child:
- 39:82dc3daecf32
File content as of revision 38:ec3b16c130d7:
// Server code #include "mbed.h" #include <stdio.h> // Analog sampling #include "PeripheralNames.h" #include "PeripheralPins.h" #include "fsl_adc_hal.h" #include "fsl_clock_manager.h" #include "fsl_dspi_hal.h" #include "AngleEncoder.h" #include "dma.h" // Analog sampling #define MAX_FADC 6000000 #define SAMPLING_RATE 10 // In microseconds, so 10 us will be a sampling rate of 100 kHz #define TOTAL_SAMPLES 3 // originally 30000 for 0.3 ms of sampling. #define LAST_SAMPLE_INDEX (TOTAL_SAMPLES-1) // If sampling time is 25 us, then 2000 corresponds to 50 ms #define FIRST_SAMPLE_INDEX 0 #define BEGIN_SAMPLING 0xFFFFFFFF #define WAITING_TO_BEGIN (BEGIN_SAMPLING-1) // for debug purposes Serial pc(USBTX, USBRX); DigitalOut led_red(LED_RED); DigitalOut led_green(LED_GREEN); DigitalOut led_blue(LED_BLUE); AngleEncoder angle_encoder(PTD2, PTD3, PTD1, PTD0, 8, 0, 1000000); // mosi, miso, sclk, cs, bit_width, mode, hz DigitalIn AMT20_A(PTC0); // input for quadrature encoding from angle encoder DigitalIn AMT20_B(PTC1); // input for quadrature encoding from angle encoder // Analog sampling AnalogIn A0_pin(A0); AnalogIn A2_pin(A2); Ticker Sampler; uint32_t current_sample_index = WAITING_TO_BEGIN; uint16_t sample_array1[TOTAL_SAMPLES]; uint16_t sample_array2[TOTAL_SAMPLES]; uint16_t angle_array[TOTAL_SAMPLES]; float currA0 = 0; float currA2 = 0; // Declaration of functions void analog_initialization(PinName pin); void timed_sampling(); // Important globabl variables necessary for the sampling every interval int rotary_count = 0; uint32_t last_AMT20_AB_read = 0; using namespace std; int main() { led_blue = 1; led_green = 1; led_red = 1; pc.baud(230400); pc.printf("Starting\r\n"); // Turn on the ADC0 and ADC1 clocks as well as the PDB clocks to test ADC triggered by PDB SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; SIM_SCGC6 |= SIM_SCGC6_PDB_MASK; analog_initialization(A0); //analog_initialization(A2); ADC0->CFG1 |= ADC_CFG1_ADLPC_MASK; // high power mode for faster frequencies //ADC0->SC2 |= ADC_SC2_ADTRG_MASK; // enable hardware trigger SIM_SOPT7 |= 0; // put in continuous conversion mode //pc.printf("ADC0_SC3: %08x\r\n", ADC0->SC3); // enable the DMA ADC0->SC2 |= ADC_SC2_DMAEN_MASK; //ADC1->SC2 |= ADC_SC2_DMAEN_MASK; ADC0->SC3 = 0; // Reset SC3 //ADC1->SC3 = 0; // Reset SC3 dma_init(sample_array1, sample_array2, angle_array, TOTAL_SAMPLES); // initialize the Programmable Delay Block SIM->SCGC6 |= SIM_SCGC6_PDB_MASK; // turn on the clock to the PDB // Configure System Integration Module for defaults as far as ADC SIM_SOPT7 &= ~(SIM_SOPT7_ADC1ALTTRGEN_MASK | // selects PDB not ALT trigger SIM_SOPT7_ADC1PRETRGSEL_MASK | SIM_SOPT7_ADC0ALTTRGEN_MASK | // selects PDB not ALT trigger SIM_SOPT7_ADC0ALTTRGEN_MASK) ; SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // applies only in case of ALT trigger, in which case PDB external pin input trigger for ADC SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // same for both ADCs // Configure the Peripheral Delay Block (PDB): // enable PDB, pdb counter clock = busclock / 20 , continous triggers, sw trigger , and use prescaler too PDB0_SC = PDB_SC_CONT_MASK // Contintuous, rather than one-shot, mode | PDB_SC_PDBEN_MASK // PDB enabled //| PDB_SC_PDBIE_MASK // PDB Interrupt Enable | PDB_SC_PRESCALER(0x5) // Slow down the period of the PDB for testing | PDB_SC_TRGSEL(0xf) // Trigger source is Software Trigger to be invoked in this file | PDB_SC_MULT(2); // Multiplication factor 20 for the prescale divider for the counter clock // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time. PDB0_IDLY = 0x0000; // need to trigger interrupt every counter reset which happens when modulus reached PDB0_MOD = 0xffff; // largest period possible with the slections above, so slow you can see each conversion. // channel 0 pretrigger 0 and 1 enabled and delayed PDB0_CH0C1 = PDB_C1_EN(0x01) | PDB_C1_TOS(0x01) | PDB_C1_EN(0x02) | PDB_C1_TOS(0x02) ; PDB0_CH0DLY0 = 100 ; PDB0_CH0DLY1 = 300 ; // channel 1 pretrigger 0 and 1 enabled and delayed PDB0_CH1C1 = PDB_C1_EN(0x01) | PDB_C1_TOS(0x01) | PDB_C1_EN(0x02) | PDB_C1_TOS(0x02) ; PDB0_CH1DLY0 = 200 ; PDB0_CH1DLY1 = 400 ; PDB0_SC = PDB_SC_CONT_MASK // Contintuous, rather than one-shot, mode | PDB_SC_PDBEN_MASK // PDB enabled | PDB_SC_PDBIE_MASK // PDB Interrupt Enable | PDB_SC_PRESCALER(0x5) // Slow down the period of the PDB for testing | PDB_SC_TRGSEL(0xf) // Trigger source is Software Trigger to be invoked in this file | PDB_SC_MULT(2) // Multiplication factor 20 for the prescale divider for the counter clock | PDB_SC_LDOK_MASK; // Need to ok the loading or it will not load certain regsiters! // the software trigger, PDB_SC_SWTRIG_MASK is not triggered at this time. //PDB configured above ///////////////////////////////////////////////////////////////////////////////////////// //ADC configured below /* // setup the initial ADC default configuration Master_Adc_Config.CONFIG1 = ADLPC_NORMAL | ADC_CFG1_ADIV(ADIV_4) | ADLSMP_LONG | ADC_CFG1_MODE(MODE_16) | ADC_CFG1_ADICLK(ADICLK_BUS); Master_Adc_Config.CONFIG2 = MUXSEL_ADCA | ADACKEN_DISABLED | ADHSC_HISPEED | ADC_CFG2_ADLSTS(ADLSTS_20) ; Master_Adc_Config.COMPARE1 = 0x1234u ; // can be anything Master_Adc_Config.COMPARE2 = 0x5678u ; // can be anything // since not using // compare feature Master_Adc_Config.STATUS2 = ADTRG_HW | ACFE_DISABLED | ACFGT_GREATER | ACREN_ENABLED | DMAEN_DISABLED | ADC_SC2_REFSEL(REFSEL_EXT); Master_Adc_Config.STATUS3 = CAL_OFF | ADCO_SINGLE | AVGE_ENABLED | ADC_SC3_AVGS(AVGS_32); Master_Adc_Config.PGA = PGAEN_DISABLED | PGACHP_NOCHOP | PGALP_NORMAL | ADC_PGA_PGAG(PGAG_64); Master_Adc_Config.STATUS1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); Master_Adc_Config.STATUS1B = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(31); // Configure ADC as it will be used, but becuase ADC_SC1_ADCH is 31, // the ADC will be inactive. Channel 31 is just disable function. // There really is no channel 31. ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC // Calibrate the ADC in the configuration in which it will be used: ADC_Cal(ADC0_BASE_PTR); // do the calibration // The structure still has the desired configuration. So restore it. // Why restore it? The calibration makes some adjustments to the // configuration of the ADC. The are now undone: // config the ADC again to desired conditions ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // REPEAT for BOTH ADC's. However we will only 'use' the results from // the ADC wired to the Potentiometer on the Kinetis Tower Card. // Repeating for ADC1: ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // config ADC ADC_Cal(ADC1_BASE_PTR); // do the calibration // ADC_Read_Cal(ADC1_BASE_PTR,&CalibrationStore[0]); // store the cal // config the ADC again to default conditions ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // ***************************************************************************** // ADC0 and ADC1 using the PDB trigger in ping pong // ***************************************************************************** // use interrupts, single ended mode, and real channel numbers now: Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANA); Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC0_CHANB); ADC_Config_Alt(ADC0_BASE_PTR, &Master_Adc_Config); // config ADC0 Master_Adc_Config.STATUS1A = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANA); Master_Adc_Config.STATUS1B = AIEN_ON | DIFF_SINGLE | ADC_SC1_ADCH(ADC1_CHANB); ADC_Config_Alt(ADC1_BASE_PTR, &Master_Adc_Config); // config ADC1 */ /* PDB0->SC = 0x0100; // DMA enable and Load OK PDB0->MOD = 1000;// the period of the PDB // AOS PDB0->SC |= PDB_SC_CONT_MASK; // run PDB in continuous mode PDB0->SC |= PDB_SC_TRGSEL(7); // set trigger selection to 7 PDB0->SC |= PDB_SC_LDOK_MASK; // load values into the register PDB0->SC |= PDB_SC_PDBEN_MASK; // enables the PDB PDB0->SC |= PDB_SC_SWTRIG_MASK; // enable software trigger (start the PDB) */ PDB0->SC |= PDB_SC_SWTRIG_MASK; // enable software trigger (start the PDB) //pc.printf("SampleArr: %08x\r\n", &sample_array1); //uint16_t* dma_csr = (uint16_t*) 0x4000901C; //uint32_t* dma_daddr = (uint32_t*) 0x40009010; //*dma_csr |= 1; // Start the sampling loop current_sample_index = WAITING_TO_BEGIN; Sampler.attach_us(&timed_sampling, SAMPLING_RATE); pc.printf("\r\n\r\n\r\n"); while(1) { rotary_count++; if(pc.readable() > 0) { char temp = pc.getc(); switch(temp) { case 's': for(int i = 0; i < TOTAL_SAMPLES; i++) pc.printf("%i: %f\t",i,sample_array1[i]*3.3/65535); pc.printf("\r\n"); break; case 'f': for(int i = 0; i < TOTAL_SAMPLES; i++) sample_array1[i] = 0; break; } } for(int i = 0; i < TOTAL_SAMPLES; i++) pc.printf("A%i: %f ",i,sample_array1[i]*3.3/65535); for(int i = 0; i < TOTAL_SAMPLES; i++) pc.printf("B%i: %f ",i,sample_array2[i]*3.3/65535); for(int i = 0; i < TOTAL_SAMPLES; i++) pc.printf("C%i: %i ",i,angle_array[i]); pc.printf("\r"); //pc.printf("DMA_DADDR: %08x \r", *dma_daddr); //pc.printf("A1: %f\tA2: %f\r\n", currA0, currA2); wait(1); } } void timed_sampling() { // Write to SC1A to start conversion with channel 12 PTB2 //ADC0_SC1A = (ADC_SC1_ADCH(ADC_CHANNEL) | (ADC0_SC1A & (ADC_SC1_AIEN_MASK | ADC_SC1_DIFF_MASK))); //__disable_irq(); // Disable Interrupts // The following performs analog-to-digital conversions - first reading the last conversion - then initiating another //uint32_t A0_value = adc_hal_get_conversion_value(0, 0); // ADC0_RA //uint32_t A2_value = adc_hal_get_conversion_value(1, 0); BW_ADC_SC1n_ADCH(0, 0, kAdcChannel12); // This corresponds to starting an ADC conversion on channel 12 of ADC 0 - which is A0 (PTB2) BW_ADC_SC1n_ADCH(1, 0, kAdcChannel14); // This corresponds to starting an ADC conversion on channel 14 of ADC 1 - which is A2 (PTB10) /* currA0 = (float) A0_value*3.3/65535; currA2 = (float) A2_value*3.3/65535; */ // The following updates the rotary counter for the AMT20 sensor // Put A on PTC0 // Put B on PTC1 uint32_t AMT20_AB = HW_GPIO_PDIR_RD(HW_PORTC) & 0x03; if (AMT20_AB != last_AMT20_AB_read) { // change "INVERT_ANGLE" to change whether relative angle counts up or down. if ((AMT20_AB >> 1)^(last_AMT20_AB_read) & 1U) #if INVERT_ANGLE == 1 {rotary_count--;} else {rotary_count++;} #else {rotary_count++;} else {rotary_count--;} #endif last_AMT20_AB_read = AMT20_AB; } /* //current_sample_index = BEGIN_SAMPLING; // Used to force extra time. if (current_sample_index == WAITING_TO_BEGIN) {} else { if (current_sample_index == BEGIN_SAMPLING) { current_sample_index = FIRST_SAMPLE_INDEX; } sample_array1[current_sample_index] = A0_value; sample_array2[current_sample_index] = A2_value; angle_array[current_sample_index] = rotary_count; if (current_sample_index == LAST_SAMPLE_INDEX) { current_sample_index = WAITING_TO_BEGIN; } else { current_sample_index++; } } */ //__enable_irq(); // Enable Interrupts } void analog_initialization(PinName pin) { ADCName adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); // MBED_ASSERT(adc != (ADCName)NC); uint32_t instance = adc >> ADC_INSTANCE_SHIFT; clock_manager_set_gate(kClockModuleADC, instance, true); uint32_t bus_clock; clock_manager_get_frequency(kBusClock, &bus_clock); uint32_t clkdiv; for (clkdiv = 0; clkdiv < 4; clkdiv++) { if ((bus_clock >> clkdiv) <= MAX_FADC) break; } if (clkdiv == 4) { clkdiv = 0x7; //Set max div } // adc is enabled/triggered when reading. adc_hal_set_clock_source_mode(instance, (adc_clock_source_mode_t)(clkdiv >> 2)); adc_hal_set_clock_divider_mode(instance, (adc_clock_divider_mode_t)(clkdiv & 0x3)); adc_hal_set_reference_voltage_mode(instance, kAdcVoltageVref); adc_hal_set_resolution_mode(instance, kAdcSingleDiff16); adc_hal_configure_continuous_conversion(instance, false); // true=continuous conversion mode, false = single conversion mode adc_hal_configure_hw_trigger(instance, false); // true=hw trigger, false=sw trigger adc_hal_configure_hw_average(instance, false); adc_hal_set_hw_average_mode(instance, kAdcHwAverageCount4); adc_hal_set_group_mux(instance, kAdcChannelMuxB); // only B channels are avail pinmap_pinout(pin, PinMap_ADC); } /* // read some registers for some info. uint32_t* dma_cr = (uint32_t*) 0x40008000; pc.printf("DMA_CR: %08x\r\n", *dma_cr); uint32_t* dma_eei = (uint32_t*) 0x40008014; pc.printf("DMA_EEI: %08x\r\n", *dma_eei); uint32_t* dma_erq = (uint32_t*) 0x4000800C; pc.printf("DMA_ERQ: %08x\r\n", *dma_erq); uint16_t* dma_csr = (uint16_t*) 0x4000901C; pc.printf("DMA_TD0_CSR: %04x\r\n\n", *dma_csr); uint32_t* dma_saddr = (uint32_t*) 0x40009000; pc.printf("DMA_SAADR: %08x\r\n", *dma_saddr); uint16_t* dma_soff = (uint16_t*) 0x40009004; pc.printf("DMA_SOFF: %04x\r\n", *dma_soff); uint16_t* dma_attr = (uint16_t*) 0x40009006; pc.printf("DMA_ATTR: %04x\r\n", *dma_attr); uint32_t* dma_minor = (uint32_t*) 0x40009008; pc.printf("DMA_MINOR: %08x\r\n", *dma_minor); uint32_t* dma_daddr = (uint32_t*) 0x40009010; pc.printf("DMA_DADDR: %08x\r\n", *dma_daddr); // read some registers for some info. pc.printf("DMA_CR: %08x\r\n", *dma_cr); pc.printf("DMA_EEI: %08x\r\n", *dma_eei); pc.printf("DMA_ERQ: %08x\r\n", *dma_erq); pc.printf("DMA_TD0_CSR: %04x\r\n\n", *dma_csr); pc.printf("DMA_SAADR: %08x\r\n", *dma_saddr); pc.printf("DMA_SOFF: %04x\r\n", *dma_soff); pc.printf("DMA_ATTR: %04x\r\n", *dma_attr); pc.printf("DMA_MINOR: %08x\r\n", *dma_minor); pc.printf("DMA_DADDR: %08x\r\n", *dma_daddr); pc.printf("SampleArr: %08x\r\n",&sample_array1); */