123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- #include "AP_SBusOut.h"
- #include <AP_Math/AP_Math.h>
- #include <AP_SerialManager/AP_SerialManager.h>
- #include <SRV_Channel/SRV_Channel.h>
- extern const AP_HAL::HAL& hal;
- #define SBUS_DEBUG 0
- #define SBUS_BSIZE 25
- #define SBUS_CHANNELS 16
- #define SBUS_MIN 880.0f
- #define SBUS_MAX 2156.0f
- #define SBUS_SCALE (2048.0f / (SBUS_MAX - SBUS_MIN))
- const AP_Param::GroupInfo AP_SBusOut::var_info[] = {
-
-
-
-
-
-
- AP_GROUPINFO("RATE", 1, AP_SBusOut, sbus_rate, 50),
- AP_GROUPEND
- };
- AP_SBusOut::AP_SBusOut(void)
- {
-
- AP_Param::setup_object_defaults(this, var_info);
- }
- void AP_SBusOut::sbus_format_frame(uint16_t *channels, uint8_t num_channels, uint8_t buffer[SBUS_BSIZE])
- {
- uint8_t index = 1;
- uint8_t offset = 0;
- memset(buffer, 0, SBUS_BSIZE);
- buffer[0] = 0x0f;
-
- uint8_t nchan = MIN(num_channels, SBUS_CHANNELS);
- for (unsigned i = 0; i < nchan; ++i) {
-
- uint16_t pwmval = MAX(channels[i], SBUS_MIN);
- uint16_t value = (uint16_t)((pwmval - SBUS_MIN) * SBUS_SCALE);
- if (value > 0x07ff) {
- value = 0x07ff;
- }
- #if SBUS_DEBUG
- static uint16_t lastch9 = 0;
- if ((i==8) && (pwmval != lastch9)) {
- lastch9 = pwmval;
- hal.console->printf("channel 9 pwm: %04d\n", pwmval);
- }
- #endif
- while (offset >= 8) {
- ++index;
- offset -= 8;
- }
- buffer[index] |= (value << (offset)) & 0xff;
- buffer[index + 1] |= (value >> (8 - offset)) & 0xff;
- buffer[index + 2] |= (value >> (16 - offset)) & 0xff;
- offset += 11;
- }
- }
- void
- AP_SBusOut::update()
- {
- if (!initialised) {
- initialised = true;
- init();
- }
- if (sbus1_uart == nullptr) {
- return;
- }
-
- static uint32_t last_micros = 0;
- uint32_t now = AP_HAL::micros();
- if ((now - last_micros) <= sbus_frame_interval) {
- return;
- }
- last_micros = now;
-
- uint8_t nchan = MIN(NUM_SERVO_CHANNELS, SBUS_CHANNELS);
- uint16_t channels[SBUS_CHANNELS] {};
- for (unsigned i = 0; i < nchan; ++i) {
- SRV_Channel *c = SRV_Channels::srv_channel(i);
- if (c == nullptr) {
- continue;
- }
- channels[i] = c->get_output_pwm();
- }
- uint8_t buffer[SBUS_BSIZE];
- sbus_format_frame(channels, nchan, buffer);
- #if SBUS_DEBUG
- hal.gpio->pinMode(55, HAL_GPIO_OUTPUT);
- hal.gpio->write(55, 1);
- #endif
- sbus1_uart->write(buffer, sizeof(buffer));
- #if SBUS_DEBUG
- hal.gpio->pinMode(55, HAL_GPIO_OUTPUT);
- hal.gpio->write(55, 0);
- #endif
- }
- void AP_SBusOut::init() {
- uint16_t rate = sbus_rate.get();
- #if SBUS_DEBUG
- hal.console->printf("AP_SBusOut: init %d Hz\n", rate);
- #endif
-
- sbus_frame_interval = (1000UL * 1000UL) / rate - 500;
-
-
- if (sbus_frame_interval < 3700) {
- sbus_frame_interval = 3700;
- }
- AP_SerialManager *serial_manager = AP_SerialManager::get_singleton();
- if (!serial_manager) {
- return;
- }
- sbus1_uart = serial_manager->find_serial(AP_SerialManager::SerialProtocol_Sbus1,0);
- }
|