1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
/*
* rsbus.c
*
* Created on: 2014-4-26
* Author: Tuowen
*/
#include "rsbus.h"
#include "sysctl.h"
#define SYSRET (0xF0)
#define INSREP (0x0F)
unsigned char rs_rxbuf[RSMAX];
unsigned char len;
unsigned char pch;
unsigned char ret;
rshdlr rxhdlr;
enum rs_stat{REST,ST,ADDR,READ,DISCARD,ED,DED};
enum rs_stat rs_st=REST;
unsigned char rs_tx[15]={STBIT1,0,RSADDR,MACTYPE};
unsigned char tx_len;
unsigned char tx_pos;
#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);
}
else
UCA0TXBUF = rs_tx[tx_pos++]; // TX next character
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void rsbus_rx(void)
{
//IFG2&=(~UCA0RXIFG);
int dat;
dat=UCA0RXBUF;
/************ Simple State Machine *************/
switch (rs_st)
{
case REST:
rs_st=(dat==STBIT0)?ST:REST;
break;
case ST:
rs_st=(dat==STBIT1)?ADDR:REST;
break;
case ADDR:
if (dat==RSADDR)
{
rs_st=READ;
len=0;
pch=RSADDR;
}
else
rs_st=DISCARD;
break;
case READ:
rs_rxbuf[len++]=dat;
pch^=dat;
if (dat==EDBIT0)
rs_st=ED;
if (len>=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)
{
ret=(SYSRET ^ MACTYPE);
SYSCALL_IRQ(RSSYSRET); // TODO RETURN CURRENT STATUS
}
else
SYSCALL_IRQ(RSSYSBIT); // SYSCTL call happened here!!!
}
else
{
ret=(SYSRET ^ INSREP);
SYSCALL_IRQ(RSSYSRET); // RETURN machine type
}
}
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)
{
unsigned int i;
if (len>4)
return;
RSOUT |= RSPIN;
tx_len=len+7;
unsigned int parity=addr^MACTYPE^RSADDR;
rs_tx[1]=addr;
for (i=0;i<len;++i)
parity^=(rs_tx[4+i]=buf[i]);
rs_tx[4+len]=parity;
rs_tx[5+len]=EDBIT0;
rs_tx[6+len]=EDBIT1;
tx_pos=0;
UCA0TXBUF=(STBIT0 & 0xff);
UC0IE |= UCA0TXIE;
}
void rsbus_syscall()
{
rxhdlr(rs_rxbuf,len-1);
}
void rsbus_ret()
{
rsbus_w(0,(unsigned char*)&ret,1);
}
void rsbus_init(rshdlr hdlr) // If need to change this part consult user guide pg908
{
P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSSEL_2; // UartCLK: SMCLK=4MHz
UCA0BR0 = 208; // BaudRate: 19200
UCA0BR1 = 0; // BaudRate: 19200
UCA0MCTL = UCBRS0 + UCBRS1; // Modulation UCBRSx = 3
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
/******************* CTL for output buffer ***********************/
RSDIR |= RSPIN;
RSOUT &= ~(RSPIN); //HIGH for ENABLE -> Low as DEFAULT
/******************* SYSCTL INIT *************************/
rxhdlr=hdlr;
sysctl_reghdlr(RSSYSBIT,&rsbus_syscall);
sysctl_reghdlr(RSSYSRET,&rsbus_ret);
}
|