예제 #1
0
파일: monitor.c 프로젝트: jdrunner/smartee
int mon_calibrate(int argc, char **argv){
  int on_time, off_time;

  //check if we should stop calibration mode
  if(argc==2){
    if(strcmp(argv[1],"stop")==0){
      printf("stopping calibration mode\n");
      wemo_config.calibrate = false;
      //disable the calibration PWM
      pwm_channel_disable_interrupt(PWM,CAL_PWM_CHANNEL,CAL_PWM_CHANNEL);
      pwm_channel_disable(PWM,CAL_PWM_CHANNEL);
      //save the new config
      fs_write_config();
      return 0;
    } else {
      printf("usage: specify [stop] or [start # #]\n");
    }
    return -1;
  }
  //make sure there are enough params to start 
  if(argc!=4 || (strcmp(argv[1],"start")!=0)){
    printf("usage: specify [stop] or \n");
    printf("\t [start on_time off_time] in ms\n");
    return -1;
  }
  //parse the on_time and off_time params
  on_time = atoi(argv[2]);
  off_time = atoi(argv[3]);
  //make sure these times are valid
  if(on_time<MIN_CAL_TIME || off_time<MIN_CAL_TIME){
    printf("times must be >= %d\n",MIN_CAL_TIME);
    return -1;
  }
  //stop data collection
  wemo_config.collect_data = false;
  //setup calibration parameters
  wemo_config.calibrate = true;
  wemo_config.cal_on_time = on_time;
  wemo_config.cal_off_time = off_time;
  //start the calibration PWM
  pwm_channel_enable_interrupt(PWM,CAL_PWM_CHANNEL,CAL_PWM_CHANNEL);
  pwm_channel_enable(PWM,CAL_PWM_CHANNEL);
  //save the new config
  fs_write_config();

  return 0;
}
예제 #2
0
파일: tm_stick.c 프로젝트: dorght/libHemp
static void configure_time_trigger_for_ssc(uint32_t ssc_trigger_hz)
{
	
#if 0
	gpio_configure_pin(PIO_PA12_IDX, PIO_PERIPH_B);
	pmc_enable_periph_clk(ID_PWM);

	/* Disable PWM channels */
	pwm_channel_disable(PWM, PWM_CHANNEL_1);

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = 1000 * 100,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);
	
	pwm_channel_t g_pwm_channel;

	/* Period is left-aligned */
	g_pwm_channel.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel.ul_period = 100;
	/* Duty cycle value of output waveform */
	g_pwm_channel.ul_duty = 50;
	g_pwm_channel.channel = PWM_CHANNEL_1;
	pwm_channel_init(PWM, &g_pwm_channel);
	
	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM, PWM_CHANNEL_1, 0);
	
	pwm_channel_enable(PWM, PWM_CHANNEL_1);
#endif


	
	uint32_t ul_div = 0;
	uint32_t ul_tc_clks = 0;
	uint32_t ul_sysclk = sysclk_get_cpu_hz();

	pmc_set_writeprotect(false);

	// Enable peripheral clock.
	pmc_enable_periph_clk(CONF_SSC_CLOCK_SOURCE_ID);

	// TIOA configuration 
	// gpio_configure_pin(PIN_TC0_TIOA0, PIN_TC0_TIOA0_FLAGS);
	// tc_set_writeprotect(TC2, true);
	tc_set_writeprotect(CONF_SSC_CLOCK_TC, false);

	// Configure TC for a 1Hz frequency and trigger on RC compare.
	tc_find_mck_divisor(ssc_trigger_hz, ul_sysclk, &ul_div, &ul_tc_clks, ul_sysclk);
	tc_init(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, ul_tc_clks | TC_CMR_WAVSEL_UP_RC | TC_CMR_WAVE | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
	uint32_t tmp_val = (ul_sysclk / ul_div) / ssc_trigger_hz;
	
	tc_write_ra(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val / 2);
	tc_write_rc(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL, tmp_val);

	// Start the Timer.
	tc_start(CONF_SSC_CLOCK_TC, CONF_SSC_CLOCK_CHANNEL);

}

void tm_stick_init(uint32_t bus_speed_hz) {
	if(g_tm_stick_data.mutex == NULL) {
		g_tm_stick_data.mutex =  xSemaphoreCreateMutex();
	}
	
	if(g_tm_stick_data.rtos_task_semaphore == NULL) {
		vSemaphoreCreateBinary(g_tm_stick_data.rtos_task_semaphore);
	}
	
	configure_time_trigger_for_ssc(1000);
	
	sysclk_enable_peripheral_clock(ID_SSC);
	ssc_reset(SSC);
	// Do not go over 1MHz, the pulse will be too long and extend over to the next clock's rising edge (The spec. sheet of 4021BCM does not really list the operation times of 3.3V operation.
	// I tested a couple of speeds.... at 1.25MHz, I found that it sometimes misses some pulses.
	if(bus_speed_hz > TM_STICK_MAX_BUS_SPEED){
		bus_speed_hz = TM_STICK_MAX_BUS_SPEED;
	}
	ssc_set_clock_divider(SSC, bus_speed_hz, sysclk_get_cpu_hz()); 
	clock_opt_t rx_clk_opt = {
		.ul_cks = SSC_RCMR_CKS_MCK,
		.ul_cko = SSC_RCMR_CKO_TRANSFER,
// TODO: Fix the SSC clock for some reason shift 1/2 clock pulse position.
// This makes the button results shift one position to the right. So we have to change rising/falling edge to "correct" it (oh, well, "hack" around it).
// Don't know why.
// One possible patch up is to use a pin to signal which one is desired to determine which of the following settings to use..
#if defined(CONF_BOARD_ARDUINO_DUE) 
		.ul_cki = 0, //SSC_RCMR_CKI,
#else
		.ul_cki = SSC_RCMR_CKI,
#endif
		.ul_ckg = SSC_RCMR_CKG_CONTINUOUS,
		.ul_start_sel = SSC_RCMR_START_RF_FALLING,
		.ul_period = 0,
		.ul_sttdly = 0
	};
	
	data_frame_opt_t rx_data_frame_opt = {
		.ul_datlen = 23,
		.ul_msbf = 0,  //SSC_RFMR_MSBF,
		.ul_fsos = SSC_RFMR_FSOS_NONE,
		.ul_datnb = 0,
		.ul_fsedge = SSC_RFMR_FSEDGE_NEGATIVE,
		.ul_fslen = 0,
		.ul_fslen_ext = 0
	};
	
	ssc_set_receiver(SSC, &rx_clk_opt, &rx_data_frame_opt);
	ssc_enable_interrupt(SSC, SSC_IER_RXRDY);
	
	// It is VERY IMPORTANT to set the priority of the interrupt to conform to what FreeRTOS needs because we are calling FreeRTOS interrupt-safe APIs (those *FromISR) from within interrupt handlers.
	// If we don't do this, if would work at the beginning, and then eventually the whole thing will come crashing down.
	// And it's not gonna crash even after millions of interrupts are handled. It will come crashing down in some very weird place after you start using another interrupt handler, like the pio handlers, and only after some handlling...
	// And, it will appear random. You press the button a couple of times, it dies. Then, at other times, you press and hold the button, etc. etc. Each time will be different.
	// You would be suspecting your stack overflowed, your code does a wild pointer, etc. etc. It's very difficult to debug. Trust me, you don't wanna go there.
	NVIC_ClearPendingIRQ(SSC_IRQn);
	NVIC_SetPriority(SSC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
	
	NVIC_EnableIRQ(SSC_IRQn); 
	
	ssc_enable_rx(SSC);
}

void SSC_Handler( void ) {	
	portBASE_TYPE xHigherTaskWoken = pdFALSE;
	uint32_t* in_data_buf = (uint32_t*)g_tm_stick_data.data;
	uint32_t in_data = 0;
	static uint32_t previous_in_data = 0;
	static bool is_first_time = true;
	// calculate the mask needed to wipe off extra high bit junk.
	static uint32_t mask = 0xFFFFFFFF;
	if(is_first_time) {
		for(int i = 4; i > TM_STICK_NUM_DATA_BYTES; i--) {
			mask = mask >> 8;
		}
	}

	if(ssc_is_rx_ready(SSC) == SSC_RC_YES) {
		xSemaphoreTakeFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
		in_data = SSC->SSC_RHR;
		// in_data >>= 1; // No idea why it always reads 25bits (one too many bit at the end LSB), instead of 24 I told it to. Therefore, we shift it off.
		in_data = ~in_data; // reverse it. So, now 1 is on, 0 is off.
		in_data &= mask;
		
		// Glitch filtering below.
		if(is_first_time
			||  (previous_in_data ^ in_data) == 0) {
			is_first_time = false;
			*in_data_buf = in_data;
		}
		previous_in_data = in_data;
		xSemaphoreGiveFromISR(g_tm_stick_data.mutex, &xHigherTaskWoken);
	
		xHigherTaskWoken = pdFALSE;
		xSemaphoreGiveFromISR(g_tm_stick_data.rtos_task_semaphore, &xHigherTaskWoken); // if there is an RTOS waiting for the ADC task mutex, wake it up.
		portEND_SWITCHING_ISR(xHigherTaskWoken);
	}
}

#ifdef __cplusplus
}
예제 #3
0
/**
 * \brief Application entry point for PWM with LED example.
 * Output PWM waves on LEDs to make them fade in and out.
 *
 * \return Unused (ANSI-C compatibility).
 */
int main(void)
{
	/* Initialize the SAM system */
	sysclk_init();
	board_init();

	/* Configure the console uart for debug information */
	configure_console();

	/* Output example information */
	puts(STRING_HEADER);
	
	/* Enable PWM peripheral clock */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pmc_enable_periph_clk(ID_PWM0);
#else
	pmc_enable_periph_clk(ID_PWM);
#endif

	/* Disable PWM channels for LEDs */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_disable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM0, PIN_PWM_LED1_CHANNEL);
#else
	pwm_channel_disable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM, PIN_PWM_LED1_CHANNEL);
#endif

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_init(PWM0, &clock_setting);
#else
	pwm_init(PWM, &clock_setting);
#endif

	/* Initialize PWM channel for LED0 */
	/* Period is left-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel_led.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_init(PWM0, &g_pwm_channel_led);
#else
	pwm_channel_init(PWM, &g_pwm_channel_led);
#endif

	/* Enable channel counter event interrupt */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_enable_interrupt(PWM0, PIN_PWM_LED0_CHANNEL, 0);
#else
	pwm_channel_enable_interrupt(PWM, PIN_PWM_LED0_CHANNEL, 0);
#endif

	/* Initialize PWM channel for LED1 */
	/* Period is center-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
	/* Output waveform starts at a high level */
	g_pwm_channel_led.polarity = PWM_HIGH;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM0, PIN_PWM_LED1_CHANNEL, 0);
#else
	pwm_channel_init(PWM, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM, PIN_PWM_LED1_CHANNEL, 0);
#endif

	/* Configure interrupt and enable PWM interrupt */
#if (SAMV70 || SAMV71 || SAME70 || SAMS70)
	NVIC_DisableIRQ(PWM0_IRQn);
	NVIC_ClearPendingIRQ(PWM0_IRQn);
	NVIC_SetPriority(PWM0_IRQn, 0);
	NVIC_EnableIRQ(PWM0_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_enable(PWM0, PIN_PWM_LED1_CHANNEL);
#else
	NVIC_DisableIRQ(PWM_IRQn);
	NVIC_ClearPendingIRQ(PWM_IRQn);
	NVIC_SetPriority(PWM_IRQn, 0);
	NVIC_EnableIRQ(PWM_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM, PIN_PWM_LED0_CHANNEL);
	pwm_channel_enable(PWM, PIN_PWM_LED1_CHANNEL);
#endif


	/* Infinite loop */
	while (1) {
	}
}
void init_pwm(void)
{
	/* Enable PWM peripheral clock */
	pmc_enable_periph_clk(ID_PWM0);

	/* Disable PWM channels for LEDs */
	pwm_channel_disable(PWM0, PIN_PWM_LED0_CHANNEL);
	pwm_channel_disable(PWM0, PIN_PWM_LED1_CHANNEL);

	/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
	pwm_clock_t clock_setting = {
		.ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
		.ul_clkb = 0,
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM0, &clock_setting);

	/* Initialize PWM channel for LED0 */
	/* Period is left-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a low level */
	g_pwm_channel_led.polarity = PWM_LOW;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED0_CHANNEL;
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Enable channel counter event interrupt */
	pwm_channel_enable_interrupt(PWM0, PIN_PWM_LED0_CHANNEL, 0);

	/* Initialize PWM channel for LED1 */
	/* Period is center-aligned */
	g_pwm_channel_led.alignment = PWM_ALIGN_CENTER;
	/* Output waveform starts at a high level */
	g_pwm_channel_led.polarity = PWM_HIGH;
	/* Use PWM clock A as source clock */
	g_pwm_channel_led.ul_prescaler = PWM_CMR_CPRE_CLKA;
	/* Period value of output waveform */
	g_pwm_channel_led.ul_period = PERIOD_VALUE;
	/* Duty cycle value of output waveform */
	g_pwm_channel_led.ul_duty = INIT_DUTY_VALUE;
	g_pwm_channel_led.channel = PIN_PWM_LED1_CHANNEL;
	pwm_channel_init(PWM0, &g_pwm_channel_led);

	/* Disable channel counter event interrupt */
	pwm_channel_disable_interrupt(PWM0, PIN_PWM_LED1_CHANNEL, 0);

	/* Configure interrupt and enable PWM interrupt */
	NVIC_DisableIRQ(PWM0_IRQn);
	NVIC_ClearPendingIRQ(PWM0_IRQn);
	NVIC_SetPriority(PWM0_IRQn, 0);
	NVIC_EnableIRQ(PWM0_IRQn);
	
	/* Enable PWM channels for LEDs */
	pwm_channel_enable(PWM0, PIN_PWM_LED0_CHANNEL);
//jsi 15feb16	pwm_channel_enable(PWM0, PIN_PWM_LED1_CHANNEL);

}