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; }
void WS2801::refresh(void) { // 3 bytes per LED spi_send(pixels, strip_length * 3); }
uint8_t ads_spi_send(uint8_t chip, uint8_t data){ ads_select(chip); uint8_t ret = spi_send(data); ads_deselect(); return ret; }
// Clears SPI buffers void spi_clear() { *sd_cs_ptr = 1; spi_send(0xFF); *sd_cs_ptr = 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) }
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; }
//---------------------------------------------------------------------------------- // 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); }
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 }
static inline void lcd_data(char c) { LCD_DC_DATA(); LCD_CE_ACTIVATE(); spi_send(c); LCD_CE_DEACTIVATE(); }
// @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 }
static inline void lcd_command(char c) { LCD_DC_COMM(); LCD_CE_ACTIVATE(); spi_send(c); LCD_CE_DEACTIVATE(); }
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); }
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); }
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; }
//---------------------------------------------------------------------------------- // 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); }
static inline uint8_t spi_recv(void) { spi_send(0x00); return SPDR; }
uint8_t ads_read_register(uint8_t address){ spi_send(0x20 | (address&0x1F)); spi_send(0x00); uint8_t ret = spi_send(0x00); return ret; }
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; }
void ads_write_register(uint8_t address, uint8_t value){ spi_send(0x40 | (address&0x1F)); spi_send(0x00); spi_send(value); }
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; } } }
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); }