/* * © 2023, Neil McKechnie. All rights reserved. * * This file is part of CommandStation-EX * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * It is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ #ifndef I2CMANAGER_AVR_H #define I2CMANAGER_AVR_H #include #include "I2CManager.h" #include "I2CManager_NonBlocking.h" // to satisfy intellisense #include #include /**************************************************************************** TWI State codes ****************************************************************************/ // General TWI Master staus codes #define TWI_START 0x08 // START has been transmitted #define TWI_REP_START 0x10 // Repeated START has been transmitted #define TWI_ARB_LOST 0x38 // Arbitration lost // TWI Master Transmitter staus codes #define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received #define TWI_MTX_ADR_NACK 0x20 // SLA+W has been tramsmitted and NACK received #define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received #define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received // TWI Master Receiver staus codes #define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received #define TWI_MRX_ADR_NACK 0x48 // SLA+R has been tramsmitted and NACK received #define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK tramsmitted #define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK tramsmitted // TWI Miscellaneous status codes #define TWI_NO_STATE 0xF8 // No relevant state information available #define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition #define TWI_TWBR ((F_CPU / I2C_FREQ) - 16) / 2 // TWI Bit rate Register setting. #if defined(I2C_USE_INTERRUPTS) #define ENABLE_TWI_INTERRUPT (1<writeLen; bytesToReceive = currentRequest->readLen; rxCount = 0; txCount = 0; #if defined(I2C_EXTENDED_ADDRESS) if (currentRequest->i2cAddress.muxNumber() != I2CMux_None) { // Send request to multiplexer muxPhase = MuxPhase_PROLOG; // When start bit interrupt comes in, send SLA+W to MUX } else muxPhase = 0; #endif TWCR = (1< MuxPhase_OFF) { switch (twsr) { case TWI_MTX_ADR_ACK: // SLA+W has been transmitted and ACK received if (muxPhase == MuxPhase_PROLOG) { // Send MUX selecter mask to follow address I2CSubBus subBus = currentRequest->i2cAddress.subBus(); TWDR = (subBus==SubBus_All) ? 0xff : (subBus==SubBus_None) ? 0x00 : 1 << subBus; TWCR = (1< 1) { // Device transaction complete, prepare to deselect MUX by sending start bit TWCR = (1<i2cAddress.deviceAddress() == 0) { // Send stop and post rb. TWDR = 0xff; TWCR = (1< 0) { currentRequest->readBuffer[rxCount++] = TWDR; bytesToReceive--; } if (muxPhase == MuxPhase_PASSTHRU && _muxCount > 1) { // Prepare to transmit epilog to mux - first send the stop bit and start bit // (we don't need to reset mux if there is only one. TWCR = (1<i2cAddress.muxNumber(); TWDR = (muxAddress << 1) | 0; // MUXaddress+Write TWCR = (1< MuxPhase_EPILOG) { // Mux Cleardown was NAK'd, send stop and then finish. TWCR = (1<writeBuffer + (txCount++)); else TWDR = currentRequest->writeBuffer[txCount++]; bytesToSend--; TWCR = (1< 0) { currentRequest->readBuffer[rxCount++] = TWDR; bytesToReceive--; } /* fallthrough */ case TWI_MRX_ADR_ACK: // SLA+R has been sent and ACK received if (bytesToReceive <= 1) { TWCR = (1< 0) { currentRequest->readBuffer[rxCount++] = TWDR; bytesToReceive--; } TWCR = (1<i2cAddress; if (operation == OPERATION_READ || (operation==OPERATION_REQUEST && !bytesToSend)) TWDR = (deviceAddress << 1) | 1; // SLA+R else TWDR = (deviceAddress << 1) | 0; // SLA+W TWCR = (1<