kiss.rs (4536B)
1 pub(crate) enum KissAction { 2 PushTx(u8), 3 ClearTx, 4 SendTx, 5 _SetTxDelay { tx_delay_10ms: u8 }, 6 _SetPersistence { persistence: u8 }, 7 _SetSlotTime { slot_time_10ms: u8 }, 8 _SetTxTail { tx_tail_10ms: u8 }, 9 _SetFullDuplex { full_duplex: bool }, 10 _SetHardware { argument: u8 }, 11 _Return, 12 } 13 14 enum KissCommand { 15 DataFrame, 16 TxDelay, 17 Persistence, 18 SlotTime, 19 TxTail, 20 FullDuplex, 21 SetHardware, 22 Return, 23 #[allow(dead_code)] 24 Invalid(u8), 25 } 26 27 enum KissPort { 28 Port0, 29 Port1, 30 Port2, 31 Port3, 32 Port4, 33 Port5, 34 Port6, 35 Port7, 36 Port8, 37 Port9, 38 Port10, 39 Port11, 40 Port12, 41 Port13, 42 Port14, 43 Port15, 44 } 45 46 struct KissHostTypeIndicator { 47 _function: KissCommand, 48 _port: KissPort, 49 } 50 51 impl From<u8> for KissHostTypeIndicator { 52 fn from(value: u8) -> Self { 53 let function_number = (value & 0b1111_0000) >> 4; 54 let function = match function_number { 55 0 => KissCommand::DataFrame, 56 1 => KissCommand::TxDelay, 57 2 => KissCommand::Persistence, 58 3 => KissCommand::SlotTime, 59 4 => KissCommand::TxTail, 60 5 => KissCommand::FullDuplex, 61 6 => KissCommand::SetHardware, 62 15 => KissCommand::Return, 63 f => KissCommand::Invalid(f), 64 }; 65 let port_index = value & 0b0000_1111; 66 let port = match port_index { 67 0 => KissPort::Port0, 68 1 => KissPort::Port1, 69 2 => KissPort::Port2, 70 3 => KissPort::Port3, 71 4 => KissPort::Port4, 72 5 => KissPort::Port5, 73 6 => KissPort::Port6, 74 7 => KissPort::Port7, 75 8 => KissPort::Port8, 76 9 => KissPort::Port9, 77 10 => KissPort::Port10, 78 11 => KissPort::Port11, 79 12 => KissPort::Port12, 80 13 => KissPort::Port13, 81 14 => KissPort::Port14, 82 15 => KissPort::Port15, 83 p => unreachable!("Expected port index in range [0, 15] but got {p}"), 84 }; 85 KissHostTypeIndicator { 86 _function: function, 87 _port: port, 88 } 89 } 90 } 91 92 pub(crate) enum KissTncState { 93 Idle, 94 Fend, 95 TypeIndicator, 96 Data, 97 Fesc, 98 } 99 100 impl KissTncState { 101 const FEND: u8 = 0xc0; 102 const FESC: u8 = 0xdb; 103 const TFEND: u8 = 0xdc; 104 const TFESC: u8 = 0xdd; 105 106 pub(crate) fn update(&mut self, byte: u8) -> Option<KissAction> { 107 match (&self, byte) { 108 // FEND after data means the frame is complete and ready to send 109 (KissTncState::Data, Self::FEND) => { 110 *self = KissTncState::Fend; 111 Some(KissAction::SendTx) 112 } 113 114 // FEND anywhere else means the frame is incomplete and should not be sent, but a new 115 // frame is beginning 116 (_, Self::FEND) => { 117 *self = KissTncState::Fend; 118 Some(KissAction::ClearTx) 119 } 120 121 // Idle state waits for FEND 122 (KissTncState::Idle, _) => { 123 *self = KissTncState::Idle; 124 None 125 } 126 127 // Type indicator follows FEND 128 (KissTncState::Fend, _) => { 129 *self = KissTncState::TypeIndicator; 130 None 131 } 132 133 // FESC can follow frame type indicator or data 134 (KissTncState::TypeIndicator, Self::FESC) => { 135 *self = KissTncState::Fesc; 136 None 137 } 138 (KissTncState::Data, Self::FESC) => { 139 *self = KissTncState::Fesc; 140 None 141 } 142 143 // Data follows type indicator 144 (KissTncState::TypeIndicator, _) => { 145 *self = KissTncState::Data; 146 None 147 } 148 149 // Handle escaped bytes 150 (KissTncState::Fesc, Self::TFEND) => { 151 *self = KissTncState::Data; 152 Some(KissAction::PushTx(Self::FEND)) 153 } 154 (KissTncState::Fesc, Self::TFESC) => { 155 *self = KissTncState::Data; 156 Some(KissAction::PushTx(Self::FESC)) 157 } 158 (KissTncState::Fesc, b) => { 159 *self = KissTncState::Data; 160 Some(KissAction::PushTx(b)) 161 } 162 163 // Data follows data 164 (KissTncState::Data, b) => { 165 *self = KissTncState::Data; 166 Some(KissAction::PushTx(b)) 167 } 168 } 169 } 170 }