Конечный автомат в sx127x
Чип sx127x имеет встроенный конечный автомат для FSK модема. Он содержит несколько заранее заданных состояний и позволяет программировать условия перехода между ними. Сделано это прежде всего для тех режимов, где нужна быстрая скорость реакции, а задержки на передачу данных в процессор и обратно слишком большие. Например, приёмник может проснуться, проверить есть ли синхрослово входящего сообщения и если нет, то заснуть на небольшой промежуток времени. Это позволяет немного съэкономить энергию.
Практическое применение
В sx127x есть особенность: после того, как данные переданы, чип остаётся в режиме FSTX. Это режим, в котором передатчик генерирует несущую частоту и передаёт её в эфир. Это не очень хорошо по нескольким причинам: во-первых, засоряется эфир. В разных странах есть регуляции радиоэфира, в которых сказано сколько секунд каждый передатчик может передавать данные на каких частотах (duty cycle). Во-вторых, на передачу несущей частоты тратится энергия.
Именно поэтому, как только сообщение было получено (прерывание PacketSent), sx127x переключает чип в режим STANDBY:
sx127x_set_opmod(SX127x_MODE_STANDBY, device->active_modem, device);
Однако переключение происходит не сразу, а через некоторое время. И всё это время несущая отправляется в эфир. В примере ниже это выделено красным квадратом.
Получается как-то неаккуратненько.
Вместо этого, можно сконфигурировать конечный автомат, который сразу после отправки сообщения будет автоматически переключаться в режим STANDBY.
Конечный автомат
Работа с ним достаточно простая - нужно записать конфигурацию в определённый регистр и он запустится:
uint8_t value = 0b10010000;
ERROR_CHECK(sx127x_spi_write_register(REG_SEQ_CONFIG1, &value, 1, device->spi_device));
В примере выше конфигурация следующая (биты слева направо):
- 1 - стартует конечный автомат
- 0 - не используется
- 0 - режим ожидания - STANDBY
- 10 - из режима ожидания переходит в режим передачи
- 0 - из режима LowPower Selection выключает стейт-машину
- 0 - из режима ожидания переходит в режим передачи
- 0 - из режима передачи переходит в режим LowPower Selection
Однако, запустив программу в первый раз, у меня ничего не получилось. Оказалось, что конечный автомат проглотил прерывание PacketSent, и оно не отправилось в ESP32. Вместо этого прерывания я решил использовать FifoEmpty. Оно генерируется, когда очередь байт на отправку пуста. Возможно, это не самой лучший способ, но другого прерывания просто нет. А его неплохо было бы иметь если нужно отправить подряд несколько сообщений.
В результате у меня получилось следующее:
Как видно, несущая не отправляется сразу же после сообщения.
Результаты
Удивительно, как много всего помещается в такой маленький чип как sx127x. В результате мне удалось чуть-чуть ускорить отправку пакетов и съэкономить энергию.
Теперь вопрос: а сможет ли приёмник получать пакеты так же быстро, как их отправляет передатчик?