/* * rsbus.c * * Created on: 2014-4-26 * Author: Tuowen */ #include "rsbus.h" #include "sysctl.h" #define SYSRET (0xF0) #define INSREP (0x0F) // Maximum size of receive buffer #define RSMAX (20) #define CODE_LEN (6) unsigned char rs_rxbuf[RSMAX]; unsigned char len; unsigned char pch; rshdlr rxhdlr; enum rs_stat{REST,ST,ADDR,READ,DISCARD,ED,DED}; enum rs_stat rs_st=REST; unsigned char rs_tx[CODE_LEN+RS_MAX]={STBIT1,0,RSADDR,MACTYPE}; volatile unsigned char tx_len; volatile unsigned char tx_pos=255; volatile unsigned char mac_stat[4]={0,0,0,0}; // UART transmit routine #pragma vector=USCIAB0TX_VECTOR __interrupt void USCI0TX_ISR(void) { if (tx_pos == tx_len) // TX over? { UC0IE &= ~UCA0TXIE; // Disable USCI_A0 TX interrupt RSOUT &= ~(RSPIN); tx_pos = 255; } else UCA0TXBUF = rs_tx[tx_pos++]; // TX next character } // Inline send for ISR #pragma FUNC_ALWAYS_INLINE(rsbus_w_irq) static __inline void rsbus_w_irq(unsigned char* buf,unsigned int len) { unsigned int i; if (tx_pos < tx_len) // This shouldn't happen return; // Race condition RSOUT |= RSPIN; tx_len=len+7; unsigned int parity=MACTYPE^RSADDR; rs_tx[1]=0; // Useless addr spec for (i=0;i=RSMAX) rs_st=REST; break; case DISCARD: if (dat==EDBIT0) rs_st=DED; break; case DED: if (dat==EDBIT1) rs_st=REST; else rs_st=DISCARD; break; case ED: if (dat==EDBIT1) { rs_st=REST; --len; pch^=EDBIT0; if (pch==0) // Parity check passed { if (len<2) rsbus_w_irq((unsigned char*)mac_stat,4); // RETURN CURRENT STATUS else SYSCALL_IRQ(RSSYSBIT); // SYSCTL call happened here!!! } else // Parity check failed { dat = SYSRET ^ INSREP; // RETURN REP rsbus_w_irq(&dat,1); } } else { rs_rxbuf[len++]=dat; pch^=dat; rs_st=READ; if (len>=RSMAX) rs_st=REST; } break; } } void rsbus_w(int addr,unsigned char* buf,unsigned int len) { while (tx_pos < tx_len) // This shouldn't happen __delay_cycles(100); // Race condition -> wait unsigned int i; if (len>RS_MAX) return; RSOUT |= RSPIN; tx_len=len+7; unsigned int parity=addr^MACTYPE^RSADDR; rs_tx[1]=addr; // Useless addr spec for (i=0;i Low as DEFAULT /******************* SYSCTL INIT *************************/ rxhdlr=hdlr; sysctl_reghdlr(RSSYSBIT,&rsbus_syscall); }