/* * Process a command-complete interrupt. These are only generated by * the transmission of frames. This routine is deceptively simple, since * most of the real work is done by iestart(). */ static int ietint(struct ie_softc *sc) { int status; int i; sc->arpcom.ac_if.if_timer = 0; sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; for (i = 0; i < sc->xmit_count; i++) { status = sc->xmit_cmds[i]->ie_xmit_status; if (status & IE_XS_LATECOLL) { printf("ie%d: late collision\n", sc->unit); sc->arpcom.ac_if.if_collisions++; sc->arpcom.ac_if.if_oerrors++; } else if (status & IE_XS_NOCARRIER) { printf("ie%d: no carrier\n", sc->unit); sc->arpcom.ac_if.if_oerrors++; } else if (status & IE_XS_LOSTCTS) { printf("ie%d: lost CTS\n", sc->unit); sc->arpcom.ac_if.if_oerrors++; } else if (status & IE_XS_UNDERRUN) { printf("ie%d: DMA underrun\n", sc->unit); sc->arpcom.ac_if.if_oerrors++; } else if (status & IE_XS_EXCMAX) { printf("ie%d: too many collisions\n", sc->unit); sc->arpcom.ac_if.if_collisions += 16; sc->arpcom.ac_if.if_oerrors++; } else { sc->arpcom.ac_if.if_opackets++; sc->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL; } } sc->xmit_count = 0; /* * If multicast addresses were added or deleted while we were * transmitting, ie_mc_reset() set the want_mcsetup flag indicating * that we should do it. */ if (sc->want_mcsetup) { mc_setup(sc); sc->want_mcsetup = 0; } /* Wish I knew why this seems to be necessary... */ sc->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL; iestart(&sc->arpcom.ac_if); return (0); /* shouldn't be necessary */ }
int main( void ) { uint32_t val = 0; char textbuf [ (2*16) + 1 ]; // lcd /* setup */ // LCD lcd_init(); // Timer: enable a timer so we can measure passage of time // // Given: 20MHz clock // --> if we want resolution of ms (1/1000th second) .. actually, we want us (1/10th of a ms) so we can measure partial ms // --> and we have 1/20000000 clock resolution // -----> 2000 ticks will get us there (20,000 will get us ms) // // Goal: Use CTC interupt mode (CTC -> Clear on Timer Compare) // So a compare matches, it clears to zero and triggers interupt TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode OCR1A = 2000; // number to compare against TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt TCCR1B |= (1 << CS10); // Set up timer , with no prescaler (works at full MHz of clock) // Receiver setup - set up pin change interupt #if 1 EICRA &= ~ ( (1 << ISC01) | (1 << ISC01) ); // clear ISC01+ISC00 EICRA |= ( (1 << ISC00) ); // 00 set and 01 unset means any edge will make event PCMSK0 |= ( (1 << PCINT0) | (1 << PCINT1) ); // Pins to monitor: PA0 and PA1 PCICR |= (1 << PCIE0); // PA is monitored #endif // Serial - setup (for motor controller) mc_setup(); // TWI - set up unsigned char twibuf [ TWI_BUFFER_SIZE ]; unsigned char TWI_slaveAddress; TWI_slaveAddress = 0x10; // our TWI address TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); // Initialise TWI module as slave; include addr+general unsigned char twi_heartbeat_counter = 0; // setup done - kick up interupts sei(); // lets burn the first couple of seconds, so the receiver can get some signal // before we start blasting stuff into the motor controllers { unsigned int start_sec = g_time_s; while ( g_time_s - start_sec < 3 ) { nop(); } } // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); #if 1 // timer test .. show per-second counter update on lcd if ( 1 ) { unsigned int last_sec = g_time_s; unsigned int last_us = _g_time_us_tick; unsigned char sent_l = 0, sent_r = 0; char message [ 17 ]; while(1) { unsigned int ch1 = g_ch1_duration; unsigned int ch2 = g_ch2_duration; // 100ms has past? if ( _g_time_us_tick - last_us > 1000 ) { if ( g_control_twi ) { // we're on TWI control, but if nothing comes in.. revert back to RC if ( g_time_s - g_control_last_s > 2 ) { g_control_twi = 0; } } else { mc_set_by_receiver ( ch1, ch2, &sent_l, &sent_r, message ); } last_us = _g_time_us_tick; } // .1sec tick // one second has past? update lcd if ( g_time_s != last_sec ) { //sprintf ( textbuf, "recv %2d %2d ", g_ch1_duration, g_ch2_duration ); sprintf ( textbuf, "m %2d %2d th %2d %2d #", sent_l, sent_r, ch1, ch2 ); lcd_xy ( 0, 0 ); lcd_puts( textbuf ); // display number right adjusted //sprintf ( textbuf, "t%2d #", g_time_s ); sprintf ( textbuf, "t%2d # %s", g_time_s, message ); lcd_xy ( 0, 1 ); lcd_puts( textbuf ); // display number right adjusted last_sec = g_time_s; } // 1 sec tick // TWI/I2C stuff, talk to r-pi // // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver ( twibuf, 3 ); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // don't care } else { // Ends up here if the last operation was a reception as Slave Address Match // Example of how to interpret a command and respond. #if 0 // TWI_CMD_MASTER_WRITE stores the data to PORTB if (twibuf[0] == TWI_CMD_MASTER_WRITE) { PORTB = twibuf[1]; } #endif // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if ( twibuf[0] == tc_heartbeat ) { twibuf [ 0 ] = 1; twibuf [ 1 ] = twi_heartbeat_counter++; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_gethello ) { sprintf ( twibuf + 1, "hello" ); twibuf [ 0 ] = strlen ( twibuf + 1 ); // len TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_setmotors ) { g_control_last_s = g_time_s; mc_speed ( mcm_left, twibuf [ 1 ] ); mc_speed ( mcm_right, twibuf [ 2 ] ); } else if ( twibuf[0] == tc_takeover ) { g_control_last_s = g_time_s; g_control_twi = 1; } else if ( twibuf[0] == tc_release ) { g_control_twi = 0; } else { twibuf [ 0 ] = 1; twibuf [ 1 ] = 0xde; twibuf [ 2 ] = 0xad; twibuf [ 3 ] = 0xbe; twibuf [ 4 ] = 0xef; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } } } else { // Ends up here if the last operation was a transmission // don't care } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else { // Ends up here if the last operation completed unsuccessfully TWI_Act_On_Failure_In_Last_Transmission ( TWI_Get_State_Info() ); } // success/fail } // TWI busy? // spin _delay_ms ( 20 ); } // while forever } // if 1 #endif /* churn forever */ while(1); return ( 0 ); }