/* cpu runs at 1mhz */ #define F_CPU 1000000 #include #include #include #include #include #include /* i2c device addresses */ #define L3GD20 0b11010100 #define L3GD20_WHOAMI 0xf #define L3GD20_CTRLREG1 0x20 #define LIS302DL 0b00111000 #define LIS302DL_WHOAMI 0xf #define LIS302DL_CTRLREG1 0x20 typedef enum { TWM_INVALID = 0, TWM_WRITE, TWM_READ_MULTI, } twMode; typedef enum { TWST_WAIT = 0, TWST_OK = 1, TWST_ERR = 2, } twStatus; typedef struct { twMode mode; uint8_t address; uint8_t subaddress; uint8_t data; uint8_t step; /* read data store */ uint8_t *retData; /* number of bytes to be read */ uint8_t count; /* current byte */ uint8_t i; twStatus status; } twReq; volatile twReq twr; void twStartRaw () { /* disable stop, enable interrupt, reset twint, enable start, enable i2c */ TWCR = (TWCR & ~(1 << TWSTO)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); } void twStopRaw () { /* disable start, enable interrupt, reset twint, enable stop, enable i2c */ TWCR = (TWCR & ~(1 << TWSTA)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); } void twFlushRaw () { /* disable start/stop, enable interrupt, reset twint, enable i2c */ TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO) | (1 << TWEA))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN); } /* flush and send master ack */ void twFlushContRaw () { /* disable start/stop, enable interrupt, reset twint, enable i2c, send master ack */ TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN) | (1 << TWEA); } void twWaitRaw () { while (!(TWCR & (1 << TWINT))); } bool twWriteRaw (uint8_t data) { TWDR = data; if (TWCR & (1 << TWWC)) { printf("write collision\n"); return false; } else { return true; } } void twInit () { /* set scl to 3.6 kHz (at 1Mhz CPU speed)*/ TWBR = 2; TWSR |= 0x3; /* set prescaler to 64 */ twr.mode = TWM_INVALID; twr.status = TWST_ERR; } /* high-level write */ static bool twWrite (uint8_t address, uint8_t subaddress, uint8_t data) { /* do not start if request is pending */ if (twr.status == TWST_WAIT) { return false; } twr.mode = TWM_WRITE; twr.address = address; twr.subaddress = subaddress; twr.data = data; twr.step = 0; twr.status = TWST_WAIT; /* wait for stop finish */ while (TW_STATUS != 0xf8); twStartRaw (); return true; } static bool twReadMulti (uint8_t address, uint8_t subaddress, uint8_t *retData, uint8_t count) { /* do not start if request is pending */ if (twr.status == TWST_WAIT) { return false; } twr.mode = TWM_READ_MULTI; twr.address = address; twr.subaddress = subaddress; twr.retData = retData; twr.count = count; twr.i = 0; twr.step = 0; twr.status = TWST_WAIT; /* wait for stop finish */ while (TW_STATUS != 0xf8); twStartRaw (); return true; } void ledInit () { /* set led1,led2 to output */ DDRB |= (1 << PB6) | (1 << PB7); /* set led3,led4,led5,led6 to output */ DDRD |= (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); } /* show data with leds */ void ledShow (unsigned char val) { PORTB = (PORTB & ~((1 << PB6) | (1 << PB7))) | ((val & 0x3) << PB6); PORTD = (PORTD & ~((1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5))) | (((val >> 2) & 0xf) << PD2); } void uartInit () { /* Set baud rate (9600, double speed, at 1mhz) */ UBRR0H = 0; UBRR0L = 12; /* enable double speed mode */ UCSR0A = (1 << U2X0); /* Enable receiver and transmitter */ UCSR0B = (1<