void TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart, uint8_t blocking) { // Wait until ready while (!isTWIReady()) {_delay_us(1);} // Reset the I2C stuff TWCR = (1 << TWINT)|(1 << TWSTO); TWIInit(); // Set repeated start mode TWIInfo.repStart = repStart; // Copy transmit info to global variables TWITransmitBuffer = (uint8_t *)TXdata; TXBuffLen = dataLen; TXBuffIndex = 0; // If a repeated start has been sent, then devices are already listening for an address // and another start does not need to be sent. if (TWIInfo.mode == RepeatedStartSent) { TWIInfo.mode = Initializing; TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer TWISendTransmit(); // Send the data } else // Otherwise, just send the normal start signal to begin transmission. { TWIInfo.mode = Initializing; TWISendStart(); } if(blocking){ // Wait until ready while (!isTWIReady()){_delay_us(1);} } }
uint8_t isTWIReady() { if ( (TWIInfo.mode == Ready) | (TWIInfo.mode == RepeatedStartSent) ) { // xprintf("i2c ready\n"); return 1; } else { if(TWIInfo.mode == Initializing){ switch(TWIInfo.errorCode){ case TWI_SUCCESS: break; case TWI_NO_RELEVANT_INFO: break; case TWI_LOST_ARBIT: case TWI_MT_DATA_NACK: // Some kind of I2C error, reset and re-init xprintf("I2C init error: %d\n", TWIInfo.errorCode); TWCR = (1 << TWINT)|(1 << TWSTO); TWIInit(); break; default: xprintf("Other i2c init error: %d\n", TWIInfo.errorCode); } } return 0; } }
void matrix_scan_kb(void) { #ifdef WATCHDOG_ENABLE wdt_reset(); #endif #ifdef ISSI_ENABLE // switch/underglow lighting update static uint32_t issi_device = 0; static uint32_t twi_last_ready = 0; if(twi_last_ready > 1000){ // Its been way too long since the last ISSI update, reset the I2C bus and start again xprintf("TWI failed to recover, TWI re-init\n"); twi_last_ready = 0; TWIInit(); force_issi_refresh(); } if(isTWIReady()){ twi_last_ready = 0; // If the i2c bus is available, kick off the issi update, alternate between devices update_issi(issi_device, issi_device); if(issi_device){ issi_device = 0; }else{ issi_device = 3; } }else{ twi_last_ready++; } #endif matrix_scan_user(); }
void matrix_scan_kb(void) { #ifdef WATCHDOG_ENABLE wdt_reset(); #endif #ifdef ISSI_ENABLE // switch/underglow lighting update static uint32_t issi_device = 0; static uint32_t twi_last_ready = 0; if(twi_last_ready > 1000){ // Its been way too long since the last ISSI update, reset the I2C bus and start again dprintf("TWI failed to recover, TWI re-init\n"); twi_last_ready = 0; TWIInit(); force_issi_refresh(); } if(isTWIReady()){ twi_last_ready = 0; // If the i2c bus is available, kick off the issi update, alternate between devices update_issi(issi_device, issi_device); if(issi_device){ issi_device = 0; }else{ issi_device = 3; } }else{ twi_last_ready++; } #endif // Update layer indicator LED // // Not sure how else to reliably do this... TMK has the 'hook_layer_change' // but can't find QMK equiv static uint32_t layer_indicator = -1; if(layer_indicator != layer_state){ for(uint32_t i=0;; i++){ // the layer_info list should end with layer 0xFFFFFFFF // it will break this out of the loop and define the unknown layer color if((layer_info[i].layer == (layer_state & layer_info[i].mask)) || (layer_info[i].layer == 0xFFFFFFFF)){ OCR1A = layer_info[i].color.red; OCR1B = layer_info[i].color.green; OCR1C = layer_info[i].color.blue; layer_indicator = layer_state; break; } } } matrix_scan_user(); }
int main(void) { // \/ \/ \/ \/ Setup \/ \/ \/ \/ // -------- Initialize TWI -------- TWIInit(); // -------- Pin Registers -------- // Set all of PORTC to Input DDRC = 0x00; // Set PORTB and D to outputs DDRB = 0xFF; DDRD = 0xFF; // -------- Interrupts -------- sei(); // Pin change interrupts PCICR = (1 << PCIE1); // Enable interrupts for PCIE2 [14:8] PCMSK1 = (1 << PCINT8) | (1 << PCINT9) | (1 << PCINT10) | (1 << PCINT11); // Enable interrupts for PC0 PC1 PC2 and PC3 (PCINT8, 9, 10, 11) // Pin change interrupts //PCICR = (1 << PCIE2); // Enable interrupts for PCIE2 [23:16] //PCMSK2 = (1 << PCINT18) | (1 << PCINT19); // Enable interrupts for PD2 and PD3 // -------- PID Loop Timer -------- // Set Timer 1 clock prescaler to 1/64 TCCR1B = (0 << CS12) | (1 << CS11) | (1 << CS10); // -------- PWM timer Setup -------- TCCR0A = (0 << COM0A0) | (1 << COM0A1) | (0 << COM0B0) | (1 << COM0B1) | // Non inverting mode (1 << WGM00) | (1 << WGM01); // Fast PWM mode OCR0A = 128; OCR0B = 0; TCCR0B = (0 << CS02) | (0 << CS01) | (1 << CS00); // Start timer with 1/64 pre scaler // -------- Read PID Parameters into RAM -------- // PID parameters eeprom_read_block(&velocityPID, &PID_v, sizeof(MotorPID::PID)); /*velocityPID.Kp = 140; velocityPID.Ki = 2; velocityPID.Kd = 0; velocityPID.K0 = 20000;*/ // Create motor objects m_motorA = new MotorPID(&OCR0A, &PORTB, 0x01, 0x02, velocityPID); m_motorB = new MotorPID(&OCR0B, &PORTB, 0x04, 0x08, velocityPID); while (1) { // -------- 50ms PID Loop -------- if (TCNT1 >= 12500) // > 50ms PID loop { if (++watchdog > WATCHDOG) { m_motorA->motor.Velocity = 0; m_motorB->motor.Velocity = 0; } // Take a snapshot of each motor status m_motorA->snapshot(TCNT1); m_motorB->snapshot(TCNT1); // Reset the PID timer once snapshots are taken TCNT1 = 0; // Spin PID for each motor m_motorA->spin(); m_motorB->spin(); } // -------- TWI check -------- if (TWCR & (1 << TWINT)) // If TWINT is set then we need to handle some TWI comms { constructOutStr(); handleTWI(); } } }
void TWIInit() { // Initialize with hard coded slave address of 4 TWIInit(0x08); }
void initializeI2C(){ TWIInit(); }
int main(void) { init(); //****** //TEST 1 //****** #if _TEST == 1 bool toggle = false; uint8_t packet_pos = 0; char c; DDRD |= (1 << PD6); init(); while(true) { c = uart0_getchar(); if (c == 'y') { toggle = false; uart0_putchar('y'); } if (c == 'n') { toggle = true; uart0_putchar('n'); } if (toggle) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); } //****** //TEST 2 //****** #elif _TEST == 2 char c; DDRD |= (1 << PD6) // set outputs in PORTD | (1 << PD5) | (1 << PD4); TCCR1A = 0x00; // clear all current timer 1 settings TCCR1B = 0x00; TCCR1B |= (1 << WGM12); // turn on CTC mode: // Clear Timer on Compare Match TIMSK1 = (1 << TOIE1); // enable global and timer overflow interrupt TCCR1B |= (1 << CS10); while(true) { c = uart0_getchar(); if (c != EOF) { if (c == 'f') servoTurn(0); if (c == 'g') servoTurn(90); if (c == 'h') servoTurn(180); } } //****** v //TEST 3 //****** #elif _TEST == 3 Packet host_packet; PacketInit(&host_packet); int len = 0; char c; DDRD |= (1 << PD6); while(1) { c = uart0_getchar(); if (c != EOF) len = PacketProcessChar(&host_packet, c); if (len > 0) uart0_printstr("got a packet!\r\n"); } //****** //TEST 4 //****** #elif _TEST == 4 uint8_t messageBuf[4]; uint8_t TWI_slaveAddress = 0x10; DDRD |= (1 << PD5) | (1 << PD6); TWIInit(); sei(); while(1) { PORTD ^= (1 << PD5) | (1 << PD6); TWIStart(); //TWIStop(); _delay_ms(500); } #elif _TEST == 5 Packet host_packet; PacketInit(&host_packet); int len = 0; char c; DDRD |= (1 << PD5); uint8_t message_buf[] = {0xFE, 0xFE, 0x01, 0x04, 0x02, 0x2B, 0x01, 0xCC}; int i; while(1) { c = uart0_getchar(); if (c != EOF) { len = PacketProcessChar(&host_packet, c); } if (len > 0) { PORTD ^= (1 << PD5); len = 0; } //for (i = 0; i < 8; i++) // uart0_putchar(message_buf[i]); //uart0_putchar(0xFD); //uart0_putchar(0xFF); //c = uart0_getchar(); //if (c != EOF) { // len = PacketProcessChar(&host_packet, c); //PORTD ^= (1 << PD5); //} //if (len > 0) //PORTD ^= (1 << PD5); //_delay_ms(1000); } /* DDRD |= (1 << PD5); char c; while(1) { c = uart0_getchar(); if (c != EOF) { uart0_putchar(c); PORTD ^= (1 << PD5); //_delay_ms(500); } }*/ #endif // _TEST return 0; }