/******************************************************************************
 * @brief  Main function
 * The main file starts a timer and uses PRS to trigger an ADC conversion.
 * It waits in EM1 until the ADC conversion is complete, then prints the
 * result on the lcd.
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
  
  SegmentLCD_Init(false);

  /* Enable clocks required */
  CMU_ClockEnable(cmuClock_ADC0, true);
  CMU_ClockEnable(cmuClock_PRS, true);
  CMU_ClockEnable(cmuClock_TIMER0, true);

  /* Select TIMER0 as source and TIMER0OF (Timer0 overflow) as signal (rising edge) */
  PRS_SourceSignalSet(0, PRS_CH_CTRL_SOURCESEL_TIMER0, PRS_CH_CTRL_SIGSEL_TIMER0OF, prsEdgePos);

  ADCConfig();
  TimerConfig();

  /* Stay in this loop forever */
  while (1)
  {
    /* Enter EM1 and wait for timer triggered adc conversion */
    EMU_EnterEM1();

    /* Write result to LCD */
    SegmentLCD_Number(adcResult);

    /* Do other stuff */
    int i;
    for (i = 0; i < 10000; i++) ;
  }
}
示例#2
0
/***************************************************************************//**
 * @brief
 *   Enable PRS and configure TIMER TOP value for different sampling frequency.
 * @param bufferSize - Buffer size to setup sampling frequency  
 *******************************************************************************/
void setTopValue(uint16_t bufferSize)
{
  /* Select TIMER as source and Timer overflow as signal */
  PRS_SourceSignalSet(DAC_PRS_CH, TIMER_PRS, TIMER_SRC, prsEdgeOff);

#if SPEEX_BAND == WIDEBAND  
  /* Setup sampling frequency for WB to play NB or WB */
  if (bufferSize < SAMPLE_SIZE)
  {
    TIMER_USED->TOP = SAMPLE_8K;
  }
  else
  {
    TIMER_USED->TOP = SAMPLE_16K;
  }
#elif SPEEX_BAND == ULTRAWIDEBAND
  /* Setup sampling frequency for UWB to play NB or WB or UWB */
  if (bufferSize < SAMPLE_SIZE/2)
  {
    TIMER_USED->TOP = SAMPLE_8K;
  }
  else if (bufferSize < SAMPLE_SIZE)
  {
    TIMER_USED->TOP = SAMPLE_16K;
  }
  else
  {
    TIMER_USED->TOP = SAMPLE_32K;
  }    
#endif
  /* Sampling frequency is fixed on codec, NB8K and NB */  
  TIMER_USED->CMD = TIMER_CMD_START;
}
示例#3
0
文件: memmem.c 项目: havardh/bitless
void setupPRS( void )
{
  PRS_LevelSet(0, 1 << (PRS_CHANNEL_ADC + _PRS_SWLEVEL_CH0LEVEL_SHIFT));
  PRS_SourceSignalSet(PRS_CHANNEL_ADC,
                      PRS_CH_CTRL_SOURCESEL_TIMER0,
                      PRS_CH_CTRL_SIGSEL_TIMER0OF,
                      prsEdgePos);
}
示例#4
0
/***************************************************************************//**
* @brief
*   Configure PRS usage for this application.
*
* @param[in] prsChannel
*   PRS channel to use.
*******************************************************************************/
static void preampPRSConfig(unsigned int prsChannel)
{
  PRS_LevelSet(0, 1 << (prsChannel + _PRS_SWLEVEL_CH0LEVEL_SHIFT));
  PRS_SourceSignalSet(prsChannel,
                      PRS_CH_CTRL_SOURCESEL_TIMER0,
                      PRS_CH_CTRL_SIGSEL_TIMER0OF,
                      prsEdgePos);
}
/***************************************************************************//**
* @brief
*   Configure PRS usage for this application.
*
* @param[in] prsChannel
*   PRS channel to use.
*******************************************************************************/
static void guitarPRSConfig(unsigned int prsChannel)
{
  /* Set channel to 0. */
  PRS_LevelSet(0, 1 << (prsChannel + _PRS_SWLEVEL_CH0LEVEL_SHIFT));
  /* Configure PRS channel with positive edge on Timer0 overflow as source. */
  /* Will result in a 1 HFclk pulse on the PRS channel, which can trigger the ADC. */
  PRS_SourceSignalSet(prsChannel,
                      PRS_CH_CTRL_SOURCESEL_TIMER0,
                      PRS_CH_CTRL_SIGSEL_TIMER0OF,
                      prsEdgePos);
}
/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{  
  /* Initialize chip */
  CHIP_Init();
  
  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);
  
  /* Enable clock for ADC0 module */
  CMU_ClockEnable(cmuClock_ADC0, true);
  
  /* Enable clock for PRS module */
  CMU_ClockEnable(cmuClock_PRS, true);
  
  /* Configure PD8 as an input for PB0 button with filter enable (out = 1)*/
  GPIO_PinModeSet(gpioPortD, 8, gpioModeInput, 1); 
  
  /* Select PD8 as PRS output */
  GPIO->EXTIPSELH = (GPIO->EXTIPSELH & !_GPIO_EXTIPSELH_EXTIPSEL8_MASK ) | GPIO_EXTIPSELH_EXTIPSEL8_PORTD;
  
  /* Enable PRS sense */
  GPIO->INSENSE = GPIO->INSENSE | GPIO_INSENSE_PRS;
  
  /* Select GPIO as source and GPIOPIN8 as signal (falling edge) */
  PRS_SourceSignalSet(0, PRS_CH_CTRL_SOURCESEL_GPIOH, PRS_CH_CTRL_SIGSEL_GPIOPIN8, prsEdgeNeg);

  /* Initialize ADC common parts for both single conversion and scan sequence */
  ADC_Init(ADC0, &ADCInit);
  
  /* Initialize ADC single sample conversion */
  ADC_InitSingle(ADC0, &ADCInitSingle);
  
  /* Enable ADC Interrupt when Single Conversion Complete */
  ADC0->IEN = ADC_IEN_SINGLE;
  
  /* Enable ADC interrupt vector in NVIC*/
  NVIC_EnableIRQ(ADC0_IRQn);
   
  while(1)
  {
    /* Enter EM1 */ 
    EMU_EnterEM1();
    
    /* After ADC Single conversion wake up -> Delay 1000mS */  
    Delay(1000);
  }
}
示例#7
0
/**************************************************************************//**
 * @brief Configure TIMER to trigger ADC through PRS at a set sample rate
 *****************************************************************************/
void setupAdc(void)
{
  ADC_Init_TypeDef        adcInit       = ADC_INIT_DEFAULT;
  ADC_InitSingle_TypeDef  adcInitSingle = ADC_INITSINGLE_DEFAULT;
  
  /* Configure ADC single mode to sample Ref/2 */
  adcInit.prescale = ADC_PrescaleCalc(7000000, 0); /* Set highest allowed prescaler */
  ADC_Init(ADC0, &adcInit);
  
  adcInitSingle.input     =  adcSingleInpVrefDiv2;  /* Reference */
  adcInitSingle.prsEnable = true;                  
  adcInitSingle.prsSel    = adcPRSSELCh0;           /* Triggered by PRS CH0 */
  ADC_InitSingle(ADC0, &adcInitSingle);
  
  /* Connect PRS channel 0 to TIMER overflow */
  PRS_SourceSignalSet(0, PRS_CH_CTRL_SOURCESEL_TIMER0, PRS_CH_CTRL_SIGSEL_TIMER0OF, prsEdgeOff);
  
  /* Configure TIMER to trigger 100 kHz sampling rate */
  TIMER_TopSet(TIMER0,  CMU_ClockFreqGet(cmuClock_TIMER0)/ADCSAMPLESPERSEC);
  TIMER_Enable(TIMER0, true);
}
/**************************************************************************//**
 * @brief  ACMP_setup
 * Configures and starts the ACMP
 *****************************************************************************/
void ACMP_setup(void)
{
  /* Enable necessary clocks */
  CMU_ClockEnable(cmuClock_ACMP0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure PC4 as input with pull down for ACMP channel 4 input */
  GPIO_PinModeSet(gpioPortC, 4, gpioModeInputPullFilter, 0);

  /* Analog comparator parameters */
  const ACMP_Init_TypeDef acmpInit =
  {
    .fullBias                 = false,                  /* no full bias current*/
    .halfBias                 = false,                  /* no half bias current */
    .biasProg                 = 7,                      /* Biasprog current 1.4 uA */
    .interruptOnFallingEdge   = false,                  /* disable interrupt for falling edge */
    .interruptOnRisingEdge    = false,                  /* disable interrupt for rising edge */
    .warmTime                 = acmpWarmTime256,        /* Warm-up time in clock cycles, should be >140 cycles for >10us warm-up @ 14MHz */
    .hysteresisLevel          = acmpHysteresisLevel0,   /* Hysteresis level 0  - no hysteresis */
    .inactiveValue            = 0,                      /* Inactive comparator output value */
    .lowPowerReferenceEnabled = false,                  /* Low power reference mode disabled */
    .vddLevel                 = 32,                     /* Vdd reference scaling of 32 */
  };

  /* Init ACMP and set ACMP channel 4 as positive input
     and scaled Vdd as negative input */
  ACMP_Init(ACMP0, &acmpInit);
  ACMP_ChannelSet(ACMP0, acmpChannelVDD, acmpChannel4);
  ACMP_Enable(ACMP0);
}

/**************************************************************************//**
 * @brief  PRS_ScanChannel
 * Waits for activity on a selected PRS channel and writes on the LCD 
   when activity occurs
 *  
 * @param[in] timer  
 *   Pointer to TIMER peripheral register block.
 *
 * @param[in] prsCh
 * 	 PRS Channel to be monitored
 *
 * @param[in] edgeType
 *   Signal edge to be monitored/captured 
 *****************************************************************************/
void PRS_ScanChannel(TIMER_TypeDef *timer, TIMER_PRSSEL_TypeDef prsCh, TIMER_Edge_TypeDef edgeType)
{
  
/* enable the clock for the correct timer */  
#define TIMER_Clock(T) (T==TIMER0 ? cmuClock_TIMER0 : \
                          T==TIMER1 ? cmuClock_TIMER1 : 0)
  
  /* Enable necessary clocks */
  CMU_ClockEnable((CMU_Clock_TypeDef)TIMER_Clock(timer), true);
    
  /* Initialize LCD */
  SegmentLCD_Init(false);

  /* Select CC channel parameters */
  const TIMER_InitCC_TypeDef timerCCInit = 
  {
    .eventCtrl  = timerEventFalling,      /* input capture event control */
    .edge       = edgeType,               /* input capture on falling edge */
    .prsSel     = prsCh,                  /* prs channel select channel 5*/
    .cufoa      = timerOutputActionNone,  /* no action on counter underflow */
    .cofoa      = timerOutputActionNone,  /* no action on counter overflow */
    .cmoa       = timerOutputActionNone,  /* no action on counter match */
    .mode       = timerCCModeCapture,     /* CC channel mode capture */
    .filter     = false,                  /* no filter */
    .prsInput   = true,                   /* CC channel PRS input */
    .coist      = false,                  /* comparator output initial state */
    .outInvert  = false,                  /* no output invert */
  };
  
  /* Initialize TIMER0 CC0 */
  TIMER_InitCC(timer, 0, &timerCCInit);
  
  /* Select timer parameters */  
  const TIMER_Init_TypeDef timerInit =
  {
    .enable     = true,                         /* start counting when init complete */         
    .debugRun   = false,                        /* counter not running on debug halt */  
    .prescale   = timerPrescale1024,            /* prescaler of 64 */
    .clkSel     = timerClkSelHFPerClk,          /* TIMER0 clocked by the HFPERCLK */
    .fallAction = timerInputActionNone,         /* stop counter on falling edge */
    .riseAction = timerInputActionNone,         /* reload and start on rising edge */
    .mode       = timerModeUp,                  /* counting up */
    .dmaClrAct  = false,                        /* no DMA */
    .quadModeX4 = false,                        /* no quad decoding */
    .oneShot    = false,                        /* counting up constinuously */
    .sync       = false,                        /* no start/stop/reload by other timers */
  };
  
  /* Initialize TIMER0 */
  TIMER_Init(timer, &timerInit);  
  
  /* Poll the Input Capture Valid flag in the Status register
      The program will hang at this point waiting for activity on this
	  channel */
  while(!((TIMER0->STATUS & _TIMER_STATUS_ICV0_MASK )>>16));  
}

/**************************************************************************//**
 * @brief  Main function
 * Main is called from __iar_program_start, see assembly startup file
 *****************************************************************************/
int main(void)
{
  /* Align different chip revisions*/
  CHIP_Init();
  
  /* Initialise the ACMP */
  ACMP_setup();

  /* PRS setup */
  /* Enable clock for PRS and select ACMP as source and ACMP0OUT (ACMP0 OUTPUT) as signal 
     for channel 5 */
  CMU_ClockEnable(cmuClock_PRS, true);
  PRS_SourceSignalSet(5, PRS_CH_CTRL_SOURCESEL_ACMP0, PRS_CH_CTRL_SIGSEL_ACMP0OUT, prsEdgeOff);
  
  /* Start PRS scan 
     This function will halt the program while there is no PRS activity
     This function assumes that the PRS has been setup previously */
  PRS_ScanChannel(TIMER0, timerPRSSELCh5, timerEdgeFalling);
  
  /* Write PRS and channel number on the LCD to acknowledge PRS activity */  
  SegmentLCD_Write("PRS");
  SegmentLCD_Number((int)timerPRSSELCh5);
  
  while(1)
  {
    /* Enter EM1 while waiting for capture. */
    EMU_EnterEM1();
  }
}
示例#9
0
/**************************************************************************//**
 * @brief  TIMER0_setup
 * Configures the TIMER
 *****************************************************************************/
void TIMER_setup(void)
{
  /* Enable necessary clocks */
  CMU_ClockEnable(cmuClock_TIMER0, true);
  CMU_ClockEnable(cmuClock_PRS, true);

  /* Select CC channel parameters */
  TIMER_InitCC_TypeDef timerCCInit =
  {
    .eventCtrl  = timerEventEveryEdge,      /* Input capture event control */
    .edge       = timerEdgeBoth,       /* Input capture on falling edge */
    .prsSel     = timerPRSSELCh5,         /* Prs channel select channel 5*/
    .cufoa      = timerOutputActionNone,  /* No action on counter underflow */
    .cofoa      = timerOutputActionNone,  /* No action on counter overflow */
    .cmoa       = timerOutputActionNone,  /* No action on counter match */
    .mode       = timerCCModeCapture,     /* CC channel mode capture */
    .filter     = false,                  /* No filter */
    .prsInput   = true,                   /* CC channel PRS input */
    .coist      = false,                  /* Comparator output initial state */
    .outInvert  = false,                  /* No output invert */
  };

  /* Initialize TIMER0 CC0 channel */
  TIMER_InitCC(HIJACK_RX_TIMER, 0, &timerCCInit);

  /* Select timer parameters */
  const TIMER_Init_TypeDef timerInit =
  {
    .enable     = false,                        /* Do not start counting when init complete */
    .debugRun   = false,                        /* Counter not running on debug halt */
    .prescale   = HIJACK_TIMER_RESOLUTION,      /* Prescaler of 1 */
    .clkSel     = timerClkSelHFPerClk,          /* TIMER0 clocked by the HFPERCLK */
    .fallAction = timerInputActionReloadStart,         /* Stop counter on falling edge */
    .riseAction = timerInputActionReloadStart,  /* Reload and start on rising edge */
    .mode       = timerModeUp,                  /* Counting up */
    .dmaClrAct  = false,                        /* No DMA */
    .quadModeX4 = false,                        /* No quad decoding */
    .oneShot    = false,                        /* Counting up constinuously */
    .sync       = false,                        /* No start/stop/reload by other timers */
  };

  /* Initialize TIMER0 */
  TIMER_Init(HIJACK_RX_TIMER, &timerInit);

  /* PRS setup */
  /* Select ACMP as source and ACMP0OUT (ACMP0 OUTPUT) as signal */
  PRS_SourceSignalSet(5, PRS_CH_CTRL_SOURCESEL_ACMP0, PRS_CH_CTRL_SIGSEL_ACMP0OUT, prsEdgeOff);

  /* Enable CC0 interrupt */
  TIMER_IntEnable(HIJACK_RX_TIMER, TIMER_IF_CC0);

  /* Enable TIMER0 interrupt vector in NVIC */
  NVIC_EnableIRQ(TIMER0_IRQn);
}

/**************************************************************************//**
 * @brief  ACMP_setup
 * Configures and starts the ACMP
 *****************************************************************************/
static void ACMP_setup(void)
{
  /* Enable necessary clocks */
  CMU_ClockEnable(HIJACK_RX_ACMPCLK, true);
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure ACMP input pin. */
  GPIO_PinModeSet(HIJACK_RX_GPIO_PORT, HIJACK_RX_GPIO_PIN, gpioModeInput, 0);

  /* Analog comparator parameters */
  const ACMP_Init_TypeDef acmpInit =
  {
    .fullBias                 = false,                  /* No full bias current*/
    .halfBias                 = true,                  /* No half bias current */
    .biasProg                 = 2,                      /* Biasprog current 1.4 uA */
    .interruptOnFallingEdge   = false,                  /* Disable interrupt for falling edge */
    .interruptOnRisingEdge    = false,                  /* Disable interrupt for rising edge */
    .warmTime                 = acmpWarmTime256,        /* Warm-up time in clock cycles, should be >140 cycles for >10us warm-up @ 14MHz */
    .hysteresisLevel          = acmpHysteresisLevel7,   /* Hysteresis level 0  - no hysteresis */
    .inactiveValue            = 1,                      /* Inactive comparator output value */
    .lowPowerReferenceEnabled = false,                  /* Low power reference mode disabled */
    .vddLevel                 = HIJACK_RX_ACMP_LEVEL,                     /* Vdd reference scaling of 32 */
  };

  /* Use ACMP0 output, PD6 . */
  //GPIO_PinModeSet(gpioPortD, 6, gpioModePushPull, 0);
  //ACMP_GPIOSetup(ACMP0, 2, true, false);

  /* Init ACMP and set ACMP channel 4 as positive input
     and scaled Vdd as negative input */
  ACMP_Init(HIJACK_RX_ACMP, &acmpInit);
  ACMP_ChannelSet(HIJACK_RX_ACMP, HIJACK_RX_ACMP_NEG, HIJACK_RX_ACMP_CH);
  ACMP_Enable(HIJACK_RX_ACMP);
}

/**
 * @brief calculate whether cnt is in 500us region
 * ticker = 64Mhz/128 = 2us
 * 475us < cnt < 510us
 *
 */
static chk_result_t IsTime2Detect(uint32_t inv)
{
  	chk_result_t ret;
	
  	if( inv < HIJACK_DEC_NUM_TICKS_MIN){
    	offset = inv;
	    ret = pass;
  	}
	else if ( ( inv <= HIJACK_DEC_NUM_TICKS_MAX ) && ( inv >= HIJACK_DEC_NUM_TICKS_MIN ) ) {
		offset = 0;
		inv = 0;
	  	ret = suit;
	}
	else{
		offset = 0;
		inv = 0;
		ret = error;
	}
	return ret;
}

/*
 * Find phase remain or phase reversal.
*/

static void dec_parser(uint8_t bit_msk, state_t state)
{
  	if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine
		if( falling == cur_edge ){
	  		dec.data &= ~(1 << bit_msk);
#if DEC_DEBUG == 1
			uartPutChar( '+' ) ;
			uartPutChar( '_' ) ;
#endif//DEC_DEBUG == 1
		}
		else{
		   	dec.data |= (1 << bit_msk);
#if DEC_DEBUG == 1
			uartPutChar( '_' ) ;
			uartPutChar( '+' ) ;
#endif//DEC_DEBUG == 1
			dec.odd++;
		}
		dec.state = state;   //state switch
	}
	else if ( error == IsTime2Detect(inv) ){   //wait for edge detection time
		dec.state = Waiting;   //state switch
	}
}
/**************************************************************************//**
 * @brief  decode state machine
 * Invoke in TIMER_ISR for decoding.
 *****************************************************************************/
void decode_machine(void)
{
   	inv = offset + cur_stamp;  //update offset
#if 0
	if( dec.state > Waiting ){
	  	USART_printHexBy16u(inv);
		if(cur_edge == rising){
			uartPutChar( '\\' ) ;
		}
		else{
			uartPutChar( '/' ) ;
		}
	}
#endif	
	switch (dec.state){
		case Waiting:
         	/* go to start bit if rising edge exist. */
         	if (rising == cur_edge) {
            	dec.state = Sta0;
            	offset = 0;
				inv = 0;
         	}
			break;
			//
		case Sta0:
         	if( ( suit == IsTime2Detect(inv) ) && ( falling == cur_edge ) ){
				dec.data = 0;  //clear data field for store new potential data
				dec.odd = 0;   //clear odd field parity counter
				dec.state = Bit0;
#if DEC_DEBUG == 1
			  	uartPutChar( 'S' ) ;
				uartPutChar( '+' ) ;
				uartPutChar( '_' ) ;
#endif
         	}
			else{
				dec.state = Waiting;
			}
	   		break;
			//
		case Bit0:
#if DEC_DEBUG == 1
			uartPutChar( '0' ) ;
#endif
		  	dec_parser(BIT0, Bit1);
	   		break;
			//
		case Bit1:
#if DEC_DEBUG == 1
			uartPutChar( '1' ) ;
#endif
		  	dec_parser(BIT1, Bit2);
	   		break;
			//
		case Bit2:
#if DEC_DEBUG == 1
			uartPutChar( '2' ) ;
#endif
		  	dec_parser(BIT2, Bit3);
	   		break;
			//
		case Bit3:
#if DEC_DEBUG == 1
			uartPutChar( '3' ) ;
#endif
		  	dec_parser(BIT3, Bit4);
	   		break;
			//
		case Bit4:
#if DEC_DEBUG == 1
			uartPutChar( '4' ) ;
#endif
		  	dec_parser(BIT4, Bit5);
	   		break;
			//
		case Bit5:
#if DEC_DEBUG == 1
			uartPutChar( '5' ) ;
#endif
		  	dec_parser(BIT5, Bit6);
	   		break;
			//
		case Bit6:
#if DEC_DEBUG == 1
			uartPutChar( '6' ) ;
#endif
		  	dec_parser(BIT6, Bit7);
	   		break;
			//
		case Bit7:
#if DEC_DEBUG == 1
			uartPutChar( '7' ) ;
#endif
		  	dec_parser(BIT7, Parity);
	   		break;
			//
		case Parity:		
			if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine
				if( rising == cur_edge ){
				   dec.odd++;
#if DEC_DEBUG == 1
				   uartPutChar( '_' ) ;
				   uartPutChar( '+' ) ;
#endif
				}
				else{
#if DEC_DEBUG == 1
				   uartPutChar( '+' ) ;
				 	uartPutChar( '_' ) ;
#endif					
				}
#if DEC_DEBUG == 1
					uartPutChar( dec.odd + 0x30) ;
#endif
				if( 1 == (dec.odd%2)){  //parity pass
				   dec.state = Sto0;
				}
				else{ //parity failed
				   dec.state = Waiting;
				}
			 }
			 else if ( error == IsTime2Detect(inv) ){   //wait for edge detection time
				dec.state = Waiting;
			 }
			break;
			//
      	case Sto0:	
         	if ( ( suit == IsTime2Detect(inv) ) ){ //it's time to determine
				if( rising == cur_edge ){  //stop bit is rising edge
				    USART_txByte(dec.data);
#if DEC_DEBUG == 1
					uartPutChar( '_' ) ;
				    uartPutChar( '+' ) ;
#endif
				    HIJACKPutData(&dec.data, &decBuf, sizeof(uint8_t));
				}
				else{
#if DEC_DEBUG == 1
				  	uartPutChar( '+' ) ;
				 	uartPutChar( '_' ) ;
#endif			
				}
				dec.state = Waiting;
#if DEC_DEBUG == 1
				uartPutChar( '\r' ) ;
				uartPutChar( '\n' ) ;
#endif
         	}
         	else if ( error == IsTime2Detect(inv) ){   //wait for edge detection time
				dec.state = Waiting;
			}
         	break;
         	//
		default:
	  		break;
			//
	}
}