Beispiel #1
0
//-----------------------------------------------------------------------------------------------------------------
// SPI als Master initialisieren
//-----------------------------------------------------------------------------------------------------------------
void 	spi_master_init(uint8_t freq_div, bool lsb_first, uint8_t spi_mode)
{
	
	//Power einschalten für das SPI-Interface:
	//PRSPI-Bit im PRR0-Register auf 0 setzen
	// now use the avr-lib for this!
	// Not all Atmels support this!
	#ifdef PRSPI
	power_spi_enable();
	#endif
	
	//Portpins des SPI initialisieren
	SPI_DDR |= _BV(SPI_CLK_PIN) | _BV(SPI_MOSI_PIN);
	SPI_DDR &= ~_BV(SPI_MISO_PIN);
	
	//SPI als Master
	SPCR = (1<<SPE)|(1<<MSTR);
	
	//Frequenzteiler einstellen
	SPCR |= freq_div;
	
	//Übertragungsmodus 0...3
	SPCR |= spi_mode << 2;
	
	//LSB oder MSB first
	if(lsb_first) SPCR |= (1<<DORD);

}
Beispiel #2
0
// Initialize SPI Slave Mode (polling)
void init_spi_slave_polling (void)
{
    // Set PB4(MISO) as output. PB3(MOSI), PB2(SS), and PB5(SCK) are input
    DDRB = (1<<DDB4);
    // Enable SPI in Slave Mode
    SPCR = (1<<SPE);

    power_spi_enable();
}
Beispiel #3
0
// SPI Interrupt Initialization for Slave Mode
void init_spi_slave_int (void)
{
    power_spi_enable();

    // Set PB4(MISO) as output
    DDRB    = (1<<DDB4);
    // Enable SPI Interrupt and SPI in Slave Mode
    SPCR  = (1<<SPIE)|(1<<SPE);
}
Beispiel #4
0
void Transceiver::Wakeup()
{
  if (_inSleep){
    _inSleep=false;
    power_spi_enable();
    buffer->Wakeup();
    DBGPINHIGH();
    DBGINFO("wakeup");
  }
}
Beispiel #5
0
void cube_start(uint8_t unused)
{
	// Set sleep mode to lighter
	mode = old_mode;

	power_adc_enable();
	power_spi_enable();
	power_timer0_enable();
	power_timer1_enable();

	// Enable BLANK timer interrupt (starts SPI)
	TIMSK0 |= (1 << OCIE0A);
}
Beispiel #6
0
/*********************************************************************************************************
** Function name:           wakeUp
** Descriptions:            wakeUp
*********************************************************************************************************/
void xadow::wakeUp()
{
#if defined(__AVR_ATmega32U4__)
    power_adc_enable();
    power_usart0_enable();
    power_spi_enable();
    power_twi_enable();
    power_timer1_enable();
    power_timer2_enable();
    power_timer3_enable();
    power_usart1_enable();
    power_usb_enable();
#endif
}
Beispiel #7
0
void	Low_Power::idle(Period_t period, ADC_t adc,
                        Timer4_t timer4, Timer3_t timer3,
                        Timer1_t timer1, Timer0_t timer0,
                        SPI_t spi, USART1_t usart1,	TWI_t twi, usb_t usb)
{
    if (adc == ADC_OFF)
    {
        ADCSRA &= ~(1 << ADEN);
        power_adc_disable();
    }

    if (timer4 == TIMER4_OFF)	power_timer4_disable();
    if (timer3 == TIMER3_OFF)	power_timer3_disable();
    if (timer1 == TIMER1_OFF)	power_timer1_disable();
    if (timer0 == TIMER0_OFF)	power_timer0_disable();
    if (spi == SPI_OFF)				power_spi_disable();
    if (usart1 == USART1_OFF)	power_usart1_disable();
    if (twi == TWI_OFF)				power_twi_disable();
    if (usb == USB_OFF)				power_usb_disable();

    if (period != SLEEP_FOREVER)
    {
        wdt_enable(period);
        WDTCSR |= (1 << WDIE);
    }

    lowPowerBodOn(SLEEP_MODE_IDLE);

    if (adc == ADC_OFF)
    {
        power_adc_enable();
        ADCSRA |= (1 << ADEN);
    }

    if (timer4 == TIMER4_OFF)	power_timer4_enable();
    if (timer3 == TIMER3_OFF)	power_timer3_enable();
    if (timer1 == TIMER1_OFF)	power_timer1_enable();
    if (timer0 == TIMER0_OFF)	power_timer0_enable();
    if (spi == SPI_OFF)				power_spi_enable();
    if (usart1 == USART1_OFF)	power_usart1_enable();
    if (twi == TWI_OFF)				power_twi_enable();
    if (usb == USB_OFF)				power_usb_enable();
}
Beispiel #8
0
// enable hardware SPI
void spi_init(void)
{
    DDR_SPI &= ~( DD_MOSI | DD_MISO | DD_SS | DD_SCK );
    DDR_SPI |= (DD_MOSI | DD_SS | DD_SCK);
    // enable pull-ups since this is not done in hardware 
    PORT_SPI |= (DD_MOSI | DD_SS | DD_MISO | DD_SCK);

    power_spi_enable();

    SPCR = ((0 << SPIE) |       // SPI interrupt enable
            (1 << SPE) |        // SPI enable
            (0 << DORD) |       // data order (0=MSB first, 1=LSB first)
            (1 << MSTR) |       // 1=master 0=slave
            (0 << CPOL) |       // clock polarity (0:SCK low / 1:SCK hi when idle)
            (0 << CPHA) |       // clock phase (0:leading / 1:trailing edge sampling)
            (1 << SPR1) |       // SPI clock rate
            (0 << SPR0)
        );

    SPSR = (1 << SPI2X);        // Double Clock Rate
}
Beispiel #9
0
void	Low_Power::idle(Period_t period, ADC_t adc, Timer5_t timer5,
                        Timer4_t timer4, Timer3_t timer3, Timer2_t timer2,
                        Timer1_t timer1, Timer0_t timer0, SPI_t spi,
                        USART3_t usart3, USART2_t usart2, USART1_t usart1,
                        USART0_t usart0, TWI_t twi)
{
    // Temporary clock source variable
    unsigned char clockSource = 0;

    if (timer2 == TIMER2_OFF)
    {
        if (TCCR2B & CS22) clockSource |= (1 << CS22);
        if (TCCR2B & CS21) clockSource |= (1 << CS21);
        if (TCCR2B & CS20) clockSource |= (1 << CS20);

        // Remove the clock source to shutdown Timer2
        TCCR2B &= ~(1 << CS22);
        TCCR2B &= ~(1 << CS21);
        TCCR2B &= ~(1 << CS20);

        power_timer2_disable();
    }

    if (adc == ADC_OFF)
    {
        ADCSRA &= ~(1 << ADEN);
        power_adc_disable();
    }

    if (timer5 == TIMER5_OFF)	power_timer5_disable();
    if (timer4 == TIMER4_OFF)	power_timer4_disable();
    if (timer3 == TIMER3_OFF)	power_timer3_disable();
    if (timer1 == TIMER1_OFF)	power_timer1_disable();
    if (timer0 == TIMER0_OFF)	power_timer0_disable();
    if (spi == SPI_OFF)			  power_spi_disable();
    if (usart3 == USART3_OFF)	power_usart3_disable();
    if (usart2 == USART2_OFF)	power_usart2_disable();
    if (usart1 == USART1_OFF)	power_usart1_disable();
    if (usart0 == USART0_OFF)	power_usart0_disable();
    if (twi == TWI_OFF)			  power_twi_disable();

    if (period != SLEEP_FOREVER)
    {
        wdt_enable(period);
        WDTCSR |= (1 << WDIE);
    }

    lowPowerBodOn(SLEEP_MODE_IDLE);

    if (adc == ADC_OFF)
    {
        power_adc_enable();
        ADCSRA |= (1 << ADEN);
    }

    if (timer2 == TIMER2_OFF)
    {
        if (clockSource & CS22) TCCR2B |= (1 << CS22);
        if (clockSource & CS21) TCCR2B |= (1 << CS21);
        if (clockSource & CS20) TCCR2B |= (1 << CS20);

        power_timer2_enable();
    }

    if (timer5 == TIMER5_OFF)	power_timer5_enable();
    if (timer4 == TIMER4_OFF)	power_timer4_enable();
    if (timer3 == TIMER3_OFF)	power_timer3_enable();
    if (timer1 == TIMER1_OFF)	power_timer1_enable();
    if (timer0 == TIMER0_OFF)	power_timer0_enable();
    if (spi == SPI_OFF)			  power_spi_enable();
    if (usart3 == USART3_OFF)	power_usart3_enable();
    if (usart2 == USART2_OFF)	power_usart2_enable();
    if (usart1 == USART1_OFF)	power_usart1_enable();
    if (usart0 == USART0_OFF)	power_usart0_enable();
    if (twi == TWI_OFF)			  power_twi_enable();
}
Beispiel #10
0
/*******************************************************************************
* Name: idle
* Description: Putting microcontroller into idle state. Please make sure you 
*			   understand the implication and result of disabling module.
*
* Argument  	Description
* =========  	===========
* 1. period     Duration of low power mode. Use SLEEP_FOREVER to use other wake
*				up resource:
*				(a) SLEEP_15MS - 15 ms sleep
*				(b) SLEEP_30MS - 30 ms sleep
*				(c) SLEEP_60MS - 60 ms sleep
*				(d) SLEEP_120MS - 120 ms sleep
*				(e) SLEEP_250MS - 250 ms sleep
*				(f) SLEEP_500MS - 500 ms sleep
*				(g) SLEEP_1S - 1 s sleep
*				(h) SLEEP_2S - 2 s sleep
*				(i) SLEEP_4S - 4 s sleep
*				(j) SLEEP_8S - 8 s sleep
*				(k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc		ADC module disable control:
*				(a) ADC_OFF - Turn off ADC module
*				(b) ADC_ON - Leave ADC module in its default state
*
* 3. timer2		Timer 2 module disable control:
*				(a) TIMER2_OFF - Turn off Timer 2 module
*				(b) TIMER2_ON - Leave Timer 2 module in its default state
*
* 4. timer1		Timer 1 module disable control:
*				(a) TIMER1_OFF - Turn off Timer 1 module
*				(b) TIMER1_ON - Leave Timer 1 module in its default state
*
* 5. timer0		Timer 0 module disable control:
*				(a) TIMER0_OFF - Turn off Timer 0 module
*				(b) TIMER0_ON - Leave Timer 0 module in its default state
*
* 6. spi		SPI module disable control:
*				(a) ADC_OFF - Turn off ADC module
*				(b) ADC_ON - Leave ADC module in its default state
*
* 7. usart0		USART0 module disable control:
*				(a) USART0_OFF - Turn off USART0  module
*				(b) USART0_ON - Leave USART0 module in its default state
*
* 8. twi		TWI module disable control:
*				(a) TWI_OFF - Turn off TWI module
*				(b) TWI_ON - Leave TWI module in its default state
*
*******************************************************************************/
void	LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2, 
							timer1_t timer1, timer0_t timer0,
							spi_t spi, usart0_t usart0,	twi_t twi)
{
	// Temporary clock source variable 
	unsigned char clockSource = 0;
	
	if (timer2 == TIMER2_OFF)
	{
		if (TCCR2B & CS22) clockSource |= (1 << CS22);
		if (TCCR2B & CS21) clockSource |= (1 << CS21);
		if (TCCR2B & CS20) clockSource |= (1 << CS20);
	
		// Remove the clock source to shutdown Timer2
		TCCR2B &= ~(1 << CS22);
		TCCR2B &= ~(1 << CS21);
		TCCR2B &= ~(1 << CS20);
		
		power_timer2_disable();
	}
	
	if (adc == ADC_OFF)	
	{
		ADCSRA &= ~(1 << ADEN);
		power_adc_disable();
	}
	
	if (timer1 == TIMER1_OFF)	power_timer1_disable();	
	if (timer0 == TIMER0_OFF)	power_timer0_disable();	
	if (spi == SPI_OFF)			power_spi_disable();
	if (usart0 == USART0_OFF)	power_usart0_disable();
	if (twi == TWI_OFF)			power_twi_disable();
	
	if (period != SLEEP_FOREVER)
	{
		wdt_enable(period);
		WDTCSR |= (1 << WDIE);	
	}
	
	lowPowerBodOn(SLEEP_MODE_IDLE);
	
	if (adc == ADC_OFF)
	{
		power_adc_enable();
		ADCSRA |= (1 << ADEN);
	}
	
	if (timer2 == TIMER2_OFF)
	{
		if (clockSource & CS22) TCCR2B |= (1 << CS22);
		if (clockSource & CS21) TCCR2B |= (1 << CS21);
		if (clockSource & CS20) TCCR2B |= (1 << CS20);
		
		power_timer2_enable();
	}
	
	if (timer1 == TIMER1_OFF)	power_timer1_enable();	
	if (timer0 == TIMER0_OFF)	power_timer0_enable();	
	if (spi == SPI_OFF)			power_spi_enable();
	if (usart0 == USART0_OFF)	power_usart0_enable();
	if (twi == TWI_OFF)			power_twi_enable();
}
Beispiel #11
0
int main(void)
{
	// set clock prescaler for 8MHz
	CLKPR = 0x80;
	CLKPR = 0x01;

	cli();

	power_all_disable();
	power_spi_enable();
	power_timer1_enable();
	set_sleep_mode(SLEEP_MODE_IDLE);

	pins_init();

	delay_ms(345); // arbitrary

	uint8_t dpi = 0x0f; // default to 800
	if (!(PIND & (1<<0))) // if left is pressed at boot
		dpi = 0xff; // set to 12800

	pmw3366_init(dpi);
	nrf24_init();

	// button stuff
	// previous debounced state
	uint8_t btn_prev = ~(PIND);
	// time (in 125us) button has been unpressed.
	// consider button to be released if this time exceeds DEBOUNCE_TIME.
	uint8_t btn_time[3] = {0, 0, 0};

	// absolute positions. relies on integer overflow
	union motion_data x = {0}, y = {0};

	// wheel stuff
	uint8_t whl_prev_same = 0; // what A was the last time A == B
	uint8_t whl_prev_diff = 0; // what A was the last time A != B
	// absolute scroll position. relies on integer overflow
	int8_t whl = 0;

	// begin burst mode for 3366
	spi_set3366mode();
	SS_3366_LOW;
	spi_3366_write(0x50, 0x00);
	SS_3366_HIGH;

	// set up timer1 to set OCF0A in TIFR0 every 1ms
	TCCR1A = 0x00;
	TCCR1B = 0x09; // CTC, 8MHz
	OCR1A = 7999; // main loop nominal period (7999 + 1) / 8MHz = 1ms
	OCR1B = 320; // timing of when to read burst mode data from sensor
	OCR1C = 800; // timing of when to load nrf24l01+ with data

	// let receiver know if it's the first time sending data, so that it
	// can reset the reference for absolute position and that there's no
	// jump when rebooting the mouse
	// uint8_t first = 0x80; // transmitted as MSB with button data below.

	// when sync reaches 0, always send a packet with bit 6 in btn set, to
	// tell the receiver to calculate the timing offset.
	// when sync reaches 1, always send a packet requesting ACK to load the
	// timing offset
	// i.e. when it overflows, so 256ms periodicity.

	// when sync reaches 0, afk increments.
	// afk is cleared by any motion or button press.
	// when afk reaches AFK_TIMEOUT, go into powerdown mode.
	for (uint8_t first = 0x80, sync = 0, afk = 0; ; first = 0, sync++) {
		// sync to 1ms intervals using timer1
	//	if (TIFR1 & (1<<OCF1A)) PORTD |= (1<<6);
		TIMSK1 |= (1<<OCIE1A);
		sei(); sleep_mode(); cli();
		TIMSK1 &= ~(1<<OCIE1A);
		TIFR1 |= (1<<OCF1A); TIFR1 |= (1<<OCF1B); TIFR1 |= (1<<OCF1C);

		// begin burst mode read
		spi_set3366mode();
		SS_3366_LOW;
		spi_send(0x50);
		// do stuff here instead of busy waiting for 35us

		// read wheel
		int8_t dwhl = 0;
		const uint8_t whl_a = WHL_A_IS_HIGH;
		const uint8_t whl_b = WHL_B_IS_HIGH;
	//	if (whl_a == whl_b) {
	//		if (whl_a != whl_prev_same) {
	//			dwhl = 2 * (whl_a ^ whl_prev_diff) - 1;
	//			whl += dwhl;
	//			whl_prev_same = whl_a;
	//		}
	//	} else
	//		whl_prev_diff = whl_a;
		if (whl_a != whl_b)
			whl_prev_diff = whl_a;
		else if (whl_a != whl_prev_same) {
			dwhl = 2 * (whl_a ^ whl_prev_diff) - 1;
			whl += dwhl;
			whl_prev_same = whl_a;
		}

		// read buttons
		/*
		PIND 0 EIFR 0: low, no edges -> is low
		PIND 0 EIFR 1: low, edge -> is low
		PIND 1 EIFR 0: high, no edges -> always high during last 1ms
		PIND 1 EIFR 1: high, edge -> low at some point in the last 1ms
		*/
		const uint8_t btn_unpressed = PIND & ~(EIFR);
		EIFR = 0b00000111; // clear EIFR
		// manual loop debouncing for every button
		uint8_t btn_dbncd = 0x00;
		#define DEBOUNCE(index) \
		if ((btn_prev & (1<<index)) && (btn_unpressed & (1<<index))) { \
			btn_time[index]++; \
			if (btn_time[index] < DEBOUNCE_TIME) \
				btn_dbncd |= (1<<index); \
		} else { \
			btn_time[index] = 0; \
			btn_dbncd |= (~btn_unpressed) & (1<<index); \
		}

		DEBOUNCE(0);
		DEBOUNCE(1);
		DEBOUNCE(2);
		#undef DEBOUNCE

		// wait until 35us have elapsed since spi_send(0x50)
	//	if (TIFR1 & (1<<OCF1B)) PORTD |= (1<<6);
		TIMSK1 |= (1<<OCIE1B);
		sei(); sleep_mode(); cli();
		TIMSK1 &= ~(1<<OCIE1B);

		union motion_data dx, dy;
		spi_send(0x00); // motion, not used
		spi_send(0x00); // observation, not used
		dx.lo = spi_recv();
		dx.hi = spi_recv();
		dy.lo = spi_recv();
		dy.hi = spi_recv();
		SS_3366_HIGH;

		x.all += dx.all;
		y.all += dy.all;

		if (sync == 0) afk++;
		const uint8_t changed = (btn_dbncd != btn_prev) || dx.all || dy.all || dwhl;
		if (changed) afk = 0;

		if (changed || (sync <= 1)) {
			btn_prev = btn_dbncd;
			// W_TX_PAYLOAD if sync == 1, W_TX_PAYLOAD_NOACK otherwise
			const uint8_t mode = (sync == 1) ? 0b10100000 : 0b10110000;
			// send miscellaneous info using top bits of btn byte
			uint8_t btn_send = btn_dbncd | first; // first is either 0x80 or 0
			if (sync == 0) btn_send |= 0x40;

			// try to transmit at the same time every frame
	//		if (TIFR1 & (1<<OCF1C)) {PORTD |= (1<<6);}
			TIMSK1 |= (1<<OCIE1C);
			sei(); sleep_mode(); cli();
			TIMSK1 &= ~(1<<OCIE1C);

			spi_setnrf24mode();
			SS_NRF24_LOW;
			spi_send(0x20 | 0x07); // STATUS
			spi_send(0b01110000); // clear IRQ
			SS_NRF24_HIGH;
			SS_NRF24_LOW;
			spi_send(0b11100001); // flush tx
			SS_NRF24_HIGH;
			SS_NRF24_LOW;
			spi_send(0b11100010); // flush rx
			SS_NRF24_HIGH;

			SS_NRF24_LOW;
			spi_send(mode);
			spi_send(btn_send);
			spi_send(x.lo);
			spi_send(x.hi);
			spi_send(y.lo);
			spi_send(y.hi);
			spi_send(whl);
			SS_NRF24_HIGH;

			// pulse CE to transmit
			CE_HIGH;
			delay_us(12);
			CE_LOW;

			if (sync == 1) { // get ack payload of timing offset
				delay_us(400);
				if (IRQ_IS_LOW) {
					// recycle motion_data union for timing
					union motion_data offset;
					SS_NRF24_LOW;
					spi_send(0b01100001);
					offset.lo = spi_recv();
					offset.hi = spi_recv();
					SS_NRF24_HIGH;
					// shift TCNT1 by the offset, plus a
					// little more because of the time it
					// takes to add stuff to TCNT1.
					TCNT1 += offset.all + 11;
				}
			}
		}

		// power down if afk
		if (afk > AFK_TIMEOUT) {
			// enable external interrupts on INT0/1/2/3, PCINT0
			EIMSK = 0b00000111;
			PCICR = 0x01;
			// go power down mode; wake up on interrupt
			set_sleep_mode(SLEEP_MODE_PWR_DOWN);
			sei(); sleep_mode(); cli();
			// disable external interrupts
			PCICR = 0;
			EIMSK = 0;
			// restore state
			set_sleep_mode(SLEEP_MODE_IDLE);
			sync = 0;
			afk = 0;
		}
	}
}
Beispiel #12
0
// Shutdown
void bg_pwr_down()
{
  // execute sleep routine
  if (bg_pwr_exec_sleep_routine_flag)
  {
    if (bg_pwr_on_sleep != NULL)
      bg_pwr_on_sleep();
    // the flag is needed because we want to execute sleep
    // routine only when we go from pwr up to pwr down
    bg_pwr_exec_sleep_routine_flag = 0;
  }

  //Shut off ADC, TWI, SPI, Timer0, Timer1, Timer2

  ADCSRA &= ~(1<<ADEN); //Disable ADC
  ACSR |= (1<<ACD); //Disable the analog comparator
  DIDR0 = 0xFF; //Disable digital input buffers on all ADC0-ADC5 pins
  DIDR1 = (1<<AIN1D)|(1<<AIN0D); //Disable digital input buffer on AIN1/0

  power_twi_disable();
  power_spi_disable();
  power_usart0_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
#if defined(__AVR_ATmega1284P__)
  power_timer3_disable();
#endif

  //Power down various bits of hardware to lower power usage  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_mode();

  /*********/
  /* SLEEP */
  /*********/

  // The processor wakes up back here after interrupt

  //Turn on ADC, TWI, SPI, Timer0, Timer1, Timer2
  ADCSRA |= (1<<ADEN); // Enable ADC
  ACSR &= ~(1<<ACD);   // Enable the analog comparator

  // this should be set to reflect real usage of analog pins
  DIDR0 = 0x00;   // Enable digital input buffers on all ADC0-ADC5 pins
  DIDR1 &= ~(1<<AIN1D)|(1<<AIN0D); // Enable digital input buffer on AIN1/0

  power_twi_enable();
  power_spi_enable();
  power_usart0_enable();
  power_timer0_enable();
  power_timer1_enable();
  power_timer2_enable();
#if defined(__AVR_ATmega1284P__)
  power_timer3_enable();
#endif

  // check button press time and handle state
  unsigned long start = millis();
  while ( (ellapsed_millis(start) < BG_PWR_BUTTON_TIME) && (digitalRead(bg_pwr_switch_pin) == HIGH) );
  // if the button is pressed continuously for 2 seconds, swap to on state
  if (ellapsed_millis(start) >= BG_PWR_BUTTON_TIME)
    bg_pwr_state = BG_STATE_PWR_UP;

  // lower the button flag
  bg_pwr_button_pressed_flag = 0;

  // execute wake up routine only if we really woke up
  if (bg_pwr_state == BG_STATE_PWR_UP || sd_reader_interrupted)
  {
    // execute wake up routine if any is defined
    if (bg_pwr_on_wakeup != NULL)
      bg_pwr_on_wakeup();
    // next time we sleep execute sleep routine
    bg_pwr_exec_sleep_routine_flag = 1; 
  }
}