/*
  * 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;
     }
 }
Пример #2
0
/** 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;
	}
}
Пример #6
0
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);
}