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-v2.c

251 lines
6.2 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)
* Sensor 1 (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* Sensor 2 (TXD) PD1 -|3 26|- PC3 (ADC3) Relais 1
* Sensor 3 (INT0) PD2 -|4 25|- PC2 (ADC2) Relais 2
* Sensor 4 (INT1) PD3 -|5 24|- PC1 (ADC1) Relais 3
* Sensor 5 (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Relais 4
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* Sen6(XTAL2/TOSC2) PB6 -|9 20|- AVCC
* Sen7(XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Relais 7 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Relais 5
* Relais 8 (ICP1) PB0 -|14 15|- PB1 (OC1A) Relais 6
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.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
#define VERSION 2
#define I2C_DEFAULT_ADDR 0x4F
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_DOOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
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 || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
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_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
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;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
int offdelay;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_system[I2C_SREG_DOOFFDELAY] = EEPROM_read(I2C_SREG_DOOFFDELAY);
if (i2c_system[I2C_SREG_DOOFFDELAY] == 0) {
i2c_system[I2C_SREG_DOOFFDELAY] = 0xFF;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
DDRB |= 1 | (1<<1) | (1<<2);
DDRC |= 1 | (1<<1) | (1<<2) | (1<<3);
DDRD |= (1<<7);
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
if (PIND & 0x01) cnt[0] = offdelay;
if (PIND & 0x02) cnt[1] = offdelay;
if (PIND & 0x04) cnt[2] = offdelay;
if (PIND & 0x08) cnt[3] = offdelay;
if (PIND & 0x10) cnt[4] = offdelay;
if (PINB & 0x40) cnt[5] = offdelay;
if (PINB & 0x80) 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_regs[0] = inval;
//
// digital out registers..
if (i2c_regs[1] & 0x01) PORTC |= (1 << 3);
else PORTC &= ~(1 << 3);
if (i2c_regs[1] & 0x02) PORTC |= (1 << 2);
else PORTC &= ~(1 << 2);
if (i2c_regs[1] & 0x04) PORTC |= (1 << 1);
else PORTC &= ~(1 << 1);
if (i2c_regs[1] & 0x08) PORTC |= 1;
else PORTC &= ~1;
if (i2c_regs[1] & 0x10) PORTB |= (1 << 2);
else PORTB &= ~(1 << 2);
if (i2c_regs[1] & 0x20) PORTB |= (1 << 1);
else PORTB &= ~(1 << 1);
if (i2c_regs[1] & 0x40) PORTD |= (1 << 7);
else PORTD &= ~(1 << 7);
if (i2c_regs[1] & 0x80) PORTB |= 1;
else PORTB &= ~1;
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};