/* * Start measuring */ void EFM32_CapSenseSlider::start() { if(_running == false) { CAPLESENSE_Init(true); CAPLESENSE_setupCallbacks((cbptr_t)_scanCallback.entry(), (cbptr_t)_channelCallback.entry()); blockSleepMode(EM2); _running = true; } }
/** Start i2c asynchronous transfer. * @param obj The I2C object * @param tx The buffer to send * @param tx_length The number of words to transmit * @param rx The buffer to receive * @param rx_length The number of words to receive * @param address The address to be set - 7bit or 9 bit * @param stop If true, stop will be generated after the transfer is done * @param handler The I2C IRQ handler to be set * @param hint DMA hint usage */ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) { I2C_TransferReturn_TypeDef retval; if(i2c_active(obj)) return; if((tx_length == 0) && (rx_length == 0)) return; // For now, we are assuming a solely interrupt-driven implementation. // Store transfer config obj->i2c.xfer.addr = address; // Some combination of tx_length and rx_length will tell us what to do if((tx_length > 0) && (rx_length == 0)) { obj->i2c.xfer.flags = I2C_FLAG_WRITE; //Store buffer info obj->i2c.xfer.buf[0].data = (void *)tx; obj->i2c.xfer.buf[0].len = (uint16_t) tx_length; } else if ((tx_length == 0) && (rx_length > 0)) { obj->i2c.xfer.flags = I2C_FLAG_READ; //Store buffer info obj->i2c.xfer.buf[0].data = rx; obj->i2c.xfer.buf[0].len = (uint16_t) rx_length; } else if ((tx_length > 0) && (rx_length > 0)) { obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ; //Store buffer info obj->i2c.xfer.buf[0].data = (void *)tx; obj->i2c.xfer.buf[0].len = (uint16_t) tx_length; obj->i2c.xfer.buf[1].data = rx; obj->i2c.xfer.buf[1].len = (uint16_t) rx_length; } if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR; // Store event flags obj->i2c.events = event; // Enable interrupt i2c_enable_interrupt(obj, handler, true); // Kick off the transfer retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer)); if(retval == i2cTransferInProgress) { blockSleepMode(EM1); } else { // something happened, and the transfer did not go through // So, we need to clean up // Disable interrupt i2c_enable_interrupt(obj, 0, false); // Block until free while(i2c_active(obj)); } }
/* * Function Name: main(); * Description: All the function calls are done in main(). The CPU goes to sleep while in main(); until Interupt is generated. */ int main(void) { CHIP_Init(); CMU_HFRCOBandSet(cmuHFRCOBand_14MHz); CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO); CMU_OscillatorEnable(cmuOsc_HFXO, false, false); blockSleepMode(EM2); //Prevents the CPU to go below EM3 mode. #if DEBUG_ON BSP_TraceSwoSetup(); //For simplicity studio Energy profiler code correlation. #endif LETIMER_setup(); //Initialize LETIMER. ADC_Setup(); //Initialize the ADC DMA_Init(); //Initialize DMA. DMA_Setup(); //Setup DMA. LEUART_Setup(); //Initialize LEUART. GPIO_Init(); //Initialize GPOIs. LETIMER_IntEnable(LETIMER0, LETIMER_IF_UF); //Enable underflow UF interrupt. LEUART_IntEnable(LEUART0, LEUART_IF_SIGF); // Enable SF RXDATAV NVIC_EnableIRQ(LETIMER0_IRQn); //Enable LETIMER0 interrupt vector in NVIC (Nested Vector Interrupt Controller) NVIC_EnableIRQ(LEUART0_IRQn); //Enable LETIMER0 interrupt vector in NVIC (Nested Vector Interrupt Controller) LEUART0->SIGFRAME = '!'; // Set LEUART signal frame to '!' LEUART0->CTRL |= LEUART_CTRL_RXDMAWU; // Enable DMA wake up for LEUART RX in EM2 DMA_ActivateBasic(DMA_CHANNEL_RX, true, false, (void *)RX_Buffer, (void *)&(LEUART0->RXDATA), LEUART0_BUFFER-1); // Enable Sleep-on-Exit #if SLEEPONEXIT SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // Setting the corresponding bit for SleepOnExit #endif while(1) { sleep(); //CPU goes to EM3 Mode to save energy, waits there until Interrupt is generated. } }
/* * Function Name: ADC_setup * Description: Configures ADC0 */ void LEUART_Setup(void) { /* Enabling the required clocks */ CMU_ClockEnable(cmuClock_LFB, true); //Enable the clock input to LETIMER CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); //Selecting the ULFRCO as the source clock CMU_ClockEnable(cmuClock_LEUART0, true); //Enable the clock input to LETIMER /* Defining the LEUART1 initialization data */ LEUART_Init_TypeDef leuart0Init = { .enable = leuartEnable, // Activate data reception on LEUn_TX pin. .refFreq = 0, // Inherit the clock frequency from the LEUART clock source .baudrate = LEUART0_BAUD, // Baudrate = 9600 bps .databits = LEUART0_Databits, // Each LEUART frame contains 8 databits .parity = LEUART0_Parity, // No parity bits in use .stopbits = LEUART0_Stopbits, // Setting the number of stop bits in a frame to 2 bitperiods }; LEUART_Init(LEUART0, &leuart0Init); // Route LEUART1 TX,RX pin to DMA location 0 LEUART0->ROUTE = LEUART_ROUTE_TXPEN | LEUART_ROUTE_RXPEN | LEUART_ROUTE_LOCATION_LOC0; // Enable GPIO for LEUART1. TX is on D4 GPIO_PinModeSet(gpioPortD, 4, gpioModePushPull, 0); // Enable GPIO for LEUART1. RX is on D5 GPIO_PinModeSet(gpioPortD, 5, gpioModeInputPull, 0); // Pull PD15(CTS pin of BLE module) to GRND GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 0); } /* *Function name: LETIMER0_IRQHandler *Description : Interrupt Service Routine for LETIMER. */ void LETIMER0_IRQHandler(void) { LETIMER_IntClear(LETIMER0, LETIMER_IF_UF); //Clear LETIMER0 underflow (UF) and COMP1 flag. DMA_ActivateBasic(DMA_CHANNEL_ADC, true, false, (void *)ADC_Buffer, (void *)&(ADC0->SINGLEDATA), ADC_SAMPLES - 1); ADC_Setup(); // ADC start ADC_Start(ADC0, adcStartSingle); unblockSleepMode(EM2); blockSleepMode(EM1); trfComplete=false; }
/* *Function name: DMA_CallBack() *Description : Call back function of the DMA */ void DMA_CallBack(unsigned int channel, bool primary, void *user) { unblockSleepMode(EM1); blockSleepMode(EM2); if(!trfComplete) { ADC_Reset(ADC0); // Reset the ADC; Turn it off //ADC0->CMD = ADC_CMD_SINGLESTOP; int temp = 0, i = 0; char tempChar[7]; //To store the temperature in char, for transmitting char temp_string[TX_bufferSize]; (void) channel; (void) primary; (void) user; for (i = 0; i < ADC_SAMPLES; i++) { temp += (ADC_Buffer[i]); } temperature = temp / ADC_SAMPLES; temperature = convertToCelsius(temperature); //Get value of Temperature in deg C if (temperature > HIGHTEMP) { //GPIO_PinOutClear(gpioPortE,2); //GPIO_PinOutSet(gpioPortE,3); /* To extract the digits of the temperature variable and put in tempChar. A basic digit extraction algorithm is used and then each digit is passed one by one. */ temp = temperature*10; tempChar[0] = (temp/100)+48; temp = temp%100; tempChar[1] = (temp/10)+48; temp = temp%10; tempChar[2] = '.'; tempChar[3] = (temp)+48; tempChar[4] = 'C'; // Pad the 4th position of charTemp as C tempChar[5] = '\r'; // Pad carriage return tempChar[6] = '\n'; // Pad line feed strcpy(temp_string,HighTemp); // Copy the HighTemp message in the temporary string strcat(temp_string,tempChar); // Concatenate with the tempChar to get the final message LEUART0->CTRL |= LEUART_CTRL_TXDMAWU; // Enable DMA wake up for LEUART TX in EM2 // Activate DMA transfers for LEUART TX DMA_ActivateBasic(DMA_CHANNEL_TX, true, false, (void *)&(LEUART0->TXDATA), (void *)temp_string, strlen(temp_string) - 1); } else if (temperature < LOWTEMP) { //GPIO_PinOutSet(gpioPortE,2); //GPIO_PinOutClear(gpioPortE,3); temp = temperature*10; tempChar[0] = (temp/100)+48; temp = temp%100; tempChar[1] = (temp/10)+48; temp = temp%10; tempChar[2] = '.'; tempChar[3] = (temp)+48; tempChar[4] = 'C'; tempChar[5] = '\r'; tempChar[6] = '\n'; strcpy(temp_string,LowTemp); // Copy the LowTemp message in the temporary string strcat(temp_string,tempChar); // Concatenate with the tempChar to get the final message LEUART0->CTRL |= LEUART_CTRL_TXDMAWU; // Enable DMA wake up for LEUART TX in EM2 // Activate DMA transfers for LEUART TX DMA_ActivateBasic(DMA_CHANNEL_TX, true, false, (void *)&(LEUART0->TXDATA), (void *)temp_string, strlen(temp_string) -1); } trfComplete=true; } else { (void) channel; (void) primary; (void) user; // Disable DMA wake-up from LEUART1 TX LEUART0->CTRL &= ~LEUART_CTRL_TXDMAWU; } }
void pwmout_init(pwmout_t *obj, PinName pin) { obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM); obj->pin = pin; MBED_ASSERT(obj->channel != (PWMName) NC); /* Turn on clock */ CMU_ClockEnable(PWM_TIMER_CLOCK, true); /* Turn on timer */ if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) { TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; TIMER_Init(PWM_TIMER, &timerInit); } // Set route enable if(pwmout_channel_route_active(pwmout_get_channel_route(obj->channel))) { //This channel was already in use //TODO: gracefully handle this case. mbed_error? return; } else { pwmout_set_channel_route(pwmout_get_channel_route(obj->channel)); blockSleepMode(EM1); pwmout_enable(obj, true); pwmout_enable_pins(obj, true); } // Set route location #ifdef _TIMER_ROUTELOC0_CC0LOC_LOC0 switch (obj->channel) { case PWM_CH0: PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC0LOC_MASK; PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC0LOC_SHIFT; break; case PWM_CH1: PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC1LOC_MASK; PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM)<< _TIMER_ROUTELOC0_CC1LOC_SHIFT; break; case PWM_CH2: PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC2LOC_MASK; PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC2LOC_SHIFT; break; case PWM_CH3: PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC3LOC_MASK; PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC3LOC_SHIFT; break; default: MBED_ASSERT(false); } #else // On P1, the route location is statically defined for the entire timer. PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK; if(pwmout_all_inactive()) { PWM_TIMER->ROUTE |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT; } else { MBED_ASSERT((pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT) == (PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK)); } #endif // Set default 20ms frequency and 0ms pulse width pwmout_period(obj, 0.02); }