OpenCores
URL https://opencores.org/ocsvn/neo430/neo430/trunk

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [sw/] [lib/] [neo430/] [source/] [neo430_uart.c] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
// #################################################################################################
2
// #  < neo430_usart.c - Internal UARt driver functions >                                          #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6
// # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
7
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
33
// #################################################################################################
34
 
35
#include "neo430.h"
36
#include "neo430_uart.h"
37
 
38
 
39
/* ------------------------------------------------------------
40
 * INFO Reset UART, set the Baud rate of UART transceiver
41
 * INFO UART_BAUD reg (8 bit) = f_main/(prsc*desired_BAUDRATE)
42
 * INFO PRSC (Baud register bits 10..8):
43
 *  0: CLK/2
44
 *  1: CLK/4
45
 *  2: CLK/8
46
 *  3: CLK/64
47
 *  4: CLK/128
48
 *  5: CLK/1024
49
 *  6: CLK/2048
50
 *  7: CLK/4096
51
 * PARAM actual baudrate to be used
52
 * ------------------------------------------------------------ */
53
void neo430_uart_setup(uint32_t baudrate){
54
 
55
  // raw baud rate prescaler
56
  uint32_t clock = CLOCKSPEED_32bit;
57
  uint16_t i = 0; // BAUD rate divisor
58
  uint8_t p = 0; // prsc = CLK/2
59
  while (clock >= 2*baudrate) {
60
    clock -= 2*baudrate;
61
    i++;
62
  }
63
 
64
  // find clock prsc
65
  while (i >= 256) {
66
    if ((p == 2) || (p == 4))
67
      i >>= 3;
68
    else
69
      i >>= 1;
70
    p++;
71
  }
72
 
73
  UART_CT = 0;
74
  UART_CT = (1<<UART_CT_EN) | ((uint16_t)p << UART_CT_PRSC0) | (i << UART_CT_BAUD0);
75
}
76
 
77
 
78
/* ------------------------------------------------------------
79
 * INFO Disable UART
80
 * ------------------------------------------------------------ */
81
void neo430_uart_disable(void){
82
 
83
  UART_CT = 0;
84
}
85
 
86
 
87
/* ------------------------------------------------------------
88
 * INFO Get current UARt baud rate
89
 * ------------------------------------------------------------ */
90
uint32_t neo430_uart_get_baudrate(void) {
91
 
92
  // Clock speed
93
  uint32_t clock = CLOCKSPEED_32bit;
94
 
95
  // prescaler
96
  uint16_t prsc;
97
  switch ((UART_CT >> 8) & 0x0007) {
98
    case 0:  prsc = 2; break;
99
    case 1:  prsc = 4; break;
100
    case 2:  prsc = 8; break;
101
    case 3:  prsc = 64; break;
102
    case 4:  prsc = 128; break;
103
    case 5:  prsc = 1024; break;
104
    case 6:  prsc = 2048; break;
105
    case 7:  prsc = 4096; break;
106
    default: prsc = 0; break;
107
  }
108
 
109
  uint16_t baud = UART_CT & 0x00FF;
110
  uint32_t baud_value = clock / (uint32_t)(prsc * baud);
111
 
112
  return baud_value;
113
}
114
 
115
 
116
/* ------------------------------------------------------------
117
 * INFO Send single char via internal UART
118
 * PARAM c char to send
119
 * ------------------------------------------------------------ */
120
void neo430_uart_putc(char c){
121
 
122
  // wait for previous transfer to finish
123
  while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
124
  UART_RTX = (uint16_t)c;
125
}
126
 
127
 
128
/* ------------------------------------------------------------
129
 * INFO Read single char from internal UART (wait until data available)
130
 * INFO This function is blocking!
131
 * RETURN received char
132
 * ------------------------------------------------------------ */
133
char neo430_uart_getc(void){
134
 
135
  uint16_t d = 0;
136
  while (1) {
137
    d = UART_RTX;
138
    if ((d & (1<<UART_RTX_AVAIL)) != 0) { // char received?
139
      return (char)d;
140
    }
141
  }
142
}
143
 
144
 
145
/* ------------------------------------------------------------
146
 * INFO Returns value !=0 if a char has received
147
 * RETURN 0 if no char available
148
 * ------------------------------------------------------------ */
149
uint16_t neo430_uart_char_received(void){
150
 
151
  return UART_RTX & (1<<UART_RTX_AVAIL);
152
}
153
 
154
 
155
/* ------------------------------------------------------------
156
 * INFO Returns char from UART RX unit
157
 * INFO Check if char present with <uart_char_received>
158
 * INFO This is the base for a non-blocking read access
159
 * RETURN received char
160
 * ------------------------------------------------------------ */
161
char neo430_uart_char_read(void){
162
 
163
  return (char)UART_RTX;
164
}
165
 
166
 
167
/* ------------------------------------------------------------
168
 * INFO Print zero-terminated string of chars via internal UART
169
 * PARAM *s pointer to source string
170
 * ------------------------------------------------------------ */
171
void neo430_uart_print(char *s){
172
 
173
  char c = 0;
174
  while ((c = *s++)) {
175
    neo430_uart_putc(c);
176
  }
177
}
178
 
179
 
180
/* ------------------------------------------------------------
181
 * INFO Print zero-terminated string of chars via internal UART
182
 * Prints true line break "\r\n" for every '\n'
183
 * PARAM *s pointer to source string
184
 * ------------------------------------------------------------ */
185
void neo430_uart_br_print(char *s){
186
 
187
  char c = 0;
188
  while ((c = *s++)) {
189
    if (c == '\n') {
190
      neo430_uart_putc('\r');
191
    }
192
    neo430_uart_putc(c);
193
  }
194
}
195
 
196
 
197
/* ------------------------------------------------------------
198
 * INFO Get string via UART, string is automatically zero-terminated.
199
 * Input is acknowledged by ENTER, local echo, chars can be deleted using BACKSPACE.
200
 * PARAM buffer to store string to
201
 * PARAM size of buffer (=max string length incl. zero-termination)
202
 * PARAM activate local echo when =! 0
203
 * RETURN Length of string (without zero-termination character)
204
 * ------------------------------------------------------------ */
205
uint16_t neo430_uart_scan(char *buffer, uint16_t max_size, uint16_t echo) {
206
 
207
  char c = 0;
208
  uint16_t length = 0;
209
 
210
  while (1) {
211
    c = neo430_uart_getc();
212
    if (c == '\b') { // BACKSPACE
213
      if (length != 0) {
214
        if (echo) {
215
          neo430_uart_print("\b \b"); // delete last char in console
216
        }
217
        buffer--;
218
        length--;
219
      }
220
    }
221
    else if (c == '\r') // carriage return
222
      break;
223
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
224
      if (echo) {
225
        neo430_uart_putc(c); // echo
226
      }
227
      *buffer++ = c;
228
      length++;
229
    }
230
  }
231
  *buffer = '\0'; // terminate string
232
 
233
  return length;
234
}
235
 
236
 
237
/* ------------------------------------------------------------
238
 * INFO Print single (capital) hexadecimal value (1 digit)
239
 * PARAM char to be printed
240
 * ------------------------------------------------------------ */
241
void neo430_uart_print_hex_char(char c) {
242
 
243
  char d = c & 15;
244
  if (d < 10)
245
    d += '0';
246
  else
247
    d += 'a'-10;
248
  neo430_uart_putc(d);
249
}
250
 
251
 
252
/* ------------------------------------------------------------
253
 * INFO Print 8-bit hexadecimal value (2 digits)
254
 * PARAM uint8_t value to be printed
255
 * ------------------------------------------------------------ */
256
void neo430_uart_print_hex_byte(uint8_t b) {
257
 
258
  neo430_uart_print_hex_char((char)(b >> 4));
259
  neo430_uart_print_hex_char((char)(b >> 0));
260
}
261
 
262
 
263
/* ------------------------------------------------------------
264
 * INFO Print 16-bit hexadecimal value (4 digits)
265
 * PARAM uint16_t value to be printed
266
 * ------------------------------------------------------------ */
267
void neo430_uart_print_hex_word(uint16_t w) {
268
 
269
  union uint16_u tmp;
270
  tmp.uint16 = w;
271
 
272
  neo430_uart_print_hex_byte(tmp.uint8[1]);
273
  neo430_uart_print_hex_byte(tmp.uint8[0]);
274
}
275
 
276
 
277
/* ------------------------------------------------------------
278
 * INFO Print 32-bit hexadecimal value (8 digits)
279
 * PARAM uint32_t value to be printed
280
 * ------------------------------------------------------------ */
281
void neo430_uart_print_hex_dword(uint32_t dw) {
282
 
283
  union uint32_u tmp;
284
  tmp.uint32 = dw;
285
 
286
  neo430_uart_print_hex_byte(tmp.uint8[3]);
287
  neo430_uart_print_hex_byte(tmp.uint8[2]);
288
  neo430_uart_print_hex_byte(tmp.uint8[1]);
289
  neo430_uart_print_hex_byte(tmp.uint8[0]);
290
}
291
 
292
 
293
/* ------------------------------------------------------------
294
 * INFO Print 64-bit hexadecimal value (16 digits)
295
 * PARAM uint64_t value to be printed
296
 * ------------------------------------------------------------ */
297
void neo430_uart_print_hex_qword(uint64_t qw) {
298
 
299
  union uint64_u tmp;
300
  tmp.uint64 = qw;
301
 
302
  neo430_uart_print_hex_byte(tmp.uint8[7]);
303
  neo430_uart_print_hex_byte(tmp.uint8[6]);
304
  neo430_uart_print_hex_byte(tmp.uint8[5]);
305
  neo430_uart_print_hex_byte(tmp.uint8[4]);
306
  neo430_uart_print_hex_byte(tmp.uint8[3]);
307
  neo430_uart_print_hex_byte(tmp.uint8[2]);
308
  neo430_uart_print_hex_byte(tmp.uint8[1]);
309
  neo430_uart_print_hex_byte(tmp.uint8[0]);
310
}
311
 
312
 
313
/* ------------------------------------------------------------
314
 * INFO Print 8-bit binary value (8 digits)
315
 * PARAM uint8_t value to be printed
316
 * ------------------------------------------------------------ */
317
void neo430_uart_print_bin_byte(uint8_t b) {
318
 
319
  uint8_t i;
320
  for (i=0x80; i!=0; i>>=1) {
321
    if (b & i)
322
      neo430_uart_putc('1');
323
    else
324
      neo430_uart_putc('0');
325
  }
326
}
327
 
328
 
329
/* ------------------------------------------------------------
330
 * INFO Print 16-bit binary value (16 digits)
331
 * PARAM uint16_t value to be printed
332
 * ------------------------------------------------------------ */
333
void neo430_uart_print_bin_word(uint16_t w) {
334
 
335
  union uint16_u tmp;
336
  tmp.uint16 = w;
337
 
338
  neo430_uart_print_bin_byte(tmp.uint8[1]);
339
  neo430_uart_print_bin_byte(tmp.uint8[0]);
340
}
341
 
342
 
343
/* ------------------------------------------------------------
344
 * INFO Print 32-bit binary value (32 digits)
345
 * PARAM uint32_t value to be printed
346
 * ------------------------------------------------------------ */
347
void neo430_uart_print_bin_dword(uint32_t dw) {
348
 
349
  union uint32_u tmp;
350
  tmp.uint32 = dw;
351
 
352
  neo430_uart_print_bin_byte(tmp.uint8[3]);
353
  neo430_uart_print_bin_byte(tmp.uint8[2]);
354
  neo430_uart_print_bin_byte(tmp.uint8[1]);
355
  neo430_uart_print_bin_byte(tmp.uint8[0]);
356
}
357
 
358
 
359
/* ------------------------------------------------------------
360
 * INFO Print 32-bit number as decimal number (10 digits)
361
 * INFO Slow custom version of itoa
362
 * PARAM 32-bit value to be printed as decimal number
363
 * PARAM show #leading_zeros leading zeros
364
 * PARAM pointer to array (11 elements!!!) to store conversion result string
365
 * ------------------------------------------------------------ */
366
void neo430_itoa(uint32_t x, uint16_t leading_zeros, char *res) {
367
 
368
  const char numbers[10] = "0123456789";
369
  char buffer1[11];
370
  uint16_t i, j;
371
 
372
  buffer1[10] = '\0';
373
  res[10] = '\0';
374
 
375
  // convert
376
  for (i=0; i<10; i++) {
377
    buffer1[i] = numbers[x%10];
378
    x /= 10;
379
  }
380
 
381
  // delete 'leading' zeros
382
  for (i=9; i!=leading_zeros; i--) {
383
    if (buffer1[i] == '0')
384
      buffer1[i] = '\0';
385
    else
386
      break;
387
  }
388
 
389
  // reverse
390
  j = 0;
391
  do {
392
    if (buffer1[i] != '\0')
393
      res[j++] = buffer1[i];
394
  } while (i--);
395
 
396
  res[j] = '\0'; // terminate result string
397
}
398
 
399
 
400
/* ------------------------------------------------------------
401
 * INFO Embedded version of the printf function with reduced functionality
402
 * INFO Only use this function if it is really required!
403
 * INFO It is large and slow... ;)
404
 * INFO Original from http://forum.43oh.com/topic/1289-tiny-printf-c-version/
405
 * PARAM Argument string
406
 * ------------------------------------------------------------ */
407
void neo430_printf(char *format, ...) {
408
 
409
  char c, string_buf[11];
410
  int32_t n;
411
 
412
  va_list a;
413
  va_start(a, format);
414
 
415
  while ((c = *format++)) {
416
    if (c == '%') {
417
      c = *format++;
418
      switch (c) {
419
        case 's': // string
420
          neo430_uart_print(va_arg(a, char*));
421
          break;
422
        case 'c': // char
423
          neo430_uart_putc((char)va_arg(a, int));
424
          break;
425
        case 'b': // unsigned 16-bit binary
426
          neo430_uart_print_bin_word(va_arg(a, unsigned int));
427
          break;
428
        case 'i': // 16-bit integer
429
          n = (int32_t)va_arg(a, int);
430
          if (n < 0) {
431
            n = -n;
432
            neo430_uart_putc('-');
433
          }
434
          neo430_itoa((uint32_t)n, 0, string_buf);
435
          neo430_uart_br_print(string_buf);
436
          break;
437
        case 'u': // 16-bit unsigned
438
          neo430_itoa((uint32_t)va_arg(a, unsigned int), 0, string_buf);
439
          neo430_uart_br_print(string_buf);
440
          break;
441
        case 'l': // 32-bit signed long
442
          n = (int32_t)va_arg(a, int32_t);
443
          if (n < 0) {
444
            n = -n;
445
            neo430_uart_putc('-');
446
          }
447
          neo430_itoa((uint32_t)n, 0, string_buf);
448
          neo430_uart_br_print(string_buf);
449
          break;
450
        case 'n': // 32-bit unsigned long
451
          neo430_itoa(va_arg(a, uint32_t), 0, string_buf);
452
          neo430_uart_br_print(string_buf);
453
          break;
454
        case 'x': // 16-bit hexadecimal
455
          neo430_uart_print_hex_word(va_arg(a, unsigned int));
456
          break;
457
        case 'X': // 32-bit hexadecimal
458
          neo430_uart_print_hex_dword(va_arg(a, uint32_t));
459
          break;
460
        default:
461
          return;
462
      }
463
    }
464
    else {
465
      if (c == '\n')
466
        neo430_uart_putc('\r');
467
      neo430_uart_putc(c);
468
    }
469
  }
470
  va_end(a);
471
}
472
 
473
 
474
/* ------------------------------------------------------------
475
 * INFO Convert N hex chars into uint32
476
 * PARAM Pointer to buffer with hex chars
477
 * PARAM Number of hex chars to convert (1..8)
478
 * RETURN Conversion result
479
 * ------------------------------------------------------------ */
480
uint32_t neo430_hexstr_to_uint(char *buffer, uint8_t length) {
481
 
482
  uint32_t res = 0, d = 0;
483
  char c = 0;
484
 
485
  while (length--) {
486
    c = *buffer++;
487
 
488
    if ((c >= '0') && (c <= '9'))
489
      d = (uint32_t)(c - '0');
490
    else if ((c >= 'a') && (c <= 'f'))
491
      d = (uint32_t)((c - 'a') + 10);
492
    else if ((c >= 'A') && (c <= 'F'))
493
      d = (uint32_t)((c - 'A') + 10);
494
    else
495
      d = 0;
496
 
497
    res = res + (d << (length*4));
498
  }
499
 
500
  return res;
501
}
502
 
503
 
504
/* ------------------------------------------------------------
505
 * INFO Return terminal cursor n positions
506
 * PARAM n positions
507
 * ------------------------------------------------------------ */
508
void neo430_uart_bs(uint16_t n) {
509
 
510
  while (n--) {
511
    neo430_uart_putc(0x08);
512
  }
513
}
514
 
515
 
516
/* ------------------------------------------------------------
517
 * INFO Print signed 32-bit fixed point number (num)
518
 * PARAM fpf_c: Number of bin fractional bits in input (max 32)
519
 * PARAM num_frac_digits_c: Number of fractional digits to show (max 8)
520
 * ------------------------------------------------------------ */
521
void neo430_uart_print_fpf_32(int32_t num, uint16_t fpf_c, uint16_t num_frac_digits_c) {
522
 
523
  uint16_t i;
524
 
525
  // make positive
526
  if (num < 0) {
527
    neo430_uart_putc('-');
528
    num = -num;
529
  }
530
  uint32_t num_int = (uint32_t)num;
531
 
532
 
533
  // print integer part
534
  char int_buf[11];
535
  neo430_itoa((uint32_t)(num_int >> fpf_c), 0, int_buf);
536
  neo430_uart_br_print(int_buf);
537
  neo430_uart_putc('.');
538
 
539
 
540
  // compute fractional resolution
541
  uint32_t frac_dec_base = 1;
542
  for (i=0; i<num_frac_digits_c; i++) {
543
    frac_dec_base = frac_dec_base * 10;
544
  }
545
  frac_dec_base = frac_dec_base >> 1;
546
 
547
  // compute fractional part's bit-insulation shift mask
548
  uint32_t frac_dec_mask = 1L << (fpf_c-1);
549
 
550
 
551
  // compute actual fractional part
552
  uint32_t frac_data = num_int & ((1 << fpf_c)-1); // only keep fractional bits
553
  uint32_t frac_sum = 1;
554
  for (i=0; i<fpf_c; i++) { // test each fractional bit
555
    if (frac_data & frac_dec_mask) { // insulate current fractional bit
556
      frac_sum += frac_dec_base;
557
    }
558
    frac_dec_mask >>= 1; // go from MSB to LSB
559
    frac_dec_base >>= 1;
560
  }
561
 
562
  // print fractional part
563
  char frac_buf[11];
564
  neo430_itoa((uint32_t)frac_sum, num_frac_digits_c-1, frac_buf);
565
  frac_buf[num_frac_digits_c] = '\0'; // truncate
566
  neo430_uart_br_print(frac_buf);
567
}
568
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.