KissModem.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #pragma once
  2. #include <Arduino.h>
  3. #include <Identity.h>
  4. #include <Utils.h>
  5. #include <Mesh.h>
  6. #include <helpers/SensorManager.h>
  7. #define KISS_FEND 0xC0
  8. #define KISS_FESC 0xDB
  9. #define KISS_TFEND 0xDC
  10. #define KISS_TFESC 0xDD
  11. #define KISS_MAX_FRAME_SIZE 512
  12. #define KISS_MAX_PACKET_SIZE 255
  13. #define KISS_CMD_DATA 0x00
  14. #define KISS_CMD_TXDELAY 0x01
  15. #define KISS_CMD_PERSISTENCE 0x02
  16. #define KISS_CMD_SLOTTIME 0x03
  17. #define KISS_CMD_TXTAIL 0x04
  18. #define KISS_CMD_FULLDUPLEX 0x05
  19. #define KISS_CMD_SETHARDWARE 0x06
  20. #define KISS_CMD_RETURN 0xFF
  21. #define KISS_DEFAULT_TXDELAY 50
  22. #define KISS_DEFAULT_PERSISTENCE 63
  23. #define KISS_DEFAULT_SLOTTIME 10
  24. #define HW_CMD_GET_IDENTITY 0x01
  25. #define HW_CMD_GET_RANDOM 0x02
  26. #define HW_CMD_VERIFY_SIGNATURE 0x03
  27. #define HW_CMD_SIGN_DATA 0x04
  28. #define HW_CMD_ENCRYPT_DATA 0x05
  29. #define HW_CMD_DECRYPT_DATA 0x06
  30. #define HW_CMD_KEY_EXCHANGE 0x07
  31. #define HW_CMD_HASH 0x08
  32. #define HW_CMD_SET_RADIO 0x09
  33. #define HW_CMD_SET_TX_POWER 0x0A
  34. #define HW_CMD_GET_RADIO 0x0B
  35. #define HW_CMD_GET_TX_POWER 0x0C
  36. #define HW_CMD_GET_CURRENT_RSSI 0x0D
  37. #define HW_CMD_IS_CHANNEL_BUSY 0x0E
  38. #define HW_CMD_GET_AIRTIME 0x0F
  39. #define HW_CMD_GET_NOISE_FLOOR 0x10
  40. #define HW_CMD_GET_VERSION 0x11
  41. #define HW_CMD_GET_STATS 0x12
  42. #define HW_CMD_GET_BATTERY 0x13
  43. #define HW_CMD_GET_MCU_TEMP 0x14
  44. #define HW_CMD_GET_SENSORS 0x15
  45. #define HW_CMD_GET_DEVICE_NAME 0x16
  46. #define HW_CMD_PING 0x17
  47. #define HW_CMD_REBOOT 0x18
  48. #define HW_CMD_SET_SIGNAL_REPORT 0x19
  49. #define HW_CMD_GET_SIGNAL_REPORT 0x1A
  50. /* Response code = command code | 0x80. Generic / unsolicited use 0xF0+. */
  51. #define HW_RESP(cmd) ((cmd) | 0x80)
  52. #define HW_RESP_IDENTITY HW_RESP(HW_CMD_GET_IDENTITY) /* 0x81 */
  53. #define HW_RESP_RANDOM HW_RESP(HW_CMD_GET_RANDOM) /* 0x82 */
  54. #define HW_RESP_VERIFY HW_RESP(HW_CMD_VERIFY_SIGNATURE) /* 0x83 */
  55. #define HW_RESP_SIGNATURE HW_RESP(HW_CMD_SIGN_DATA) /* 0x84 */
  56. #define HW_RESP_ENCRYPTED HW_RESP(HW_CMD_ENCRYPT_DATA) /* 0x85 */
  57. #define HW_RESP_DECRYPTED HW_RESP(HW_CMD_DECRYPT_DATA) /* 0x86 */
  58. #define HW_RESP_SHARED_SECRET HW_RESP(HW_CMD_KEY_EXCHANGE) /* 0x87 */
  59. #define HW_RESP_HASH HW_RESP(HW_CMD_HASH) /* 0x88 */
  60. #define HW_RESP_RADIO HW_RESP(HW_CMD_GET_RADIO) /* 0x8B */
  61. #define HW_RESP_TX_POWER HW_RESP(HW_CMD_GET_TX_POWER) /* 0x8C */
  62. #define HW_RESP_CURRENT_RSSI HW_RESP(HW_CMD_GET_CURRENT_RSSI) /* 0x8D */
  63. #define HW_RESP_CHANNEL_BUSY HW_RESP(HW_CMD_IS_CHANNEL_BUSY) /* 0x8E */
  64. #define HW_RESP_AIRTIME HW_RESP(HW_CMD_GET_AIRTIME) /* 0x8F */
  65. #define HW_RESP_NOISE_FLOOR HW_RESP(HW_CMD_GET_NOISE_FLOOR) /* 0x90 */
  66. #define HW_RESP_VERSION HW_RESP(HW_CMD_GET_VERSION) /* 0x91 */
  67. #define HW_RESP_STATS HW_RESP(HW_CMD_GET_STATS) /* 0x92 */
  68. #define HW_RESP_BATTERY HW_RESP(HW_CMD_GET_BATTERY) /* 0x93 */
  69. #define HW_RESP_MCU_TEMP HW_RESP(HW_CMD_GET_MCU_TEMP) /* 0x94 */
  70. #define HW_RESP_SENSORS HW_RESP(HW_CMD_GET_SENSORS) /* 0x95 */
  71. #define HW_RESP_DEVICE_NAME HW_RESP(HW_CMD_GET_DEVICE_NAME) /* 0x96 */
  72. #define HW_RESP_PONG HW_RESP(HW_CMD_PING) /* 0x97 */
  73. #define HW_RESP_SIGNAL_REPORT HW_RESP(HW_CMD_GET_SIGNAL_REPORT) /* 0x9A */
  74. /* Generic responses (shared by multiple commands) */
  75. #define HW_RESP_OK 0xF0
  76. #define HW_RESP_ERROR 0xF1
  77. /* Unsolicited notifications (no corresponding request) */
  78. #define HW_RESP_TX_DONE 0xF8
  79. #define HW_RESP_RX_META 0xF9
  80. #define HW_ERR_INVALID_LENGTH 0x01
  81. #define HW_ERR_INVALID_PARAM 0x02
  82. #define HW_ERR_NO_CALLBACK 0x03
  83. #define HW_ERR_MAC_FAILED 0x04
  84. #define HW_ERR_UNKNOWN_CMD 0x05
  85. #define HW_ERR_ENCRYPT_FAILED 0x06
  86. #define KISS_FIRMWARE_VERSION 1
  87. typedef void (*SetRadioCallback)(float freq, float bw, uint8_t sf, uint8_t cr);
  88. typedef void (*SetTxPowerCallback)(uint8_t power);
  89. typedef float (*GetCurrentRssiCallback)();
  90. typedef void (*GetStatsCallback)(uint32_t* rx, uint32_t* tx, uint32_t* errors);
  91. struct RadioConfig {
  92. uint32_t freq_hz;
  93. uint32_t bw_hz;
  94. uint8_t sf;
  95. uint8_t cr;
  96. uint8_t tx_power;
  97. };
  98. enum TxState {
  99. TX_IDLE,
  100. TX_WAIT_CLEAR,
  101. TX_SLOT_WAIT,
  102. TX_DELAY,
  103. TX_SENDING
  104. };
  105. class KissModem {
  106. Stream& _serial;
  107. mesh::LocalIdentity& _identity;
  108. mesh::RNG& _rng;
  109. mesh::Radio& _radio;
  110. mesh::MainBoard& _board;
  111. SensorManager& _sensors;
  112. uint8_t _rx_buf[KISS_MAX_FRAME_SIZE];
  113. uint16_t _rx_len;
  114. bool _rx_escaped;
  115. bool _rx_active;
  116. uint8_t _pending_tx[KISS_MAX_PACKET_SIZE];
  117. uint16_t _pending_tx_len;
  118. bool _has_pending_tx;
  119. uint8_t _txdelay;
  120. uint8_t _persistence;
  121. uint8_t _slottime;
  122. uint8_t _txtail;
  123. uint8_t _fullduplex;
  124. TxState _tx_state;
  125. uint32_t _tx_timer;
  126. SetRadioCallback _setRadioCallback;
  127. SetTxPowerCallback _setTxPowerCallback;
  128. GetCurrentRssiCallback _getCurrentRssiCallback;
  129. GetStatsCallback _getStatsCallback;
  130. RadioConfig _config;
  131. bool _signal_report_enabled;
  132. void writeByte(uint8_t b);
  133. void writeFrame(uint8_t type, const uint8_t* data, uint16_t len);
  134. void writeHardwareFrame(uint8_t sub_cmd, const uint8_t* data, uint16_t len);
  135. void writeHardwareError(uint8_t error_code);
  136. void processFrame();
  137. void handleHardwareCommand(uint8_t sub_cmd, const uint8_t* data, uint16_t len);
  138. void processTx();
  139. void handleGetIdentity();
  140. void handleGetRandom(const uint8_t* data, uint16_t len);
  141. void handleVerifySignature(const uint8_t* data, uint16_t len);
  142. void handleSignData(const uint8_t* data, uint16_t len);
  143. void handleEncryptData(const uint8_t* data, uint16_t len);
  144. void handleDecryptData(const uint8_t* data, uint16_t len);
  145. void handleKeyExchange(const uint8_t* data, uint16_t len);
  146. void handleHash(const uint8_t* data, uint16_t len);
  147. void handleSetRadio(const uint8_t* data, uint16_t len);
  148. void handleSetTxPower(const uint8_t* data, uint16_t len);
  149. void handleGetRadio();
  150. void handleGetTxPower();
  151. void handleGetVersion();
  152. void handleGetCurrentRssi();
  153. void handleIsChannelBusy();
  154. void handleGetAirtime(const uint8_t* data, uint16_t len);
  155. void handleGetNoiseFloor();
  156. void handleGetStats();
  157. void handleGetBattery();
  158. void handlePing();
  159. void handleGetSensors(const uint8_t* data, uint16_t len);
  160. void handleGetMCUTemp();
  161. void handleReboot();
  162. void handleGetDeviceName();
  163. void handleSetSignalReport(const uint8_t* data, uint16_t len);
  164. void handleGetSignalReport();
  165. public:
  166. KissModem(Stream& serial, mesh::LocalIdentity& identity, mesh::RNG& rng,
  167. mesh::Radio& radio, mesh::MainBoard& board, SensorManager& sensors);
  168. void begin();
  169. void loop();
  170. void setRadioCallback(SetRadioCallback cb) { _setRadioCallback = cb; }
  171. void setTxPowerCallback(SetTxPowerCallback cb) { _setTxPowerCallback = cb; }
  172. void setGetCurrentRssiCallback(GetCurrentRssiCallback cb) { _getCurrentRssiCallback = cb; }
  173. void setGetStatsCallback(GetStatsCallback cb) { _getStatsCallback = cb; }
  174. void onPacketReceived(int8_t snr, int8_t rssi, const uint8_t* packet, uint16_t len);
  175. bool isTxBusy() const { return _tx_state != TX_IDLE; }
  176. /** True only when radio is actually transmitting; use to skip recvRaw in main loop. */
  177. bool isActuallyTransmitting() const { return _tx_state == TX_SENDING; }
  178. };