BBS_BBB_Ada_cfbd52e3/src-due/bbs-embed-due-serial.ads

  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
--
--  Author: Brent Seidel
--  Date: 9-Aug-2024
--
--  This file is part of bbs_embed.
--  Bbs_embed is free software: you can redistribute it and/or modify it
--  under the terms of the GNU General Public License as published by the
--  Free Software Foundation, either version 3 of the License, or (at your
--  option) any later version.
--
--  bbs_embed is distributed in the hope that it will be useful, but
--  WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
--  Public License for more details.
--
--  You should have received a copy of the GNU General Public License along
--  with bbs_embed. If not, see <https://www.gnu.org/licenses/>.--
--
with SAM3x8e.UART;
with SAM3x8e;
use type SAM3x8e.Bit;
use type SAM3x8e.Byte;
use type SAM3x8e.UInt32;
with BBS.embed.due.dev;
with BBS.embed.GPIO.Due;
with Ada.Interrupts;
with Ada.Interrupts.Names;
--
--  This package is the root of the serial I/O functionality on the Arduino
--  Due.  It has four of its serial ports wired to the headers.  These ports
--  are numbered 0 through 3.  Port 0 is also wired to the programming USB
--  connector and is used as the default port, if none is specified.
--
--  Communications is available in both polled and interrupt driven varients.
--  Polled is unbuffered and has very little memory overhead, but puts more
--  load on the CPU.  It is most useful when memory is tight or serial I/O
--  needs are minimal.  It would also be useful as a method of last resort
--  for printing messages from an exception handler.
--
--  Interrupt driven copies messages into a buffer and uses an interrupt
--  handler to feed characters into the UART as needed.  The main thread of
--  software can continue processing while this is happening.  This provides
--  more processing for user software at the expense of requiring memory for
--  the buffers.
--
--  This package contains definitions and code that is common to both methods.
--  The interrupt or polled specific definitions and code are in the
--  appropriate sub-package.
--
package BBS.embed.due.serial is

   --
   --  The Arduino has four serial ports wired to the headers.
   --
   type port_id is new Integer range 0 .. 3;
   --
   --  The programming USB port is connected to pins PA08 and PA09 - URXD and
   --  UTXD.  These are controlled by the UART.  Include code here to
   --  initialize the UART and set the baud rate.
   --
   procedure init(baud_rate : SAM3x8e.UInt32);
   procedure init(chan_num : port_id; baud_rate : SAM3x8e.UInt32);
   --
   --  Check if the transmitter is ready
   --
   function tx_ready return Boolean;
   function tx_ready(chan : port_id) return Boolean;
   --
   --  Check if the receiver is ready
   --
   function rx_ready return Boolean;
   function rx_ready(chan : port_id) return Boolean;
   --
   --  Check if the transmitter is empty.
   --
   function tx_empty return Boolean;
   function tx_empty(chan : port_id) return Boolean;

private
   --
   --  Constants for some special characters.
   --
   BS : constant Character := Character'Val(8);
   LF : constant Character := Character'Val(10);
   CR : constant Character := Character'Val(13);
   DEL : constant Character := Character'Val(127);

   Serial : aliased SAM3x8e.UART.UART_Peripheral
     with Import, Address => SAM3x8e.UART_Base;
   --
   --  The USARTs seem to be a superset of the UART, so the following works,
   --  but leaves the more advanced features of the USARTs unavailable.
   --
   Serial0 : aliased SAM3x8e.UART.UART_Peripheral
     with Import, Address => SAM3x8e.USART0_Base;

   --  Universal Synchronous Asynchronous Receiver Transmitter 1
   Serial1 : aliased SAM3x8e.UART.UART_Peripheral
     with Import, Address => SAM3x8e.USART1_Base;

   --  Universal Synchronous Asynchronous Receiver Transmitter 2
   --  This does not seem to be available on the Arduino Due pin headers.
   Serial2 : aliased SAM3x8e.UART.UART_Peripheral
     with Import, Address => SAM3x8e.USART2_Base;

   --  Universal Synchronous Asynchronous Receiver Transmitter 3
   Serial3 : aliased SAM3x8e.UART.UART_Peripheral
     with Import, Address => SAM3x8e.USART3_Base;
   --
   --  Create a serial channel information record.  This should contain all
   --  the information necessary to identify a serial port and the pins used
   --  by it.
   --
   type serial_access is access all SAM3x8e.UART.UART_Peripheral;
   type channel_info_rec is tagged limited record
      dev_id   : SAM3x8e.Byte;    --  UART device ID
      port     : serial_access;   --  Access to UART registers
      pioc     : BBS.embed.GPIO.Due.pio_access;  --  PIO controlling pins
      tx_pin   : SAM3x8e.Byte;    --  Transmit pin on PIO
      rx_pin   : SAM3x8e.Byte;    --  Receive pin on PIO
      tx_absel : SAM3x8e.Bit;     --  A/B selection on PIO for transmit
      rx_absel : SAM3x8e.Bit;     --  A/B selection on PIO for receive
      int_id   : Ada.Interrupts.Interrupt_ID; -- Interrupt for channel
   end record;
   type serial_obj is access constant channel_info_rec;
   --
   -- May need a serial channel for the USB port - TODO
   --

   --
   --  The Arduino Due has four serial channels wired to the headers.
   --  0 - UART
   --  1 - USART0
   --  2 - USART1
   --  3 - USART3
   --
   chan0 : aliased constant channel_info_rec := (dev_id => dev.UART_ID, port => Serial'Access,
                                         pioc => BBS.embed.GPIO.Due.PIOA'Access, tx_pin => 9,
                                         rx_pin => 8, tx_absel => 0, rx_absel => 0,
                                         int_id => Ada.Interrupts.Names.UART_Interrupt);
   chan1 : aliased constant channel_info_rec := (dev_id => dev.USART0_ID, port => Serial0'Access,
                                         pioc => BBS.embed.GPIO.Due.PIOA'Access, tx_pin => 11,
                                         rx_pin => 10, tx_absel => 0, rx_absel => 0,
                                         int_id => Ada.Interrupts.Names.USART0_Interrupt);
   chan2 : aliased constant channel_info_rec := (dev_id => dev.USART1_ID, port => Serial1'Access,
                                         pioc => BBS.embed.GPIO.Due.PIOA'Access, tx_pin => 13,
                                         rx_pin => 12, tx_absel => 0, rx_absel => 0,
                                         int_id => Ada.Interrupts.Names.USART1_Interrupt);
   chan3 : aliased constant channel_info_rec := (dev_id => dev.USART3_ID, port => Serial3'Access,
                                         pioc => BBS.embed.GPIO.Due.PIOD'Access, tx_pin => 4,
                                         rx_pin => 5, tx_absel => 1, rx_absel => 1,
                                         int_id => Ada.Interrupts.Names.USART3_Interrupt);
   channel : constant array (port_id'Range) of serial_obj := (chan0'Access, chan1'Access,
                                                              chan2'Access, chan3'Access);
end BBS.embed.due.serial;