int main( void ) { _delay_ms(100); // set clock speed CLKPR = _BV( CLKPCE ); // enable clock prescale change CLKPR = 0; // full speed (8MHz); #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || \ defined(__AVR_ATtiny85__) // set up periodic timer for state machine ('script_tick') TCCR0B = _BV( CS02 ) | _BV(CS00); // start timer, prescale CLK/1024 TIFR = _BV( TOV0 ); // clear interrupt flag TIMSK = _BV( TOIE0 ); // enable overflow interrupt // set up output pins PORTB = INPI2C_MASK; // turn on pullups DDRB = LED_MASK; // set LED port pins to output #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || \ defined(__AVR_ATtiny84__) // set up periodic timer for state machine ('script_tick') //TCCR0B = _BV( CS02 ) | _BV(CS00); // start timer, prescale CLK/1024 //TIFR0 = _BV( TOV0 ); // clear interrupt flag //TIMSK0 = _BV( TOIE0 ); // enable overflow interrupt // set up output pins PORTA = INPI2C_MASK; // turn on pullups DDRA = 0xFF; //LEDA_MASK; // set LED port pins to output DDRB = 0xFF; //LEDB_MASK; // set LED port pins to output #endif fanfare( 3, 300 ); #if 0 // test for ATtiny44/84 MaxM fanfare( 3, 300 ); IRsend_enableIROut(); while( 1 ) { _delay_ms(10); IRsend_iroff(); _delay_ms(10); IRsend_iron(); } /* uint8_t f = OCR1B; while( 1 ) { _delay_ms(10); f++; if( f== OCR1A ) f=0; // OCR1A == period OCR1B = f; // OCR1B == duty cycle (0-OCR1A) } */ #endif #if 0 // test timing of script_tick _delay_ms(2000); sei(); _delay_ms(500); // this should cause script_tick to equal 15 uint8_t j = script_tick; for( int i=0; i<j; i++ ) { led_flash(); _delay_ms(300); } #endif ////// begin normal startup uint8_t boot_mode = eeprom_read_byte( &ee_boot_mode ); uint8_t boot_script_id = eeprom_read_byte( &ee_boot_script_id ); uint8_t boot_reps = eeprom_read_byte( &ee_boot_reps ); //uint8_t boot_fadespeed = eeprom_read_byte( &ee_boot_fadespeed ); uint8_t boot_timeadj = eeprom_read_byte( &ee_boot_timeadj ); // initialize i2c interface uint8_t i2c_addr = eeprom_read_byte( &ee_i2c_addr ); if( i2c_addr==0 || i2c_addr>0x7f) i2c_addr = I2C_ADDR; // just in case i2c_addrs[0] = i2c_addr; for( uint8_t i = 1; i<slaveAddressesCount; i++ ) { i2c_addrs[i] = i2c_addrs[0] + i; } usiTwiSlaveInit( i2c_addrs ); timeadj = boot_timeadj; if( boot_mode == BOOT_PLAY_SCRIPT ) { play_script( boot_script_id, boot_reps, 0 ); } sei(); // enable interrupts #if 0 basic_tests(); #endif RB_Init(); // This loop runs forever. // If the TWI Transceiver is busy the execution will just // continue doing other operations. for(;;) { handle_i2c(); handle_inputs(); handle_script(); handle_ir_queue(); } } // end
//-------------------------------------------------------------------------------------------------- // NOTE: We can't set the baud rate programmatically for a SocketCAN device as it may be shared // by multiple applications. It has to be set system wide. COM_DeviceHandle COM_DriverDeviceOpen( const char* deviceName, const char* baudRate ) { if ( eDS_Inactive == gDriverState ) { // Setup driver if this is the first time this routine has been called for ( int32_t i = 0; i < MAX_NUM_DEVICES; i++ ) { gDevices[ i ].mbInUse = false; } gDriverState = eDS_Active; } // Check device name if ( strlen( deviceName ) > IF_NAMESIZE-1 ) { LogMsg( eV_Error, "Device name is to long. Max length is %i\n", IF_NAMESIZE-1 ); return NULL; } // Check to see if the device is already open for ( int32_t i = 0; i < MAX_NUM_DEVICES; i++ ) { if ( gDevices[ i ].mbInUse && strncmp( gDevices[ i ].mName, deviceName, IF_NAMESIZE ) == 0 ) { LogMsg( eV_Error, "%s is already open\n", deviceName ); return NULL; } } // Look for an empty slot int32_t deviceIdx = -1; for ( int32_t i = 0; i < MAX_NUM_DEVICES; i++ ) { if ( !gDevices[ i ].mbInUse ) { deviceIdx = i; break; } } if ( -1 == deviceIdx ) { LogMsg( eV_Error, "Unable to find slot for device. Please increase MAX_NUM_DEVICES\n" ); return NULL; } // Open the device strcpy( gDevices[ deviceIdx ].mName, deviceName ); gDevices[ deviceIdx ].mSocketId = socket( PF_CAN, SOCK_RAW, CAN_RAW ); if ( gDevices[ deviceIdx ].mSocketId < 0 ) { LogMsg( eV_Error, "Unable to open socket\n" ); return NULL; } // Specify non-blocking operation fcntl( gDevices[ deviceIdx ].mSocketId, F_SETFL, O_NONBLOCK ); // Locate the interface we wish to use struct ifreq ifr; strcpy( ifr.ifr_name, deviceName ); // ifr.ifr_ifindex gets filled with that device's index if ( ioctl( gDevices[ deviceIdx ].mSocketId, SIOCGIFINDEX, &ifr ) < 0 ) { LogMsg( eV_Error, "Can't open %s\n", deviceName ); return NULL; } // Select that CAN interface, and bind the socket to it. */ struct sockaddr_can addr; addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; if ( bind( gDevices[ deviceIdx ].mSocketId, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) { LogMsg( eV_Error, "Can't bind %s to socket\n", deviceName ); return NULL; } // Setup a rolling buffer to take the incoming data RB_Init( &gDevices[ deviceIdx ].mReadBuffer, gDevices[ deviceIdx ].mReadBufferData, sizeof( gDevices[ deviceIdx ].mReadBufferData ) ); gDevices[ deviceIdx ].mbInUse = true; LogMsg( eV_Info, "Opened channel\n" ); // Success return deviceIdxToHandle( deviceIdx ); }