minitel_stum/
protocol.rs

1//! Exchange protocol between its components
2//!
3//! Reference: <https://jbellue.github.io/stum1b/#2-6>
4
5use core::fmt;
6use std::fmt::{Display, Formatter};
7
8use num_enum::{IntoPrimitive, TryFromPrimitive};
9
10use crate::videotex;
11
12/// Emission code of the Minitel modules
13///
14/// <https://jbellue.github.io/stum1b/#2-6-1>
15#[repr(u8)]
16#[derive(Debug, Clone, Copy, IntoPrimitive)]
17pub enum RoutingTx {
18    Screen = 0x50,
19    Keyboard = 0x51,
20    Modem = 0x52,
21    Prise = 0x53,
22}
23
24/// Reception code of the Minitel modules
25///
26/// <https://jbellue.github.io/stum1b/#2-6-1>
27#[repr(u8)]
28#[derive(Debug, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
29pub enum RoutingRx {
30    Screen = 0x58,
31    Keyboard = 0x59,
32    Modem = 0x5A,
33    Prise = 0x5B,
34}
35
36/// Escape sequence starting a protocol message
37///
38/// <https://jbellue.github.io/stum1b/#2-6-2>
39#[repr(u8)]
40#[derive(Debug, Clone, Copy, IntoPrimitive)]
41pub enum Protocol {
42    /// Message with one parameter
43    Pro1 = 0x39,
44    /// Message with two parameters
45    Pro2 = 0x3A,
46    /// Message with three parameters
47    Pro3 = 0x3B,
48}
49
50impl Protocol {
51    /// Sequence for a protocol message with one parameter
52    pub fn pro1(x: Pro1) -> [u8; 3] {
53        [videotex::C0::ESC.into(), Self::Pro1.into(), x.into()]
54    }
55
56    /// Sequence for a protocol message with two parameters
57    pub fn pro2(x: Pro2, y: impl Into<u8>) -> [u8; 4] {
58        [
59            videotex::C0::ESC.into(),
60            Self::Pro2.into(),
61            x.into(),
62            y.into(),
63        ]
64    }
65
66    /// Sequence for a protocol message with three parameters
67    pub fn pro3(x: Pro3, y: impl Into<u8>, z: impl Into<u8>) -> [u8; 5] {
68        [
69            videotex::C0::ESC.into(),
70            Self::Pro3.into(),
71            x.into(),
72            y.into(),
73            z.into(),
74        ]
75    }
76
77    /// Sequence for a protocol message to enable or disable a routing
78    ///
79    /// <https://jbellue.github.io/stum1b/#2-6-3>
80    pub fn aiguillage(enable: bool, from: RoutingTx, to: RoutingRx) -> [u8; 5] {
81        Self::pro3(
82            if enable {
83                Pro3::RoutingOn
84            } else {
85                Pro3::RoutingOff
86            },
87            to,
88            from,
89        )
90    }
91}
92
93/// Protocol messages with one parameter
94#[repr(u8)]
95#[derive(Debug, Clone, Copy, IntoPrimitive)]
96pub enum Pro1 {
97    EnqSpeed = 0x74,
98    /// <https://jbellue.github.io/stum1b/#2-6-6>
99    EnqRom = 0x7B,
100}
101
102/// Protocol messages with two parameters
103#[repr(u8)]
104#[derive(Debug, Clone, Copy, IntoPrimitive)]
105pub enum Pro2 {
106    RoutingTo = 0x62,
107    Start = 0x69,
108    Stop = 0x6A,
109    Prog = 0x6B,
110}
111
112/// Protocol messages with three parameters
113#[repr(u8)]
114#[derive(Debug, Clone, Copy, IntoPrimitive)]
115pub enum Pro3 {
116    RoutingOn = 0x61,
117    RoutingOff = 0x60,
118}
119
120/// Protocol responses with two parameter
121#[repr(u8)]
122#[derive(Debug, Clone, Copy, IntoPrimitive)]
123pub enum Pro2Resp {
124    RepStatus = 0x73,
125    QuerySpeedAnswer = 0x75,
126}
127
128/// Protocol responses with three parameter
129#[repr(u8)]
130#[derive(Debug, Clone, Copy, IntoPrimitive)]
131pub enum Pro3Resp {
132    RoutingFrom = 0x63,
133}
134
135/// Function mode for scrolling, error correcting, and lowercase
136///
137/// <https://jbellue.github.io/stum1b/#2-6-11>
138#[repr(u8)]
139#[derive(Debug, Clone, Copy, IntoPrimitive)]
140pub enum FunctionMode {
141    /// Mode Rouleau (screen scrolling)
142    Rouleau = 0x43,
143    /// PCE (Error Correcting Procedure)
144    Procedure = 0x44,
145    /// Minuscule (lowercase)
146    Minuscule = 0x45,
147}
148
149#[derive(Debug, Clone, Copy)]
150pub struct RoutingStatus {
151    pub prise: bool,
152    pub modem: bool,
153    pub keyboard: bool,
154    pub screen: bool,
155}
156
157impl From<u8> for RoutingStatus {
158    fn from(status: u8) -> Self {
159        RoutingStatus {
160            prise: status & 0b1000 != 0,
161            modem: status & 0b0100 != 0,
162            keyboard: status & 0b0010 != 0,
163            screen: status & 0b0001 != 0,
164        }
165    }
166}
167
168#[derive(Debug, Clone, Copy)]
169pub enum Baudrate {
170    B300,
171    B1200,
172    B4800,
173    B9600,
174}
175
176impl Baudrate {
177    pub fn hertz(&self) -> u32 {
178        match self {
179            Baudrate::B300 => 300,
180            Baudrate::B1200 => 1200,
181            Baudrate::B4800 => 4800,
182            Baudrate::B9600 => 9600,
183        }
184    }
185
186    pub fn code(&self) -> u8 {
187        // P 1 E2 E1 E0 R2 R1 R0
188        // P: Parity
189        // E: Emission rate
190        // R: Reception rate
191        // 010 = 300 bauds
192        // 100 = 1200 bauds
193        // 110 = 4800 bauds
194        // 111 = 9600 bauds
195        // All the rates are symetrical (E = R)
196        match self {
197            Baudrate::B300 => 0b01_010_010,
198            Baudrate::B1200 => 0b01_100_100,
199            Baudrate::B4800 => 0b01_110_110,
200            Baudrate::B9600 => 0b01_111_111,
201        }
202    }
203
204    pub fn speeds() -> [Self; 4] {
205        [
206            Baudrate::B1200,
207            Baudrate::B300,
208            Baudrate::B4800,
209            Baudrate::B9600,
210        ]
211    }
212}
213
214impl TryFrom<u8> for Baudrate {
215    type Error = u8;
216
217    fn try_from(value: u8) -> Result<Self, Self::Error> {
218        match value {
219            0b01_010_010 => Ok(Baudrate::B300),
220            0b01_100_100 => Ok(Baudrate::B1200),
221            0b01_110_110 => Ok(Baudrate::B4800),
222            0b01_111_111 => Ok(Baudrate::B9600),
223            _ => Err(value),
224        }
225    }
226}
227
228impl Display for Baudrate {
229    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
230        write!(f, "{} bauds", self.hertz())
231    }
232}
233
234/// Content of the ROM retrived after PRO1 ENQROM
235/// Are omitted the SOH and EOT starting and ending bytes
236/// <https://jbellue.github.io/stum1b/#2-6-6>
237pub struct Rom {
238    pub manufacturer: u8,
239    pub model: u8,
240    pub version: u8,
241}
242
243impl From<[u8; 3]> for Rom {
244    fn from(rom: [u8; 3]) -> Self {
245        Rom {
246            manufacturer: rom[0],
247            model: rom[1],
248            version: rom[2],
249        }
250    }
251}