Ejemplo n.º 1
0
SDErr sd_init() {
  int i;

  // Set clock rate to 400kHz
  SDErr errsv = spi_set_clockrate(400000); // Save so available for printing
  if (errsv != SD_SUCCESS) {
    return errsv;
  }

  // Set CS high for wake-up phase
  *sd_cs_ptr = 1;

  // Send 80 dummy bits == 10 dummy bytes
  for (i = 0; i < 10; i++) {
    spi_send(0xFF);
  }

  // Set CS low to begin sending commands
  *sd_cs_ptr = 0;

  // Send GO_IDLE
  //printf("Initializing card\n");
  sd_res.r1 = sd_cmd(0, 0, 0, 0, 0, 0x94); // GO_IDLE
  if (sd_res.r1 != 1) {
    //printf("Error: %02X\n", sd_res.r1);
    return SD_GOIDLE;
  }

  //printf("Card entered SPI Mode\n");

  // Send CMD8 (SEND_IF_COND)
  const uint8_t volt_range = 0x01; // 0x01 = 2.7V - 3.6V
  const uint8_t check_pattern = 0xAA; // Constant
  //printf("Sending CMD8\n");
  sd_res.r7[0] = sd_cmd(8, 0, 0, volt_range, check_pattern, 0x86);
  //printf("Initial: ");
  //sd_print_r1(sd_res.r7[0]);
  for (i = 0; i < 4; i++) {
    sd_res.r7[1 + i] = spi_send(0xFF);
    //printf("%02X ", sd_res.r7[1 + i]);
  }
  //printf("\n");

  // Verify response
  if (sd_res.r7[0] != 0x01 ||
      sd_res.r7[1] != 0x00 || sd_res.r7[2] != 0x00 ||
      sd_res.r7[3] != volt_range || sd_res.r7[4] != check_pattern) {

    /*
    printf("Invalid R7 response to CMD8: ");
    for (i = 0; i < 5; i++) {
      printf("%02X ", sd_res.r7[i]);
    }
    printf("\n");
    */

    return SD_SENDIFCOND_BADRES;
  }

  // Send ACMD41  (SD_SEND_OP_COND)
  //printf("Sending ACMD41\n");

  // First try with HCS
  if (SD_SUCCESS != sd_send_op_cond_cmd(1)) {
    errsv = sd_send_op_cond_cmd(0); // On failure, try without
    if (SD_SUCCESS != errsv) {
      //printf("Unable to initialize card\n");
      return errsv;
    }
  }

  //printf("Card initialized to Data Transfer Mode\n");

  // Disable CRC - CMD59
  /*
  printf("Disabling CRC\n");
  sd_res.r1 = sd_cmd(59, 0, 0, 0, 0, 0xFF);
  if (sd_res.r1 != 0) {
    printf("Unable to disable CRC: ");
    sd_print_r1(sd_res.r1);
    printf("\n");
    return SD_CRC_BADRES;
  }
  */

  // TODO: Read OCR of card (CMD58)

  // Set block length - CMD16
  //printf("Setting block length to 512 bytes\n");
  sd_res.r1 = sd_cmd(16, 0, 0, 0x02, 0, 0xFF); // Block Length = 512 bytes = 0x0200
  if (sd_res.r1 != 0) {
    /*
    printf("Unable to set block length: ");
    sd_print_r1(res);
    printf("\n");
    */
    return SD_BLKLEN_BADRES;
  }
  sd_global_info.block_sz = 512;

  // Increase clock rate to maximum
  errsv = spi_set_clockrate(20000000); // 20MHz
  if (errsv != SD_SUCCESS) {
    //printf("Unable to increase clock rate");
    return errsv;
  }

  return SD_SUCCESS;
}
Ejemplo n.º 2
0
void WS2801::refresh(void) 
{
    // 3 bytes per LED
    spi_send(pixels, strip_length * 3);
}
Ejemplo n.º 3
0
uint8_t ads_spi_send(uint8_t chip, uint8_t data){
	ads_select(chip);
	uint8_t ret = spi_send(data);
	ads_deselect();
	return ret;
}
Ejemplo n.º 4
0
// Clears SPI buffers
void spi_clear() {
  *sd_cs_ptr = 1;
  spi_send(0xFF);
  *sd_cs_ptr = 0;
}
Ejemplo n.º 5
0
static void nrf24_init(void)
{
	spi_setnrf24mode();
	// power up, only enable RX_DR IRQ, 2 byte CRC
	SS_NRF24_LOW;
	spi_send(0x20 | 0x00); // CONFIG
	spi_send(0b00111110);
	SS_NRF24_HIGH;
	delay_ms(20);
	// flush tx, rx
	SS_NRF24_LOW;
	spi_send(0b11100001);
	SS_NRF24_HIGH;
	SS_NRF24_LOW;
	spi_send(0b11100010);
	SS_NRF24_HIGH;
	// disable auto retransmit
	SS_NRF24_LOW;
	spi_send(0x20 | 0x04); // SETUP_RETR
	spi_send(0b00000000);
	SS_NRF24_HIGH;
	// write channel 77
	SS_NRF24_LOW;
	spi_send(0x20 | 0x05); // RF_CH
	spi_send(77);
	SS_NRF24_HIGH;
	// dynamic payloads
	SS_NRF24_LOW;
	spi_send(0x20 | 0x1c); // DYNPD
	spi_send(0b00000011);
	SS_NRF24_HIGH;
	// enable all features
	SS_NRF24_LOW;
	spi_send(0x20 | 0x1d); // FEATURE
	spi_send(0b00000111);
	SS_NRF24_HIGH;
	// addresses (use default 0xe7e7e7e7e7)
}
Ejemplo n.º 6
0
static int init_nec_8048_wvga_lcd(struct spi_device *spi)
{
    /* Initialization Sequence */
    spi_send(spi, 3, 0x01);    /* R3 = 01h */
    spi_send(spi, 0, 0x00);    /* R0 = 00h */
    spi_send(spi, 1, 0x01);    /* R1 = 0x01 (normal), 0x03 (reversed) */
    spi_send(spi, 4, 0x00);    /* R4 = 00h */
    spi_send(spi, 5, 0x14);    /* R5 = 14h */
    spi_send(spi, 6, 0x24);    /* R6 = 24h */
    spi_send(spi, 16, 0xD7);   /* R16 = D7h */
    spi_send(spi, 17, 0x00);   /* R17 = 00h */
    spi_send(spi, 18, 0x00);   /* R18 = 00h */
    spi_send(spi, 19, 0x55);   /* R19 = 55h */
    spi_send(spi, 20, 0x01);   /* R20 = 01h */
    spi_send(spi, 21, 0x70);   /* R21 = 70h */
    spi_send(spi, 22, 0x1E);   /* R22 = 1Eh */
    spi_send(spi, 23, 0x25);   /* R23 = 25h */
    spi_send(spi, 24, 0x25);   /* R24 = 25h */
    spi_send(spi, 25, 0x02);   /* R25 = 02h */
    spi_send(spi, 26, 0x02);   /* R26 = 02h */
    spi_send(spi, 27, 0xA0);   /* R27 = A0h */
    spi_send(spi, 32, 0x2F);   /* R32 = 2Fh */
    spi_send(spi, 33, 0x0F);   /* R33 = 0Fh */
    spi_send(spi, 34, 0x0F);   /* R34 = 0Fh */
    spi_send(spi, 35, 0x0F);   /* R35 = 0Fh */
    spi_send(spi, 36, 0x0F);   /* R36 = 0Fh */
    spi_send(spi, 37, 0x0F);   /* R37 = 0Fh */
    spi_send(spi, 38, 0x0F);   /* R38 = 0Fh */
    spi_send(spi, 39, 0x00);   /* R39 = 00h */
    spi_send(spi, 40, 0x02);   /* R40 = 02h */
    spi_send(spi, 41, 0x02);   /* R41 = 02h */
    spi_send(spi, 42, 0x02);   /* R42 = 02h */
    spi_send(spi, 43, 0x0F);   /* R43 = 0Fh */
    spi_send(spi, 44, 0x0F);   /* R44 = 0Fh */
    spi_send(spi, 45, 0x0F);   /* R45 = 0Fh */
    spi_send(spi, 46, 0x0F);   /* R46 = 0Fh */
    spi_send(spi, 47, 0x0F);   /* R47 = 0Fh */
    spi_send(spi, 48, 0x0F);   /* R48 = 0Fh */
    spi_send(spi, 49, 0x0F);   /* R49 = 0Fh */
    spi_send(spi, 50, 0x00);   /* R50 = 00h */
    spi_send(spi, 51, 0x02);   /* R51 = 02h */
    spi_send(spi, 52, 0x02);   /* R52 = 02h */
    spi_send(spi, 53, 0x02);   /* R53 = 02h */
    spi_send(spi, 80, 0x0C);   /* R80 = 0Ch */
    spi_send(spi, 83, 0x42);   /* R83 = 42h */
    spi_send(spi, 84, 0x42);   /* R84 = 42h */
    spi_send(spi, 85, 0x41);   /* R85 = 41h */
    spi_send(spi, 86, 0x14);   /* R86 = 14h */
    spi_send(spi, 89, 0x88);   /* R89 = 88h */
    spi_send(spi, 90, 0x01);   /* R90 = 01h */
    spi_send(spi, 91, 0x00);   /* R91 = 00h */
    spi_send(spi, 92, 0x02);   /* R92 = 02h */
    spi_send(spi, 93, 0x0C);   /* R93 = 0Ch */
    spi_send(spi, 94, 0x1C);   /* R94 = 1Ch */
    spi_send(spi, 95, 0x27);   /* R95 = 27h */
    spi_send(spi, 98, 0x49);   /* R98 = 49h */
    spi_send(spi, 99, 0x27);   /* R99 = 27h */
    spi_send(spi, 102, 0x76);  /* R102 = 76h */
    spi_send(spi, 103, 0x27);  /* R103 = 27h */
    spi_send(spi, 112, 0x01);  /* R112 = 01h */
    spi_send(spi, 113, 0x0E);  /* R113 = 0Eh */
    spi_send(spi, 114, 0x02);  /* R114 = 02h */
    spi_send(spi, 115, 0x0C);  /* R115 = 0Ch */
    spi_send(spi, 118, 0x0C);  /* R118 = 0Ch */
    spi_send(spi, 121, 0x30); /* R121 = 0x30 (normal), 0x10 (reversed) */
    spi_send(spi, 130, 0x00);  /* R130 = 00h */
    spi_send(spi, 131, 0x00);  /* R131 = 00h */
    spi_send(spi, 132, 0xFC);  /* R132 = FCh */
    spi_send(spi, 134, 0x00);  /* R134 = 00h */
    spi_send(spi, 136, 0x00);  /* R136 = 00h */
    spi_send(spi, 138, 0x00);  /* R138 = 00h */
    spi_send(spi, 139, 0x00);  /* R139 = 00h */
    spi_send(spi, 140, 0x00);  /* R140 = 00h */
    spi_send(spi, 141, 0xFC);  /* R141 = FCh */
    spi_send(spi, 143, 0x00);  /* R143 = 00h */
    spi_send(spi, 145, 0x00);  /* R145 = 00h */
    spi_send(spi, 147, 0x00);  /* R147 = 00h */
    spi_send(spi, 148, 0x00);  /* R148 = 00h */
    spi_send(spi, 149, 0x00);  /* R149 = 00h */
    spi_send(spi, 150, 0xFC);  /* R150 = FCh */
    spi_send(spi, 152, 0x00);  /* R152 = 00h */
    spi_send(spi, 154, 0x00);  /* R154 = 00h */
    spi_send(spi, 156, 0x00);  /* R156 = 00h */
    spi_send(spi, 157, 0x00);  /* R157 = 00h */
    udelay(20);
    spi_send(spi, 2, 0x00);    /* R2 = 00h */
    return 0;
}
Ejemplo n.º 7
0
//----------------------------------------------------------------------------------
//  void  halRfBurstConfig(const HAL_RF_BURST_CONFIG rfConfig, const uint8* rfPaTable, uint8 rfPaTableLen)
//
//  DESCRIPTION:
//    Used to configure all of the CC1100/CC2500 registers in one burst write.
//
//  ARGUMENTS:
//    rfConfig     - register settings
//    rfPaTable    - array of PA table values (from SmartRF Studio)
//    rfPaTableLen - length of PA table
//
//----------------------------------------------------------------------------------
void halRfBurstConfig(const HAL_RF_BURST_CONFIG rfConfig, const uint8_t *rfPaTable, uint8_t rfPaTableLen)
{
    spi_send(CC2500_IOCFG2  | CC2500_WRITE_BURST, rfConfig, sizeof(rfConfig));
    spi_send(CC2500_PATABLE | CC2500_WRITE_BURST, rfPaTable, rfPaTableLen);
}
Ejemplo n.º 8
0
static inline void spi_3366_write(const uint8_t addr, const uint8_t data)
{
	spi_send(addr | 0x80);
	spi_send(data);
	delay_us(180); // maximum of t_SWW, t_SWR
}
Ejemplo n.º 9
0
static inline void lcd_data(char c) {
  LCD_DC_DATA();
  LCD_CE_ACTIVATE();
  spi_send(c);
  LCD_CE_DEACTIVATE();
}
Ejemplo n.º 10
0
Archivo: sd.c Proyecto: FyiurAmron/avr
// @return  first byte of returned response, or SPI_EMPTY_BYTE (0xFF) if failed
uint8_t sd_commandEx( uint8_t cmd, uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t arg3, uint8_t crc, uint8_t* retBuf ) {
    sd_debug_verbose_printf( "CMD: %hhu ARG: 0x%02hhx %02hhx %02hhx %02hhx CRC: 0x%02hhx\n\r",
                  cmd, arg0, arg1, arg2, arg3, crc );
    spi_assert_SS();
	spi_send( cmd | 0x40 );
	spi_send( arg0 );
	spi_send( arg1 );
	spi_send( arg2 );
	spi_send( arg3 );
	spi_send( crc );

    uint8_t r;
    bool allowBusyByte = false;
    switch( cmd ) {
        case SD_SEND_IF_COND: // CMD8 // R7
        case SD_READ_OCR: // CMD58 // R3
            r = 5;
            break;
        case SD_SEND_STATUS: // CMD13
        //case SD_STATUS: // ACMD13 // handled by case above
            r = 2; // R2
            break;
        case SD_STOP_TRANSMISSION: // CMD12
        case SD_SET_WRITE_PROT: // CMD28
        case SD_CLR_WRITE_PROT: // CMD29
        case SD_ERASE: // CMD38
            allowBusyByte = true;  // R1b
        default: // R1
            r = 1;
            break;
    }

    for( uint8_t i = SD_SPI_RESPONSE_WAIT_MAX; i > 0; i-- ) {
        retBuf[0] = spi_recv();
        if ( retBuf[0] == SPI_EMPTY_BYTE  ) {
            continue;
        }
        if ( allowBusyByte ) { // implies r == 1
            retBuf[1] = spi_recv();
            if ( !retBuf[1] ) { // busy; don't wait, just return; caller should wait himself
                spi_deassert_SS();
                sd_debug_printf( "RET: busy\n\r" );
                return SD_COMMAND_ERROR; // == SPI_EMPTY_BYTE
            } // else !busy - we already did the wait
        } else {
            for( uint8_t j = 1; j < r; j++ ) {
                retBuf[j] = spi_recv();
            }
        }
        spi_recv(); // req. 8 cycles wait = 1 SPI output byte
	    spi_deassert_SS();
        sd_debug_verbose_printf( "RET: 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n\r",
                      retBuf[0],
              r > 1 ? retBuf[1] : 0xFF,
              r > 2 ? retBuf[2] : 0xFF,
              r > 3 ? retBuf[3] : 0xFF,
              r > 4 ? retBuf[4] : 0xFF );
        return retBuf[0];
    }
    spi_deassert_SS();
    sd_debug_printf( "RET: error: response timeout\n\r" );
    return SD_COMMAND_ERROR; // == SPI_EMPTY_BYTE
}
Ejemplo n.º 11
0
static inline void lcd_command(char c) {
  LCD_DC_COMM();
  LCD_CE_ACTIVATE();
  spi_send(c);
  LCD_CE_DEACTIVATE();
}
Ejemplo n.º 12
0
void lcd_data(uint8_t data) {
    spi_send(0b11111010); // 5 1 bits, RS = 1, RW = 0
    spi_send(data & 0xf0);
    spi_send(data << 4);
    _delay_us(40);
}
Ejemplo n.º 13
0
void lcd_instruction(uint8_t ins) {
    spi_send(0b11111000); // 5 1 bits, RS = 0, RW = 0
    spi_send(ins & 0xf0);
    spi_send(ins << 4);
    _delay_us(72);
}
Ejemplo n.º 14
0
static int truly_lcd_power(struct pxa168fb_info *fbi, unsigned int spi_gpio_cs,
					unsigned int spi_gpio_reset, int on)
{
	int err = 0;

	mfp_config(ARRAY_AND_SIZE(truly_lcd_pin_config));
	if (on) {
		if (spi_gpio_reset != -1) {
			err = gpio_request(spi_gpio_reset, "LCD_SPI_RESET");
			if (err) {
				pr_err("failed to request GPIO for LCD RESET\n");
				return -1;
			}
			gpio_direction_output(spi_gpio_reset, 0);
			msleep(1);
			gpio_set_value(spi_gpio_reset, 1);
			msleep(150);

		}

		err = spi_send(fbi, truly_spi_cmdon,
			ARRAY_SIZE(truly_spi_cmdon), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command on\n");
			return -1;
		}
		err = spi_send(fbi, truly_spi_cmd_gamma,
			ARRAY_SIZE(truly_spi_cmd_gamma), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command gamma setting\n");
			return -1;
		}
		msleep(10);
		err = spi_send(fbi, truly_spi_cmd_color,
			ARRAY_SIZE(truly_spi_cmd_color), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command RGB setting\n");
			return -1;
		}
		msleep(10);
		err = spi_send(fbi, truly_spi_cmd_on1,
			ARRAY_SIZE(truly_spi_cmd_on1), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command on1\n");
			return -1;
		}
		msleep(120);
		err = spi_send(fbi, truly_spi_cmd_on2,
			ARRAY_SIZE(truly_spi_cmd_on2), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command on2\n");
			return -1;
		}
		if (spi_gpio_reset != -1)
			gpio_free(spi_gpio_reset);
	} else  {
		err = spi_send(fbi, truly_spi_cmd_off,
			ARRAY_SIZE(truly_spi_cmd_off), spi_gpio_cs);
		if (err) {
			pr_err("failed to send spi command off\n");
			return -1;
		}

		err = gpio_request(spi_gpio_reset, "LCD_SPI_RESET");
		if (err) {
			pr_err("failed to request LCD RESET gpio\n");
			return -1;
		}
		gpio_set_value(spi_gpio_reset, 0);
		gpio_free(spi_gpio_reset);
	}
	return err;
}
Ejemplo n.º 15
0
//----------------------------------------------------------------------------------
//  rf_status_t halRfWriteFifo(uint8* data, uint8 length)
//----------------------------------------------------------------------------------
rf_status_t halRfWriteFifo(const uint8_t *data, uint8_t length)
{
    return spi_send(CC2500_TXFIFO | CC2500_WRITE_BURST, data, length);
}
Ejemplo n.º 16
0
static inline uint8_t spi_recv(void)
{
	spi_send(0x00);
	return SPDR;
}
Ejemplo n.º 17
0
uint8_t ads_read_register(uint8_t address){
	spi_send(0x20 | (address&0x1F));
	spi_send(0x00);
	uint8_t ret = spi_send(0x00);
	return ret;
}
Ejemplo n.º 18
0
static void pmw3366_init(const uint8_t dpi)
{
	spi_set3366mode();
	SS_3366_HIGH;
	delay_ms(3);

	// shutdown first
	SS_3366_LOW;
	spi_3366_write(0x3b, 0xb6);
	SS_3366_HIGH;
	delay_ms(300);

	// drop and raise ncs to reset spi port
	SS_3366_LOW;
	delay_us(40);
	SS_3366_HIGH;
	delay_us(40);

	// power up reset
	SS_3366_LOW;
	spi_3366_write(0x3a, 0x5a);
	SS_3366_HIGH;
	delay_ms(50);

	// flip on and off the clock tuning. not sure purpose...
	SS_3366_LOW;
	spi_3366_write(0x3d, 0x95);
	SS_3366_HIGH;
	delay_ms(1);
	SS_3366_LOW;
	spi_3366_write(0x3d, 0x15);
	SS_3366_HIGH;
	delay_ms(1);

	// read from 0x02 to 0x06
	SS_3366_LOW;
	spi_3366_read(0x02);
	spi_3366_read(0x03);
	spi_3366_read(0x04);
	spi_3366_read(0x05);
	spi_3366_read(0x06);

	spi_3366_write(0x10, 0x00); // disable rest mode
	spi_3366_write(0x22, 0x00); // ???

	// srom download
	spi_3366_write(0x13, 0x1d);
	SS_3366_HIGH;
	delay_ms(10);
	SS_3366_LOW;
	spi_3366_write(0x13, 0x18);

	const uint8_t *psrom = srom;
	spi_send(0x62 | 0x80);
	for (uint16_t i = 0; i < SROM_LENGTH; i++) {
		delay_us(15);
		spi_send(pgm_read_byte(psrom++));
	}
	delay_us(18);
	SS_3366_HIGH;
	delay_us(200);

	// rest mode settings (copied from g900 :P)
	SS_3366_LOW;
	spi_3366_write(0x10, 0x20); // 0x20 enables rest mode after ~10s of inactivity
	spi_3366_write(0x14, 0xff); // how long to wait before going to rest mode. 0xff is max (~10 seconds)
	spi_3366_write(0x15, 0x00); // default
	spi_3366_write(0x16, 0x00); // default
	spi_3366_write(0x17, 0xff);
	spi_3366_write(0x18, 0x63); // default
	spi_3366_write(0x19, 0x00); // default
	spi_3366_write(0x1a, 0x5e);
	spi_3366_write(0x1b, 0x8f);
	spi_3366_write(0x1c, 0x01);
	SS_3366_HIGH;


	// "manual" clock tuning
	delay_ms(1); // arbitrary padding
	SS_3366_LOW;
	spi_3366_write(0x3d, 0x93);
	spi_3366_write(0x3d, 0x13); // increase this to increase the clock frequency during run mode
	SS_3366_HIGH;
	delay_ms(1); // arbitrary padding
	SS_3366_LOW;
	spi_3366_write(0x4f, 0x91);
	spi_3366_write(0x4f, 0x11); // increase this to increase the clock frequency during rest mode
	SS_3366_HIGH;
	delay_ms(1); // arbitrary padding

	SS_3366_LOW;
	spi_3366_write(0x0f, dpi);
	spi_3366_write(0x42, 0x00); // angle snapping
	//spi_3366_write(0x63, 0x03); // 3mm lod
	SS_3366_HIGH;
}
Ejemplo n.º 19
0
void ads_write_register(uint8_t address, uint8_t value){
	spi_send(0x40 | (address&0x1F));
	spi_send(0x00);
	spi_send(value);
}
Ejemplo n.º 20
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;
		}
	}
}
Ejemplo n.º 21
0
void enable_lcd(){
	uint8_t i;

	DDRF |= (1 << PF3);
	PORTF |= (1 << PF3);
	spi_init();

	_delay_ms(15);   
	for(i=0; i<=2; i++){ //do funky initalize sequence 3 times
		spi_send(0x00);
		spi_send(0x30);

		strobel(PORTF, PF3);
		_delay_ms(7);
	}

	spi_send(0x00);
	spi_send(0x38);

	strobel(PORTF, PF3);
	_delay_ms(5);   

	spi_send(0x00);
	spi_send(0x08);

	strobel(PORTF, PF3);
	_delay_ms(5);

	spi_send(0x00);
	spi_send(0x01);

	strobel(PORTF, PF3);
	_delay_ms(5);   

	spi_send(0x00);
	spi_send(0x06);

	strobel(PORTF, PF3);
	_delay_ms(5);

	spi_send(0x00);
	spi_send(0x0C);
	
	strobel(PORTF, PF3);
	_delay_ms(5);
}