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.

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 -

 
:- module rs232.
 
:- interface.
 
:- import_module bool, io, list, string.
 
:- type rs232_pin
   ---> carrier_detect
      ; received_data
      ; transmitted_data
      ; data_terminal_ready
      ; signal_ground
      ; data_set_ready
      ; request_to_send
      ; clear_to_send
      ; ring_indicator.
 
:- type rs232.
 
:- func rs232_bits       = rs232.
:- func rs232_bits(bool) = rs232.
 
:- func rs232_set(rs232, rs232_pin)   = rs232.
:- func rs232_clear(rs232, rs232_pin) = rs232.
 
:- pred rs232_is_set(rs232::in, rs232_pin::in) is semidet.
:- pred rs232_is_clear(rs232::in, rs232_pin::in) is semidet.
 
:- func rs232_set_bits(rs232, list(rs232_pin))   = rs232.
:- func rs232_clear_bits(rs232, list(rs232_pin)) = rs232.
 
:- func to_string(rs232) = string.
 
:- pred write_rs232(rs232::in, io::di, io::uo) is det.
 
:- implementation.
 
:- import_module bitmap.
 
:- type rs232 == bitmap.
 
rs232_bits          = rs232_bits(no).
rs232_bits(Default) = bitmap.init(9, Default).
 
rs232_set(A, Pin)   = unsafe_set(A, to_index(Pin)).
rs232_clear(A, Pin) = unsafe_clear(A, to_index(Pin)).
 
rs232_is_set(A, Pin)   :- unsafe_is_set(A, to_index(Pin)).
rs232_is_clear(A, Pin) :- unsafe_is_clear(A, to_index(Pin)).
 
rs232_set_bits(A, Pins)   = foldl((func(Pin, B) = rs232_set(B, Pin)), Pins, A).
rs232_clear_bits(A, Pins) = foldl((func(Pin, B) = rs232_clear(B, Pin)), Pins, A).
 
to_string(A) = bitmap.to_string(A).
 
write_rs232(A, !IO) :- write_bitmap(resize(A, 16, no), !IO).
                       % cannot write a bitmap that isn't byte-divisible
 
:- func to_index(rs232_pin) = bit_index.
to_index(carrier_detect)      = 0.
to_index(received_data)       = 1.
to_index(transmitted_data)    = 2.
to_index(data_terminal_ready) = 3.
to_index(signal_ground)       = 4.
to_index(data_set_ready)      = 5.
to_index(request_to_send)     = 6.
to_index(clear_to_send)       = 7.
to_index(ring_indicator)      = 8.
 
:- end_module rs232.
 