PropWare  3.0.0.229
C++ objects and CMake build system for Parallax Propeller
fdserial.c
Go to the documentation of this file.
1 
9 #include <stdlib.h>
10 #include "fdserial.h"
11 
12 /*
13  * start initializes and starts native assembly driver in a cog.
14  * @param rxpin is pin number for receive input
15  * @param txpin is pin number for transmit output
16  * @param mode is interface mode. see header FDSERIAL_MODE_...
17  * @param baudrate is frequency of bits ... 115200, 57600, etc...
18  * @returns non-zero on success
19  */
20 fdserial *fdserial_open(int rxpin, int txpin, int mode, int baudrate)
21 {
22  extern int binary_pst_dat_start[];
23 
24  fdserial_st *fdptr;
25 
26  /* can't use array instead of malloc because it would go out of scope. */
27  char* bufptr = (char*) malloc(2*(FDSERIAL_BUFF_MASK+1));
28  fdserial* term = (fdserial*) malloc(sizeof(fdserial));
29  memset(term, 0, sizeof(fdserial));
30 
31  fdptr = (void*) malloc(sizeof(fdserial_st));
32  term->devst = fdptr;
33  memset((char*)fdptr, 0, sizeof(fdserial_st));
34 
35  if(rxpin == 31 && txpin == 30) {
37  }
38 
39  /* required for terminal to work */
40  term->txChar = fdserial_txChar;
41  term->rxChar = fdserial_rxChar;
42  //if(mode & ECHO_RX_TO_TX) term->terminalEcho = 1;
43  //memcpy(&term->ec, "\0\0", 3);
44  //memcpy(&term->ecs, "\0\0", 3);
45  if((mode & ECHO_RX_TO_TX))
46  {
47  term->terminalEcho = 1;
48  }
49  else
50  {
51  term->terminalEcho = 0;
52  }
53  //
54  /*
55  memcpy(&text->ec, "\r\n", 3);
56  memcpy(&text->ecs, "\r\0", 3);
57  */
58  //
59  if(rxpin == 31 && txpin == 30)
60  {
61  //memcpy(&text->ec, "\r\n", 3);
62  //memcpy(&text->ecs, "\r\0", 3);
63  term->ecA = '\r';
64  term->ecB = '\n';
65  term->ecsA = '\r';
66  term->ecsB = 0;
67  }
68  else
69  {
70  //memcpy(&text->ec, "\0\0", 3);
71  //memcpy(&text->ecs, "\0\0", 3);
72  term->ecA = 0;
73  term->ecB = 0;
74  term->ecsA = 0;
75  term->ecsB = 0;
76  }
77 
78  fdptr->rx_pin = rxpin; /* recieve pin */
79  fdptr->tx_pin = txpin; /* transmit pin */
80  fdptr->mode = mode; /* interface mode */
81 
82  /* baud from clkfreq (cpu clock typically 80000000 for 5M*pll16x) */
83  fdptr->ticks = CLKFREQ/baudrate;
84 
85  fdptr->buffptr = bufptr; /* receive and transmit buffer */
86 
87  if((mode & FDSERIAL_MODE_RX_ONLY) || (txpin > 31) || (txpin < 0))
88  {
89  fdptr->tx_pin = fdptr->rx_pin;
90  fdptr->mode |= FDSERIAL_MODE_OPENDRAIN_TX;
91  //fdptr->mode &= (~FDSERIAL_MODE_RX_ONLY);
92  //fdptr->rxOnly = 1;
93  }
94  //else
95  //{
96  // fdptr->rxOnly = 0;
97  //}
98 
99  /* now start the kernel */
100 #if defined(__PROPELLER_USE_XMM__)
101  { unsigned int buffer[2048];
102  memcpy(buffer, binary_pst_dat_start, 2048);
103  term->cogid[0] = cognew(buffer, (void*)fdptr) + 1;
104  }
105 #else
106  term->cogid[0] = setStopCOGID(cognew((void*)binary_pst_dat_start, (void*)fdptr));
107 #endif
108  waitcnt(CLKFREQ/2+CNT); // give cog chance to load
109  return term;
110 }
111 
112 /*
113  * stop stops the cog running the native assembly driver
114  */
116 {
117  int id = term->cogid[0];
118  fdserial_st* fdp = (fdserial_st*) term->devst;
119 
120  while(fdserial_rxCheck(term) >= 0)
121  ; // clear out queue by receiving all available
122  fdserial_txFlush(term);
123 
124  if(id > 0) cogstop(getStopCOGID(id));
125 
126  free((void*)fdp->buffptr);
127  free((void*)fdp);
128  free(term);
129  term = 0;
130 }
131 
132 /*
133  * checks if anything is in the tx queue
134  */
136 {
137  volatile fdserial_st* fdp = (fdserial_st*) term->devst;
138  return fdp->tx_tail == fdp->tx_head;
139 }
140 
141 /*
142  * Gets a byte from the receive queue if available
143  * Function does not block. We move rxtail after getting char.
144  * @returns receive byte 0 to 0xff or -1 if none available
145  */
147 {
148  int rc = -1;
149  volatile fdserial_st* fdp = (fdserial_st*) term->devst;
150  volatile char* rxbuf = (volatile char*) fdp->buffptr; // rx buff starts at offset 0
151 
152  if(fdp->rx_tail != fdp->rx_head)
153  {
154  rc = rxbuf[fdp->rx_tail];
155  fdp->rx_tail = (fdp->rx_tail+1) & FDSERIAL_BUFF_MASK;
156  }
157  return rc;
158 }
159 
160 /*
161  * Wait for a byte from the receive queue. blocks until something is ready.
162  * @returns received byte
163  */
165 {
166  int rc = fdserial_rxCheck(term);
167  while(rc < 0)
168  rc = fdserial_rxCheck(term);
169  return rc;
170 }
171 
172 /*
173  * tx sends a byte on the transmit queue.
174  * @param txbyte is byte to send.
175  */
176 int fdserial_txChar(fdserial *term, int txbyte)
177 {
178  int rc = -1;
179  fdserial_st *fdptr = (fdserial_st *) term->devst;
180  //if(!fdptr->rxOnly)
181  if(!(fdptr->mode & FDSERIAL_MODE_RX_ONLY))
182  {
183  volatile fdserial_st* fdp = (fdserial_st*) term->devst;
184  volatile char* txbuf = (volatile char*) fdp->buffptr + FDSERIAL_BUFF_MASK+1;
185 
186  while(fdp->tx_tail == ((fdp->tx_head+1) & FDSERIAL_BUFF_MASK))
187  ; // wait for queue to be empty
188  txbuf[fdp->tx_head] = txbyte;
189  fdp->tx_head = (fdp->tx_head+1) & FDSERIAL_BUFF_MASK;
191  rc = fdserial_rxChar(term); // why not rxcheck or timeout ... this blocks for char
192  }
193  return rc;
194 }
195 
196 /*
197 +--------------------------------------------------------------------
198 | TERMS OF USE: MIT License
199 +--------------------------------------------------------------------
200 Permission is hereby granted, free of charge, to any person obtaining
201 a copy of this software and associated documentation files
202 (the "Software"), to deal in the Software without restriction,
203 including without limitation the rights to use, copy, modify, merge,
204 publish, distribute, sublicense, and/or sell copies of the Software,
205 and to permit persons to whom the Software is furnished to do so,
206 subject to the following conditions:
207 
208 The above copyright notice and this permission notice shall be
209 included in all copies or substantial portions of the Software.
210 
211 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
212 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
213 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
214 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
215 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
216 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
217 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
218 +--------------------------------------------------------------------
219 */
FDSERIAL_BUFF_MASK
#define FDSERIAL_BUFF_MASK
Definition: fdserial.h:56
FDSERIAL_MODE_IGNORE_TX_ECHO
#define FDSERIAL_MODE_IGNORE_TX_ECHO
Definition: fdserial.h:82
text_struct::rxChar
int(* rxChar)(struct text_struct *p)
Definition: simpletext.h:84
fdserial_struct::rx_head
int rx_head
Definition: fdserial.h:99
text_struct::cogid
int cogid[TERM_COG_LEN]
Definition: simpletext.h:88
FDSERIAL_MODE_OPENDRAIN_TX
#define FDSERIAL_MODE_OPENDRAIN_TX
Definition: fdserial.h:77
text_struct::txChar
int(* txChar)(struct text_struct *p, int ch)
Definition: simpletext.h:86
cognew
#define cognew(code, param)
Start a new Propeller PASM COG.
Definition: propeller.h:94
fdserial_struct::tx_tail
int tx_tail
Definition: fdserial.h:102
text_struct::devst
volatile void * devst
Definition: simpletext.h:90
fdserial_rxCheck
int fdserial_rxCheck(fdserial *term)
Gets a byte from the receive buffer if available, but does not wait if there's nothing in the buffer.
Definition: fdserial.c:146
fdserial_open
fdserial * fdserial_open(int rxpin, int txpin, int mode, int baudrate)
Open a full duplex serial connection.
Definition: fdserial.c:20
fdserial_struct::rx_tail
int rx_tail
Definition: fdserial.h:100
ECHO_RX_TO_TX
#define ECHO_RX_TO_TX
Definition: simpletext.h:64
fdserial_close
void fdserial_close(fdserial *term)
Stop stops the cog running the native assembly driver.
Definition: fdserial.c:115
simpleterm_close
void simpleterm_close(void)
Closes the SimpleIDE Terminal connection in one cog so that it can be opened in another cog with simp...
Definition: simpleterm_close.c:19
CLKFREQ
#define CLKFREQ
Returns the current clock frequency.
Definition: propeller.h:46
fdserial_struct
Defines fdserial interface structure of 9 contiguous longs + buffers.
Definition: fdserial.h:97
fdserial_txFlush
void fdserial_txFlush(fdserial *term)
Remove any bytes that might be waiting in the transmit buffer.
Definition: fdserial_utils.c:51
fdserial_struct::mode
int mode
Definition: fdserial.h:105
text_struct
Structure that contains data used by simple text device libraries.
Definition: simpletext.h:81
fdserial_txChar
int fdserial_txChar(fdserial *term, int txbyte)
Send a byte by adding it to the transmit buffer.
Definition: fdserial.c:176
waitcnt
#define waitcnt(a)
Wait until system counter reaches a value.
Definition: propeller.h:176
cogstop
#define cogstop(a)
Stop a COG.
Definition: propeller.h:100
CNT
#define CNT
The system clock count.
Definition: propeller1.h:151
text_struct::terminalEcho
volatile int terminalEcho
Definition: simpletext.h:92
FDSERIAL_MODE_RX_ONLY
#define FDSERIAL_MODE_RX_ONLY
Definition: fdserial.h:87
fdserial_txEmpty
int fdserial_txEmpty(fdserial *term)
Check if the transmit buffer is empty.
Definition: fdserial.c:135
fdserial_struct::buffptr
char * buffptr
Definition: fdserial.h:107
fdserial_rxChar
int fdserial_rxChar(fdserial *term)
Get a byte from the receive buffer, or if it's emtpy, wait until a byte is received.
Definition: fdserial.c:164
fdserial_struct::tx_head
int tx_head
Definition: fdserial.h:101
text_struct::ecA
volatile char ecA
Definition: simpletext.h:97
fdserial.h
This library supports creating and managing one or more full duplex serial connections with periphera...