PropWare  3.0.0.229
C++ objects and CMake build system for Parallax Propeller
serial.h
1 #ifndef LIBPROPELLER_SERIAL_H_
2 #define LIBPROPELLER_SERIAL_H_
3 
4 #include <cstdarg>
5 #include <propeller.h>
6 #include "libpropeller/numbers/numbers.h"
7 
8 #include "libpropeller/streaminterface/streaminterface.h"
9 
10 #include "libpropeller/printstream/printstream.h"
11 
12 extern char _load_start_serial_cog[];
13 
14 namespace libpropeller {
15 
35 class Serial : public InputStream<Serial>, public OutputStream<Serial>{
36 //class Serial : public StreamInterface{
37 //class Serial{
38 public:
39 
48  static const int kBufferLength = 512;
49 
50  ~Serial() {
51  Stop();
52  }
53 
64  bool Start(const int rxpin, const int txpin, const int rate, const int ctspin = -1) {
65 
66  // Prevent garbage collection of the ASM code
67  volatile void * asm_driver_reference = NULL;
68  __asm__ volatile ("mov %[asm_driver_reference], #Fds_entry \n\t"
69  : [asm_driver_reference] "+r" (asm_driver_reference));
70 
71  Stop();
72 
73  extern char * Masktx asm("Masktx");
74  extern char * Maskrx asm("Maskrx");
75  extern char * Ctra_val asm("Ctra_val");
76  extern char * Ctrb_val asm("Ctrb_val");
77  extern char * Period_ptr asm("Period_ptr");
78  extern char * Rx_head_ptr asm("Rx_head_ptr");
79  extern char * Rx_end_ptr asm("Rx_end_ptr");
80  extern char * Update_head_ptr asm("Update_head_ptr");
81  extern char * Maskcts asm("Maskcts");
82 
83 
84  SetDriverLong(&Masktx, 0);
85  SetDriverLong(&Ctra_val, 0);
86  if (txpin >= 0) {
87  DIRA |= 1 << txpin;
88  SetDriverLong(&Masktx, 1 << txpin);
89  SetDriverLong(&Ctra_val, 0x10000000 | txpin);
90  }
91  SetDriverLong(&Maskrx, 0);
92  SetDriverLong(&Ctrb_val, 0);
93  if (rxpin >= 0) {
94  DIRA &= ~(1 << rxpin);
95 
96  SetDriverLong(&Maskrx, 1 << rxpin);
97  SetDriverLong(&Ctrb_val, 0x54000000 | rxpin);
98  }
99 
100 
101  SetDriverLong(&Maskcts, 0);
102  if (ctspin >= 0) {
103  //Set CTS pin to input:
104  DIRA &= ~(1 << ctspin);
105 
106  SetDriverLong(&Maskcts, 1 << ctspin);
107  }
108 
109 
110  SetBaud(rate);
111 
112  SetDriverLong(&Period_ptr, (int) &half_bit_period_);
113  memset((void *) &rx_buffer_, 0, kBufferLength);
114 
115  SetDriverLong(&Rx_head_ptr, (int) &rx_buffer_);
116  SetDriverLong(&Rx_end_ptr, (int) &rx_buffer_ + kBufferLength);
117 
118  rx_head_ = 0;
119  rx_tail_ = 0;
120 
121  SetDriverLong(&Update_head_ptr, (int) &rx_head_);
122  write_buf_ptr_ = 1;
123  cog_ = 1 + cognew((int) (&(*(int *) &_load_start_serial_cog[0])), (int) (&write_buf_ptr_));
124  if (cog_) {
125  WaitForTransmissionCompletion();
126  return true;
127  }
128  return false;
129  }
130 
133  void Stop(void) {
134  WaitForTransmissionCompletion();
135  if (cog_) {
136  cogstop(cog_ - 1);
137  cog_ = 0;
138  }
139  }
140 
146  bool SetBaud(const int rate) {
147  return SetBaudClock(rate, CLKFREQ);
148  }
149 
161  bool SetBaudClock(const unsigned int rate, const unsigned int sysclock) {
162  WaitForTransmissionCompletion();
163 
164  // how many clocks per 1/2 bit (pre-round to the nearest integer)
165  int got_rate = ((sysclock >> 1) + (rate >> 1)) / rate;
166 
167  // clamp the period to the allowable range
168  half_bit_period_ = got_rate > kMinimumHalfPeriod ? got_rate : kMinimumHalfPeriod;
169 
170  // return true if the requested period was >= the allowable limit
171  return got_rate >= kMinimumHalfPeriod;
172  }
173 
178  void Put(const char character) {
179  WaitForTransmissionCompletion();
180  send_temp_ = character;
181  write_buf_ptr_ = (int) (&send_temp_);
182  }
183 
191  int Put(const char * buffer_ptr, const int count) {
192  WaitForTransmissionCompletion();
193  for (int i = 0; i < count; i++) {
194  Put(buffer_ptr[i]);
195  }
196  return count;
197  }
198 
206  int Put(const char * buffer_ptr) {
207  return Put(buffer_ptr, strlen(buffer_ptr));
208  }
209 
210 
211 
226  int Get(const int timeout = -1) {
227  int rxbyte = 0;
228 
229  if (timeout <= -1) { //No timeout, wait forever
230 
231  while ((rxbyte = CheckBuffer()) < 0);
232  return (char) rxbyte;
233  } else if (timeout == 0){
234  // Optimization: no wait if we just want a check.
235  return CheckBuffer();
236  } else {
237  unsigned int total_cycles = (CLKFREQ / 1000) * timeout;
238  unsigned int elapsed_cycles = 0;
239 
240  int previous_cnt = CNT;
241  do {
242  rxbyte = CheckBuffer();
243  int current_cnt = CNT;
244  elapsed_cycles += current_cnt - previous_cnt;
245  previous_cnt = current_cnt;
246  } while (rxbyte < 0 && elapsed_cycles < total_cycles);
247  return rxbyte;
248  }
249  }
250 
261  int Get(char * const buffer, const int length, const int timeout = -1) {
262  int character_count;
263  for (character_count = 0; character_count < length; ++character_count) {
264  int character = Get(timeout);
265  if (character <= -1) {
266  return character_count;
267  }
268  buffer[character_count] = (char) character;
269  }
270  return character_count;
271  }
272 
284  int Get(char * const buffer, const char terminator = '\n') {
285  int character_count;
286  char received_character = terminator + 1; // guarantee that they differ the first time.
287  for (character_count = 0; received_character != terminator; ++character_count) {
288  received_character = (char) Get();
289  buffer[character_count] = received_character;
290  }
291  buffer[character_count] = '\0';
292  return character_count;
293  }
294 
297  void GetFlush(void) {
298  rx_tail_ = rx_head_;
299  }
300 
303  int GetCount(void) const {
304  const int tail = rx_tail_;
305  const int head = rx_head_;
306  if (head >= tail) {
307  return head - tail;
308  } else {
309  return kBufferLength - tail + head;
310  }
311  }
312 
313  int PutFormatted(const char * formatString, ...){
314  PrintStream<Serial> ps(this);
315 
316  va_list list;
317  va_start(list, formatString);
318  int result = ps.Format(formatString, list);
319  va_end(list);
320  return result;
321  }
322 
323 
324 private:
329  static const int kMinimumHalfPeriod = 86;
330 
331  volatile int write_buf_ptr_;
332  volatile int send_temp_;
333  volatile int half_bit_period_;
334  volatile short rx_head_;
335  volatile short rx_tail_;
336  volatile char rx_buffer_[kBufferLength];
337  int cog_;
338 
342  int CheckBuffer(void) {
343  int rxbyte = -1;
344  if (rx_tail_ != rx_head_) {
345  rxbyte = rx_buffer_[rx_tail_];
346  rx_buffer_[rx_tail_] = 0;
347 
348  // Optimization:
349  // Was
350  // rx_tail_ = ((rx_tail_ + 1) % kBufferLength);
351  // But the modulo MAY be very slow. Edit: it's a bit faster...
352  rx_tail_++;
353  if (rx_tail_ == kBufferLength) {
354  rx_tail_ = 0;
355  }
356  }
357  return rxbyte;
358  }
359 
360  void WaitForTransmissionCompletion(void) {
361  while (write_buf_ptr_) {
362  };
363  }
364 
365  void SetDriverLong(const int index, const int value) {
366  ((int *) &_load_start_serial_cog[index])[0] = value;
367  }
368 
369  /* Warning: SetDriverLong(char **, int) must be declared second, otherwise it calls itself! */
370  void SetDriverLong(char ** index, const int value) {
371  SetDriverLong((int) index, value);
372  }
373 };
374 
375 //
376 // The Put(buffer) function doesn't seem to work in CMM mode. In the tests, I
377 // get a -1 for the matching Get(), instead of the character sent. The same code
378 // can pass in LMM mode.
379 
380 // Update: now, it doesn't work at all.
381 
382 //int Serial::PutBuffer(char * buffer_ptr, const bool wait, int buffer_bytes, const char terminator)
383 //{
384 // volatile char * volatile temp_ptr = buffer_ptr;
385 // if(buffer_bytes == -1){
386 // if(terminator == '\0'){
387 // buffer_bytes = strlen(buffer_ptr);
388 //
389 // }else{
390 // for(buffer_bytes = 0; buffer_ptr[buffer_bytes] != terminator; buffer_bytes++){}
391 // }
392 //
393 // }
394 
395 // buffer_bytes = 5;
396 
397 // if (buffer_bytes > 0 && buffer_ptr != NULL) {
398 //
399 // send_temp_ = (int)(buffer_ptr);
400 // write_buf_ptr_ = (send_temp_ | ((buffer_bytes - 1) << 16));
401 // }
402 //
403 // if(wait){
404 // while (write_buf_ptr_){}
405 // }
406 // return buffer_bytes;
407 //}
408 
409 }
410 
411 #endif // LIBPROPELLER_SERIAL_H_
libpropeller::Serial::Start
bool Start(const int rxpin, const int txpin, const int rate, const int ctspin=-1)
Definition: serial.h:64
libpropeller::Serial::kBufferLength
static const int kBufferLength
Definition: serial.h:48
libpropeller::Serial::Get
int Get(const int timeout=-1)
Definition: serial.h:226
cognew
#define cognew(code, param)
Start a new Propeller PASM COG.
Definition: propeller.h:94
libpropeller::Serial::GetCount
int GetCount(void) const
Definition: serial.h:303
libpropeller::Serial::Put
int Put(const char *buffer_ptr, const int count)
Definition: serial.h:191
libpropeller::Serial
Definition: serial.h:35
libpropeller::InputStream
Definition: streaminterface.h:7
timeout
int timeout(int time)
Compares the time against the time elapsed since mark (deprecated).
Definition: timeout.c:19
libpropeller::Serial::SetBaud
bool SetBaud(const int rate)
Definition: serial.h:146
CLKFREQ
#define CLKFREQ
Returns the current clock frequency.
Definition: propeller.h:46
libpropeller::Serial::Get
int Get(char *const buffer, const int length, const int timeout=-1)
Definition: serial.h:261
count
long count(int pin, long duration)
Count number of low to high transitions an external input applies to an I/O pin over a certain period...
Definition: count.c:19
libpropeller::Serial::Put
int Put(const char *buffer_ptr)
Definition: serial.h:206
libpropeller::Serial::Stop
void Stop(void)
Definition: serial.h:133
libpropeller::Serial::Get
int Get(char *const buffer, const char terminator='\n')
Definition: serial.h:284
libpropeller::OutputStream
Definition: streaminterface.h:24
libpropeller::Serial::GetFlush
void GetFlush(void)
Definition: serial.h:297
cogstop
#define cogstop(a)
Stop a COG.
Definition: propeller.h:100
CNT
#define CNT
The system clock count.
Definition: propeller1.h:151
char
libpropeller
Definition: board_unit_tester.h:4
libpropeller::Serial::SetBaudClock
bool SetBaudClock(const unsigned int rate, const unsigned int sysclock)
Definition: serial.h:161
libpropeller::PrintStream
Definition: printstream.h:12
DIRA
#define DIRA
Use to set pins to input (0) or output (1).
Definition: propeller1.h:161
libpropeller::Serial::Put
void Put(const char character)
Definition: serial.h:178