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.

163 lines
9.5 KiB

#include "USART1.h"
// USARTs common settings : Speed and Timeouts
const uint16_t USART_UBRR[8] PROGMEM={ (F_CPU/8UL)/19200-1, (F_CPU/8UL)/500000-1,
(F_CPU/8UL)/2400-1, (F_CPU/8UL)/9600-1,
(F_CPU/8UL)/115200-1, (F_CPU/8UL)/250000-1,
(F_CPU/8UL)/1000000-1, /*(F_CPU/8UL)/10000000-1*/ 0}; // Fosc=16MHz : 19.2k, 500k, 2.4k, 9.6k, 115.2k, 250k, 1M, 1M
const uint16_t USART_TIMEOUT[8] PROGMEM={ (IDIBUS_19200B_INTERFRAME_TIMEOUT_US/8*16), (IDIBUS_500K_INTERFRAME_TIMEOUT_US/8*16),
(IDIBUS_2400B_INTERFRAME_TIMEOUT_US/8*16), (IDIBUS_9600B_INTERFRAME_TIMEOUT_US/8*16),
(IDIBUS_115200B_INTERFRAME_TIMEOUT_US/8*16), (IDIBUS_250K_INTERFRAME_TIMEOUT_US/8*16),
(IDIBUS_1M_INTERFRAME_TIMEOUT_US/8*16), (IDIBUS_1M_INTERFRAME_TIMEOUT_US/8*16) };
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISR(USART1_TX_vect){
if (USART1STR.TxSendedCount == USART1STR.TxBufCount){
*USART1STR.USART->UCRSB |= (1<<RXCIE1)|(1<<RXEN1);
*USART1STR.USART->UCRSB &= ~((1<<TXCIE1)|(1<<TXEN1));
USART1STR.TxSendedCount = 0;
USART1STR.TxBufCount = 0;
USART1STR.TxComplete = 1;
USART1_TX_DDR&=~(1<<USART1_TX_BIT); USART1_TX_PORT|=1<<USART1_TX_BIT; // TXD -> Z
USART1_DRE_DDR&=~(1<<USART1_DRE_BIT); USART1_DRE_PORT&=~(1<<USART1_DRE_BIT); // RDE -> 0
} else {
*USART1STR.USART->UDR=USART1STR.TX_BUF[USART1STR.TxSendedCount];
USART1STR.TxSendedCount++;
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISR(USART1_RX_vect){
TIMSK3=0; TCNT3=0; // Timeout Timer3 On, clkI/O/8 (From prescaller)
TCCR3B=2; TIMSK3=1<<OCIE3A;
if (*USART1STR.USART->UCRSA & ((1<<FE1) | (1<<DOR1)) )
USART1STR.RxError = 1;
if (USART1STR.RxBufCount < USART1_BUF_SIZE){
USART1STR.RX_BUF[USART1STR.RxBufCount] = *USART1STR.USART->UDR;
USART1STR.RxBufCount++;
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISR(TIMER3_COMPA_vect) {
TCCR3B=0; TCNT3=0; TIMSK3=0; // Timeout TIMER3 off
*USART1STR.USART->UCRSB&=~((1<<RXCIE1)|(1<<RXEN1)); // RX off
USART1STR.RxComplete = 1; // RX data ready
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_Init(void) {
//USART1STR.USART = USART1_PERIPH_POINTER;
//USART1STR.DMATX = USART1_DMA_TX_STREAM;
USART1_ADR.UCRSA = &UCSR1A;
USART1_ADR.UCRSB = &UCSR1B;
USART1_ADR.UCRSC = &UCSR1C;
USART1_ADR.UDR = &UDR1;
USART1_ADR.UBRR = &UBRR1;
USART1STR.USART = &USART1_ADR;
USART1STR.RX_BUF = USART1_RX_BUF;
USART1STR.TX_BUF = USART1_TX_BUF;
USART1STR.TxBufCount = 0;
USART1STR.TxSendedCount = 0;
USART1STR.RxBufCount = 0;
USART1STR.RxComplete = 0;
USART1STR.TxComplete = 1;
USART1STR.InterFrameTimeoutTicks = 0;
USART1_INTERFACE.SetNewBaudrate = USART1_SetBaudrate;
USART1_INTERFACE.SendTxBuf = USART1_SendTxBuf;
USART1_INTERFACE.SendByteBuf = USART1_SendByteBuf;
USART1_INTERFACE.IsNewRxMessage = USART1_IsNewRxMessage;
USART1_INTERFACE.IsTxActive = USART1_IsTxActive;
USART1_INTERFACE.IsRxError = USART1_IsRxError;
USART1_INTERFACE.getRxBufSize = USART1_getRxBufSize;
USART1_INTERFACE.copyRxBuf = USART1_copyRxBuf;
USART1_INTERFACE.getRxBuf = USART1_getRxBuf;
USART1_INTERFACE.getTxBuf = USART1_getTxBuf;
USART1_INTERFACE.RxTransferRestart = USART1_RxTransferRestart;
USART1_IDIBUS.SetIdiBusBoudrate = USART1_SetIdiBusBoudrate;
USART1_IDIBUS.RxAlarmFrameStart = USART1_RxAlarmFrameStart;
USART1_IDIBUS.ResponseTimeoutComplete = 0;
USART1_IDIBUS.AlarmTimeoutUS = 0;
USART1_IDIBUS.ResponseTimeoutUS = 0;
USART1_IDIBUS.TimerMode = IDIBUS_TIMER_MODE_RX_TIMEOUT;
USART1_TX_DDR&=~(1<<USART1_TX_BIT); USART1_TX_PORT|=1<<USART1_TX_BIT; // TXD -> Z
USART1_RX_DDR&=~(1<<USART1_RX_BIT); USART1_RX_PORT|=1<<USART1_RX_BIT; // RXD -> Z
USART1_DRE_DDR&=~(1<<USART1_DRE_BIT); USART1_DRE_PORT&=~(1<<USART1_DRE_BIT); // RDE -> 0
*USART1STR.USART->UCRSA=(1<<U2X1);
*USART1STR.USART->UCRSB=(1<<RXCIE1)|(1<<RXEN1); // RX enable
*USART1STR.USART->UCRSC=(1<<UCSZ10)|(1<<UCSZ11)|(1<<USBS1); // 8 bit, 2 stop
TCCR3B=0; TCNT3=0; TIMSK3=0; // Timeout TIMER3 off
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_SetBaudrate(uint32_t Baudrate){
*USART1STR.USART->UBRR = (F_CPU/16UL)/Baudrate-1;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t USART1_IsNewRxMessage(void) { return USART1STR.RxComplete; }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t USART1_IsRxError(void) { return USART1STR.RxError; }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t USART1_getRxBufSize(void) { return USART1STR.RxBufCount; }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t *USART1_getRxBuf(void) { return &USART1STR.RX_BUF[0]; }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t *USART1_getTxBuf(void) { return &USART1STR.TX_BUF[0]; }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_copyRxBuf(uint8_t *Dst, uint16_t StartPos, uint16_t Count) { memcpy(Dst, &USART1STR.RX_BUF[StartPos], Count); }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t USART1_IsTxActive(void){
if (USART1STR.TxComplete) return 0;
else return 1;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_SetIdiBusBoudrate(enum IDIBUS_SERIAL_BAUDRATE BoudrateCode){
*USART1STR.USART->UBRR = pgm_read_word(&USART_UBRR[BoudrateCode]);
USART1STR.InterFrameTimeoutTicks = pgm_read_word(&USART_TIMEOUT[BoudrateCode]);
OCR3A = USART1STR.InterFrameTimeoutTicks;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_SendByteBuf(uint8_t *Buf, uint16_t Count){
if ( (!USART1STR.TxComplete) || (Count == 0) || (Count > USART1_BUF_SIZE) ) { return; }
memcpy(USART1STR.TX_BUF, Buf, Count);
USART1_TX_DDR|=1<<USART1_TX_BIT; USART1_TX_PORT|=1<<USART1_TX_BIT; // TXD -> out
USART1_DRE_DDR|=1<<USART1_DRE_BIT; USART1_DRE_PORT|=1<<USART1_DRE_BIT;
USART1STR.TxComplete = 0;
USART1STR.TxBufCount = Count;
USART1STR.TxSendedCount = 1;
*USART1STR.USART->UCRSB&=~((1<<RXCIE1)|(1<<RXEN1)); // RX off
*USART1STR.USART->UCRSB|=(1<<TXCIE1)|(1<<TXEN1);
*USART1STR.USART->UDR = USART1STR.TX_BUF[0];
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_SendTxBuf(uint16_t Count){
if ( (!USART1STR.TxComplete) || (Count == 0) || (Count > USART1_BUF_SIZE) ) { return; }
USART1_TX_DDR|=1<<USART1_TX_BIT; USART1_TX_PORT|=1<<USART1_TX_BIT; // TXD -> out
USART1_DRE_DDR|=1<<USART1_DRE_BIT; USART1_DRE_PORT|=1<<USART1_DRE_BIT;
USART1STR.TxComplete = 0;
USART1STR.TxBufCount = Count;
USART1STR.TxSendedCount = 1;
*USART1STR.USART->UCRSB&=~((1<<RXCIE1)|(1<<RXEN1)); // RX off
*USART1STR.USART->UCRSB|=(1<<TXCIE1)|(1<<TXEN1);
*USART1STR.USART->UDR = USART1STR.TX_BUF[0];
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_RxTransferRestart(void){
//USART1_RX_TIMER_STOP(); //We are already doing this in IRQ
//(void) USART1STR.USART->SR;
//(void) USART1STR.USART->DR;
*USART1STR.USART->UCRSB|=(1<<RXCIE1)|(1<<RXEN1);
USART1STR.RxBufCount = 0;
USART1STR.RxComplete = 0;
USART1STR.RxError = 0;
USART1_IDIBUS.TimerMode = IDIBUS_TIMER_MODE_RX_TIMEOUT;
//USART1_RX_TIMER_SET_TIMEOUT(USART1STR.InterFrameTimeoutUS);
//OCR3A = USART1STR.InterFrameTimeoutTicks; //Not necessary but why not
//USART1STR.USART->CR1 |= (1U<<USART_CR1_RE_Pos);
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void USART1_RxAlarmFrameStart(void){
//Sometimes there will be something
}