You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Modelbahn/z21emu/atmega8_detect/gleiserkennung.c

154 lines
3.7 KiB

/************************************************************
* reads some dis and make them readable over i2c bus.
* out of 8 registers only the register 1 is needed
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* (TXD) PD1 -|3 26|- PC3 (ADC3)
* (INT0) PD2 -|4 25|- PC2 (ADC2)
* (INT1) PD3 -|5 24|- PC1 (ADC1) Sensor 4
* (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Sensor 3
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* (XTAL2/TOSC2) PB6 -|9 20|- AVCC
* (XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* Sensor 7 (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Sensor 6 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Sensor 2
* Sensor 5 (ICP1) PB0 -|14 15|- PB1 (OC1A) Sensor 1
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
volatile int i2c_reg;
volatile uint8_t i2c_inregs[I2C_NUM_REGS];
volatile uint8_t i2c_outregs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
char i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_inregs[i] = i;
i2c_outregs[i] = i | 0x80;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS)
i2c_reg = data;
else
i2c_reg = 0; // FIXME: wrong address so start at register 0
TWCR_ACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_inregs[i2c_reg] = data;
i2c_reg++;
}
TWCR_ACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_outregs[i2c_reg];
// TWDR = 0xF3;
i2c_reg++;
}
else {
TWDR = 0; //Kein Daten mehr im Buffer
}
TWCR_ACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
#define OFFDELAY 0x2000;
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
long int t;
// i2c benutzt PORTC bit5+C4
i2c_slave_init (0x30);
while( 1 ) {
if (PINB & 0x02) cnt[0] = OFFDELAY;
if (PINB & 0x04) cnt[1] = OFFDELAY;
if (PINC & 0x02) cnt[2] = OFFDELAY;
if (PINC & 0x01) cnt[3] = OFFDELAY;
if (PINB & 0x01) cnt[4] = OFFDELAY;
if (PIND & 0x80) cnt[5] = OFFDELAY;
if (PIND & 0x40) cnt[6] = OFFDELAY;
if (PIND & 0x20) cnt[7] = OFFDELAY;
for (i = 0; i < 8; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_outregs[1] = inval;
}
return 0;
};