KissModem.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 KISS_TX_TIMEOUT_FACTOR 3/2 // 1.5x estimated airtime
  25. #define HW_CMD_GET_IDENTITY 0x01
  26. #define HW_CMD_GET_RANDOM 0x02
  27. #define HW_CMD_VERIFY_SIGNATURE 0x03
  28. #define HW_CMD_SIGN_DATA 0x04
  29. #define HW_CMD_ENCRYPT_DATA 0x05
  30. #define HW_CMD_DECRYPT_DATA 0x06
  31. #define HW_CMD_KEY_EXCHANGE 0x07
  32. #define HW_CMD_HASH 0x08
  33. #define HW_CMD_SET_RADIO 0x09
  34. #define HW_CMD_SET_TX_POWER 0x0A
  35. #define HW_CMD_GET_RADIO 0x0B
  36. #define HW_CMD_GET_TX_POWER 0x0C
  37. #define HW_CMD_GET_CURRENT_RSSI 0x0D
  38. #define HW_CMD_IS_CHANNEL_BUSY 0x0E
  39. #define HW_CMD_GET_AIRTIME 0x0F
  40. #define HW_CMD_GET_NOISE_FLOOR 0x10
  41. #define HW_CMD_GET_VERSION 0x11
  42. #define HW_CMD_GET_STATS 0x12
  43. #define HW_CMD_GET_BATTERY 0x13
  44. #define HW_CMD_GET_MCU_TEMP 0x14
  45. #define HW_CMD_GET_SENSORS 0x15
  46. #define HW_CMD_GET_DEVICE_NAME 0x16
  47. #define HW_CMD_PING 0x17
  48. #define HW_CMD_REBOOT 0x18
  49. #define HW_CMD_SET_SIGNAL_REPORT 0x19
  50. #define HW_CMD_GET_SIGNAL_REPORT 0x1A
  51. /* Response code = command code | 0x80. Generic / unsolicited use 0xF0+. */
  52. #define HW_RESP(cmd) ((cmd) | 0x80)
  53. /* Generic responses (shared by multiple commands) */
  54. #define HW_RESP_OK 0xF0
  55. #define HW_RESP_ERROR 0xF1
  56. /* Unsolicited notifications (no corresponding request) */
  57. #define HW_RESP_TX_DONE 0xF8
  58. #define HW_RESP_RX_META 0xF9
  59. #define HW_ERR_INVALID_LENGTH 0x01
  60. #define HW_ERR_INVALID_PARAM 0x02
  61. #define HW_ERR_NO_CALLBACK 0x03
  62. #define HW_ERR_MAC_FAILED 0x04
  63. #define HW_ERR_UNKNOWN_CMD 0x05
  64. #define HW_ERR_ENCRYPT_FAILED 0x06
  65. #define HW_ERR_TX_BUSY 0x07
  66. #define KISS_FIRMWARE_VERSION 1
  67. typedef void (*SetRadioCallback)(float freq, float bw, uint8_t sf, uint8_t cr);
  68. typedef void (*SetTxPowerCallback)(uint8_t power);
  69. typedef float (*GetCurrentRssiCallback)();
  70. typedef void (*GetStatsCallback)(uint32_t* rx, uint32_t* tx, uint32_t* errors);
  71. struct RadioConfig {
  72. uint32_t freq_hz;
  73. uint32_t bw_hz;
  74. uint8_t sf;
  75. uint8_t cr;
  76. uint8_t tx_power;
  77. };
  78. enum TxState {
  79. TX_IDLE,
  80. TX_WAIT_CLEAR,
  81. TX_SLOT_WAIT,
  82. TX_DELAY,
  83. TX_SENDING
  84. };
  85. class KissModem {
  86. Stream& _serial;
  87. mesh::LocalIdentity& _identity;
  88. mesh::RNG& _rng;
  89. mesh::Radio& _radio;
  90. mesh::MainBoard& _board;
  91. SensorManager& _sensors;
  92. uint8_t _rx_buf[KISS_MAX_FRAME_SIZE];
  93. uint16_t _rx_len;
  94. bool _rx_escaped;
  95. bool _rx_active;
  96. uint8_t _pending_tx[KISS_MAX_PACKET_SIZE];
  97. uint16_t _pending_tx_len;
  98. bool _has_pending_tx;
  99. uint8_t _txdelay;
  100. uint8_t _persistence;
  101. uint8_t _slottime;
  102. uint8_t _txtail;
  103. uint8_t _fullduplex;
  104. TxState _tx_state;
  105. uint32_t _tx_timer;
  106. SetRadioCallback _setRadioCallback;
  107. SetTxPowerCallback _setTxPowerCallback;
  108. GetCurrentRssiCallback _getCurrentRssiCallback;
  109. GetStatsCallback _getStatsCallback;
  110. RadioConfig _config;
  111. bool _signal_report_enabled;
  112. void writeByte(uint8_t b);
  113. void writeFrame(uint8_t type, const uint8_t* data, uint16_t len);
  114. void writeHardwareFrame(uint8_t sub_cmd, const uint8_t* data, uint16_t len);
  115. void writeHardwareError(uint8_t error_code);
  116. void processFrame();
  117. void handleHardwareCommand(uint8_t sub_cmd, const uint8_t* data, uint16_t len);
  118. void processTx();
  119. void handleGetIdentity();
  120. void handleGetRandom(const uint8_t* data, uint16_t len);
  121. void handleVerifySignature(const uint8_t* data, uint16_t len);
  122. void handleSignData(const uint8_t* data, uint16_t len);
  123. void handleEncryptData(const uint8_t* data, uint16_t len);
  124. void handleDecryptData(const uint8_t* data, uint16_t len);
  125. void handleKeyExchange(const uint8_t* data, uint16_t len);
  126. void handleHash(const uint8_t* data, uint16_t len);
  127. void handleSetRadio(const uint8_t* data, uint16_t len);
  128. void handleSetTxPower(const uint8_t* data, uint16_t len);
  129. void handleGetRadio();
  130. void handleGetTxPower();
  131. void handleGetVersion();
  132. void handleGetCurrentRssi();
  133. void handleIsChannelBusy();
  134. void handleGetAirtime(const uint8_t* data, uint16_t len);
  135. void handleGetNoiseFloor();
  136. void handleGetStats();
  137. void handleGetBattery();
  138. void handlePing();
  139. void handleGetSensors(const uint8_t* data, uint16_t len);
  140. void handleGetMCUTemp();
  141. void handleReboot();
  142. void handleGetDeviceName();
  143. void handleSetSignalReport(const uint8_t* data, uint16_t len);
  144. void handleGetSignalReport();
  145. public:
  146. KissModem(Stream& serial, mesh::LocalIdentity& identity, mesh::RNG& rng,
  147. mesh::Radio& radio, mesh::MainBoard& board, SensorManager& sensors);
  148. void begin();
  149. void loop();
  150. void setRadioCallback(SetRadioCallback cb) { _setRadioCallback = cb; }
  151. void setTxPowerCallback(SetTxPowerCallback cb) { _setTxPowerCallback = cb; }
  152. void setGetCurrentRssiCallback(GetCurrentRssiCallback cb) { _getCurrentRssiCallback = cb; }
  153. void setGetStatsCallback(GetStatsCallback cb) { _getStatsCallback = cb; }
  154. void onPacketReceived(int8_t snr, int8_t rssi, const uint8_t* packet, uint16_t len);
  155. bool isTxBusy() const { return _tx_state != TX_IDLE; }
  156. /** True only when radio is actually transmitting; use to skip recvRaw in main loop. */
  157. bool isActuallyTransmitting() const { return _tx_state == TX_SENDING; }
  158. };