+/* ----------------- iBus ------------------ */
+
+typedef int16_t servo_val_t;
+servo_val_t ibus_channel[N_IBUS_CHANNELS];
+#define N_IBUS_CHANNELS_DIRECT 14
+/*
+ * channel value ibus frame value
+ * -120 % 900
+ * -100 % 1000
+ * 0 % 1500
+ * 100 % 2000
+ * 120 % 2100
+ */
+#define IBUS_SERVO_CENTER 1500
+
+static void ibus_servo_frame(void)
+{
+ uint16_t csum = 0xFFFF;
+ uint8_t i;
+
+ for (i = 0; i < serial_frame[0]-2; i++)
+ csum -= (uint16_t)serial_frame[i];
+
+ if ((serial_frame[serial_frame[0]-2] != (csum & 0xFF))
+ || (serial_frame[serial_frame[0]-1] != (csum >> 8))) {
+ // invalid csum
+ return;
+ }
+
+ for (i = 0; i < N_IBUS_CHANNELS_DIRECT; i++)
+ ibus_channel[i] = (uint16_t)serial_frame[2 + 2*i]
+ + (((uint16_t)serial_frame[3 + 2*i] & 0x000F) << 8)
+ - IBUS_SERVO_CENTER;
+ // TODO channels 15-18
+}
+
+/* -------------- PWM output --------------- */
+
+#define SERVO_PWM_CENTER (1500 * TICKS_IN_US)
+
+time_t pwm_channels[N_PWM_CHANNELS];
+volatile uint8_t pwm_busy;
+uint8_t pwm_data_ready;