|
|
@ -4,6 +4,13 @@ |
|
|
|
dshot::dshot(void) { |
|
|
|
} |
|
|
|
|
|
|
|
void dshot::set_pins(uint8_t motor1_pin, uint8_t motor2_pin, uint8_t motor3_pin, uint8_t motor4_pin) { |
|
|
|
_motor1_pin = motor1_pin; |
|
|
|
_motor2_pin = motor2_pin; |
|
|
|
_motor3_pin = motor3_pin; |
|
|
|
_motor4_pin = motor4_pin; |
|
|
|
} |
|
|
|
|
|
|
|
/***
|
|
|
|
(>>4) = 000010000010 # right shift value by 4 |
|
|
|
(^) = 100010101110 # XOR with value |
|
|
@ -17,25 +24,45 @@ uint8_t dshot::crc(uint16_t val) { |
|
|
|
return (a ^ (a >> 8)) & 0x0F; |
|
|
|
} |
|
|
|
|
|
|
|
void dshot::send_cmd(uint8_t pin, uint16_t speed, bool telemetry) { |
|
|
|
void dshot::send_cmd(uint16_t motor1_val, uint16_t motor2_val, uint16_t motor3_val, uint16_t motor4_val, bool telemetry) { |
|
|
|
bool all_channels_done = false; |
|
|
|
|
|
|
|
// Over limit protection
|
|
|
|
if(speed > 2047) |
|
|
|
speed = 2047; |
|
|
|
if(motor1_val > 2047) motor1_val = 2047; |
|
|
|
if(motor2_val > 2047) motor2_val = 2047; |
|
|
|
if(motor3_val > 2047) motor3_val = 2047; |
|
|
|
if(motor4_val > 2047) motor4_val = 2047; |
|
|
|
|
|
|
|
// Speed left shift by 1 and add the telemetry bit
|
|
|
|
uint16_t val = (speed << 1) | telemetry; |
|
|
|
uint16_t val1 = (motor1_val << 1) | telemetry; |
|
|
|
uint16_t val2 = (motor2_val << 1) | telemetry; |
|
|
|
uint16_t val3 = (motor3_val << 1) | telemetry; |
|
|
|
uint16_t val4 = (motor4_val << 1) | telemetry; |
|
|
|
|
|
|
|
// Preparing packets
|
|
|
|
if(!telemetry) { |
|
|
|
uint16_t packet = (val << 4) | crc(val); |
|
|
|
uint16_t packet1 = (val1 << 4) | crc(val1); |
|
|
|
uint16_t packet2 = (val2 << 4) | crc(val2); |
|
|
|
uint16_t packet3 = (val3 << 4) | crc(val3); |
|
|
|
uint16_t packet4 = (val4 << 4) | crc(val4); |
|
|
|
|
|
|
|
// Serial.print(F("PACKET: "));
|
|
|
|
// Serial.println(packet, BIN);
|
|
|
|
uint8_t bits = 16, duration_on, duration_off; |
|
|
|
uint8_t bits = 16, counter = 0; |
|
|
|
uint16_t duration_on, duration_off; |
|
|
|
uint32_t time_on_start, time_off_start, time_on_end, time_off_end; |
|
|
|
uint32_t current_clock; |
|
|
|
uint32_t time_on_start_1, time_on_start_2, time_on_start_3, time_on_start_4; |
|
|
|
uint32_t time_off_start_1, time_off_start_2, time_off_start_3, time_off_start_4; |
|
|
|
uint16_t duration_on_1, duration_on_2, duration_on_3, duration_on_4; |
|
|
|
uint16_t duration_off_1, duration_off_2, duration_off_3, duration_off_4; |
|
|
|
bool bits_done_1, bits_done_2, bits_done_3, bits_done_4; |
|
|
|
|
|
|
|
while(bits != 0) { |
|
|
|
bits--; |
|
|
|
|
|
|
|
/***
|
|
|
|
if((packet >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
if((packet1 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
duration_on = DSHOT_CLOCK_CYCLE_T1H; |
|
|
|
duration_off = DSHOT_CLOCK_CYCLE_T1L; |
|
|
|
} else { // LOW PULSE
|
|
|
@ -43,28 +70,38 @@ void dshot::send_cmd(uint8_t pin, uint16_t speed, bool telemetry) { |
|
|
|
duration_off = DSHOT_CLOCK_CYCLE_T0L; |
|
|
|
} |
|
|
|
|
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor1_pin); |
|
|
|
time_on_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1H time reached
|
|
|
|
while(time_on_end < time_on_start + duration_on) { |
|
|
|
while(time_on_end <= time_on_start + duration_on) { |
|
|
|
time_on_end = ESP.getCycleCount(); |
|
|
|
} |
|
|
|
|
|
|
|
// Setting pin low for T1L
|
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor1_pin); |
|
|
|
time_off_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1L time reached
|
|
|
|
while(time_off_end < time_off_start + duration_off) { |
|
|
|
while(time_off_end <= time_off_start + duration_off) { |
|
|
|
time_off_end = ESP.getCycleCount(); |
|
|
|
} |
|
|
|
|
|
|
|
// Making sure total clock...
|
|
|
|
while(time_off_end < time_on_start + DSHOT_CLOCK_CYCLE_TOTAL) { |
|
|
|
time_off_end = ESP.getCycleCount(); |
|
|
|
} |
|
|
|
***/ |
|
|
|
if((packet >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
|
|
|
|
/***
|
|
|
|
if((packet1 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
// __
|
|
|
|
// If high then generate high signal pulse _| |_|
|
|
|
|
// Setting pin high for T1H
|
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor1_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor2_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor3_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor4_pin); |
|
|
|
time_on_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1H time reached
|
|
|
@ -72,7 +109,10 @@ void dshot::send_cmd(uint8_t pin, uint16_t speed, bool telemetry) { |
|
|
|
} |
|
|
|
|
|
|
|
// Setting pin low for T1L
|
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor1_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor2_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor3_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor4_pin); |
|
|
|
time_off_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1L time reached
|
|
|
@ -82,7 +122,10 @@ void dshot::send_cmd(uint8_t pin, uint16_t speed, bool telemetry) { |
|
|
|
} else { // LOW PULSE
|
|
|
|
// _
|
|
|
|
// If low then generate high signal pulse _| |__|
|
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor1_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor2_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor3_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor4_pin); |
|
|
|
time_on_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1H time reached
|
|
|
@ -90,14 +133,177 @@ void dshot::send_cmd(uint8_t pin, uint16_t speed, bool telemetry) { |
|
|
|
} |
|
|
|
|
|
|
|
// Setting pin low for T1L
|
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor1_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor2_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor3_pin); |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor4_pin); |
|
|
|
time_off_start = ESP.getCycleCount(); |
|
|
|
|
|
|
|
// Wait till the T1L time reached
|
|
|
|
while(ESP.getCycleCount() < time_off_start + DSHOT_CLOCK_CYCLE_T0L) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
***/ |
|
|
|
|
|
|
|
// TODO: NEED TO RETHINK THE LOGIC!!
|
|
|
|
// All channels set to false
|
|
|
|
bits_done_1 = false; |
|
|
|
bits_done_2 = false; |
|
|
|
bits_done_3 = false; |
|
|
|
bits_done_4 = false; |
|
|
|
all_channels_done = false; |
|
|
|
|
|
|
|
if((packet1 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
duration_on_1 = DSHOT_CLOCK_CYCLE_T1H; |
|
|
|
duration_off_1 = DSHOT_CLOCK_CYCLE_T1L; |
|
|
|
} else { // LOW PULSE
|
|
|
|
duration_on_1 = DSHOT_CLOCK_CYCLE_T0H; |
|
|
|
duration_off_1 = DSHOT_CLOCK_CYCLE_T0L; |
|
|
|
} |
|
|
|
|
|
|
|
if((packet2 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
duration_on_2 = DSHOT_CLOCK_CYCLE_T1H; |
|
|
|
duration_off_2 = DSHOT_CLOCK_CYCLE_T1L; |
|
|
|
} else { // LOW PULSE
|
|
|
|
duration_on_2 = DSHOT_CLOCK_CYCLE_T0H; |
|
|
|
duration_off_2 = DSHOT_CLOCK_CYCLE_T0L; |
|
|
|
} |
|
|
|
|
|
|
|
if((packet3 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
duration_on_3 = DSHOT_CLOCK_CYCLE_T1H; |
|
|
|
duration_off_3 = DSHOT_CLOCK_CYCLE_T1L; |
|
|
|
} else { // LOW PULSE
|
|
|
|
duration_on_3 = DSHOT_CLOCK_CYCLE_T0H; |
|
|
|
duration_off_3 = DSHOT_CLOCK_CYCLE_T0L; |
|
|
|
} |
|
|
|
|
|
|
|
if((packet4 >> bits) & 0x0001) { // HIGH PULSE
|
|
|
|
duration_on_4 = DSHOT_CLOCK_CYCLE_T1H; |
|
|
|
duration_off_4 = DSHOT_CLOCK_CYCLE_T1L; |
|
|
|
} else { // LOW PULSE
|
|
|
|
duration_on_4 = DSHOT_CLOCK_CYCLE_T0H; |
|
|
|
duration_off_4 = DSHOT_CLOCK_CYCLE_T0L; |
|
|
|
} |
|
|
|
|
|
|
|
// Start of the bit
|
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor1_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor2_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor3_pin); |
|
|
|
GPIO.out_w1ts = ((uint32_t)1 << _motor4_pin); |
|
|
|
|
|
|
|
time_on_start_1 = ESP.getCycleCount(); |
|
|
|
time_on_start_2 = time_on_start_1; |
|
|
|
time_on_start_3 = time_on_start_1; |
|
|
|
time_on_start_4 = time_on_start_1; |
|
|
|
|
|
|
|
// Due to each of the bits may have different on time and off time. We need to track it
|
|
|
|
// counter = 0;
|
|
|
|
while(!all_channels_done){ |
|
|
|
// while(
|
|
|
|
// counter != 4
|
|
|
|
// ) {
|
|
|
|
current_clock = ESP.getCycleCount(); |
|
|
|
if( |
|
|
|
!bits_done_1 && |
|
|
|
current_clock > time_on_start_1 + duration_on_1 |
|
|
|
) { |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor1_pin); |
|
|
|
// time_off_start_1 = ESP.getCycleCount();
|
|
|
|
time_off_start_1 = current_clock; |
|
|
|
bits_done_1 = true; |
|
|
|
// counter++;
|
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_2 && |
|
|
|
current_clock > time_on_start_2 + duration_on_2 |
|
|
|
) { |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor2_pin); |
|
|
|
// time_off_start_2 = ESP.getCycleCount();
|
|
|
|
time_off_start_2 = current_clock; |
|
|
|
bits_done_2 = true; |
|
|
|
// counter++;
|
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_3 && |
|
|
|
current_clock > time_on_start_3 + duration_on_3 |
|
|
|
) { |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor3_pin); |
|
|
|
// time_off_start_3 = ESP.getCycleCount();
|
|
|
|
time_off_start_3 = current_clock; |
|
|
|
bits_done_3 = true; |
|
|
|
// counter++;
|
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_4 && |
|
|
|
current_clock > time_on_start_4 + duration_on_4 |
|
|
|
) { |
|
|
|
GPIO.out_w1tc = ((uint32_t)1 << _motor4_pin); |
|
|
|
// time_off_start_4 = ESP.getCycleCount();
|
|
|
|
time_off_start_4 = current_clock; |
|
|
|
bits_done_4 = true; |
|
|
|
// counter++;
|
|
|
|
} |
|
|
|
|
|
|
|
if(bits_done_1 && bits_done_2 && bits_done_3 && bits_done_4) |
|
|
|
all_channels_done = true; |
|
|
|
|
|
|
|
} // End of while
|
|
|
|
|
|
|
|
|
|
|
|
// Reset flags
|
|
|
|
all_channels_done = false; |
|
|
|
bits_done_1 = false; |
|
|
|
bits_done_2 = false; |
|
|
|
bits_done_3 = false; |
|
|
|
bits_done_4 = false; |
|
|
|
|
|
|
|
|
|
|
|
// Waiting for each of the motor bits done...
|
|
|
|
while( |
|
|
|
!bits_done_1 && |
|
|
|
!bits_done_2 && |
|
|
|
!bits_done_3 && |
|
|
|
!bits_done_4 |
|
|
|
) { |
|
|
|
current_clock = ESP.getCycleCount(); |
|
|
|
if( |
|
|
|
!bits_done_1 && |
|
|
|
current_clock > time_off_start_1 + duration_off_1 |
|
|
|
) { |
|
|
|
bits_done_1 = true; |
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_2 && |
|
|
|
current_clock > time_off_start_2 + duration_off_2 |
|
|
|
) { |
|
|
|
bits_done_2 = true; |
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_3 && |
|
|
|
current_clock > time_off_start_3 + duration_off_3 |
|
|
|
) { |
|
|
|
bits_done_3 = true; |
|
|
|
} |
|
|
|
|
|
|
|
if( |
|
|
|
!bits_done_4 && |
|
|
|
current_clock > time_off_start_4 + duration_off_4 |
|
|
|
) { |
|
|
|
bits_done_4 = true; |
|
|
|
} |
|
|
|
/*
|
|
|
|
if(bits_done_1 && bits_done_2 && bits_done_3 && bits_done_4) |
|
|
|
all_channels_done = true; |
|
|
|
*/ |
|
|
|
|
|
|
|
} // End of while
|
|
|
|
|
|
|
|
} // End of while
|
|
|
|
} else { |
|
|
|
// TODO: FUTURE for TURTLE MODE
|
|
|
|
} |
|
|
|