Memory layout of a data structure

Revision as of 06:26, 9 November 2007 by MikeMol (talk | contribs) (Point to C++ instead of C plus plus)

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.

Task
Memory layout of a data structure
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'});