Memory layout of a data structure
It is often useful to control the memory layout of fields in a data structure to match an interface control definition, or to interface with hardware. Define a data structure matching the RS-232 Plug Definition. Use the 9-pin definition for brevity.
You are encouraged to solve this task according to the task description, using any language you may know.
Pin Settings for Plug (Reverse order for socket.) __________________________________________ 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 _________________ 1 2 3 4 5 6 7 8 9 25 pin 9 pin 1 - PG Protective ground 2 - TD Transmitted data 3 3 - RD Received data 2 4 - RTS Request to send 7 5 - CTS Clear to send 8 6 - DSR Data set ready 6 7 - SG Signal ground 5 8 - CD Carrier detect 1 9 - + voltage (testing) 10 - - voltage (testing) 11 - 12 - SCD Secondary CD 13 - SCS Secondary CTS 14 - STD Secondary TD 15 - TC Transmit clock 16 - SRD Secondary RD 17 - RC Receiver clock 18 - 19 - SRS Secondary RTS 20 - DTR Data terminal ready 4 21 - SQD Signal quality detector 22 - RI Ring indicator 9 23 - DRS Data rate select 24 - XTC External clock 25 -
Ada
type Bit is mod 2; type Rs_232_Layout is record Carrier_Detect : Bit; Received_Data : Bit; Transmitted_Data : Bit; Data_Terminal_ready : Bit; Signal_Ground : Bit; Data_Set_Ready : Bit; Request_To_Send : Bit; Clear_To_Send : Bit; Ring_Indicator : Bit; end record; for Rs_232_Layout use record Carrier_Detect at 0 range 0..0; Received_Data at 0 range 1..1; Transmitted_Data at 0 range 2..2; Data_Terminal_Ready at 0 range 3..3; Signal_Ground at 0 range 4..4; Data_Set_Ready at 0 range 5..5; Request_To_Send at 0 range 6..6; Clear_To_Send at 0 range 7..7; Ring_Indicator at 0 range 8..8; end record;
C/C++
Note: The order of the fields is implementation-defined (i.e. the first bit might be the least-significant one or the most-significant one). On GCC and MSVC++, the first bit is the least-significant one.
struct RS232_data { unsigned carrier_detect : 1; unsigned received_data : 1; unsigned transmitted_data : 1; unsigned data_terminal_ready : 1; unsigned signal_ground : 1; unsigned data_set_ready : 1; unsigned request_to_send : 1; unsigned clear_to_send : 1; unsigned ring_indicator : 1; };
The ":1" gives the number of allocated bits. For unused bits (e.g. pin 11 in the 25-pin version above) the field name can be omitted.
Forth
Low level hardware control is a typical use of Forth. None of this is standard, however, since hardware I/O mechanisms differ on different systems. Forth does not have a structure mechanism, much less bitfields. These would be represented instead via bitmask constants if doing real serial port control.
: masks ( n -- ) 0 do 1 i lshift constant loop ; 9 masks DCD RxD TxD DTR SG DSR RTS CTS RI
Example usage, assuming I/O primitives in and out:
hex 3fd constant com1-ctrl decimal : wait-ready begin com1-ctrl in CTS and until ; : wait-rx begin com1-ctrl in CTS and 0= until ; : send-byte ( b -- ) \ send assuming N81 (no parity, 8 bits data, 1 bit frame) 255 and 9 0 do RTS com1-ctrl out wait-ready dup 1 and if TxD else 0 then com1-ctrl out wait-rx 2/ loop drop ;
Of course, this is a very simplified view of the full RS-232 protocol. Also, although this represents the order of the pins in a D-9 connector, this would not necessarily be the same as the order of the bits in a control register.
Perl
use Bit::Vector::Minimal qw(); my $vec = Bit::Vector::Minimal->new(size => 24); my %rs232 = reverse ( 1 => 'PG Protective ground', 2 => 'TD Transmitted data', 3 => 'RD Received data', 4 => 'RTS Request to send', 5 => 'CTS Clear to send', 6 => 'DSR Data set ready', 7 => 'SG Signal ground', 8 => 'CD Carrier detect', 9 => '+ voltage (testing)', 10 => '- voltage (testing)', 12 => 'SCD Secondary CD', 13 => 'SCS Secondary CTS', 14 => 'STD Secondary TD', 15 => 'TC Transmit clock', 16 => 'SRD Secondary RD', 17 => 'RC Receiver clock', 19 => 'SRS Secondary RTS', 20 => 'DTR Data terminal ready', 21 => 'SQD Signal quality detector', 22 => 'RI Ring indicator', 23 => 'DRS Data rate select', 24 => 'XTC External clock', ); $vec->set($rs232{'RD Received data'}, 1); $vec->get($rs232{'TC Transmit clock'});