Control drones with a proper joystick
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cppm.cpp 2.4KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * Combined-PPM signal generator
  3. *
  4. * Based on the code from:
  5. * https://quadmeup.com/generate-ppm-signal-with-arduino/
  6. * https://github.com/DzikuVx/ppm_encoder/blob/master/ppm_encoder_source.ino
  7. *
  8. * Copyright 2016 by Thomas Buck <xythobuz@xythobuz.de>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation, version 2.
  13. */
  14. #include <Arduino.h>
  15. #include "cppm.h"
  16. //#define DEBUG_OUTPUT Serial
  17. CPPM* CPPM::inst = NULL;
  18. void CPPM::init(void) {
  19. #ifdef DEBUG_OUTPUT
  20. DEBUG_OUTPUT.println("Initializing Timer...");
  21. #endif
  22. state = 1;
  23. currentChannel = channels;
  24. calcRest = 0;
  25. for (uint8_t i = 0; i < channels; i++) {
  26. data[i] = CHANNEL_DEFAULT_VALUE;
  27. }
  28. pinMode(CPPM_OUTPUT_PIN, OUTPUT);
  29. digitalWrite(CPPM_OUTPUT_PIN, CPPM::inst->onState ? LOW : HIGH);
  30. cli();
  31. TCCR1A = 0; // set entire TCCR1 register to 0
  32. TCCR1B = 0;
  33. OCR1A = 100; // compare match register
  34. TCCR1B |= (1 << WGM12); // turn on CTC mode
  35. TCCR1B |= (1 << CS11); // 8 prescaler: 0,5 microseconds at 16mhz
  36. TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
  37. sei();
  38. }
  39. void CPPM::copy(uint16_t* d) {
  40. #ifdef DEBUG_OUTPUT
  41. DEBUG_OUTPUT.println("New CPPM data!");
  42. #endif
  43. cli();
  44. for (int i = 0; i < channels; i++) {
  45. data[i] = d[i];
  46. }
  47. sei();
  48. }
  49. ISR(TIMER1_COMPA_vect) {
  50. if (!CPPM::inst) {
  51. return;
  52. }
  53. TCNT1 = 0;
  54. if (CPPM::inst->state) {
  55. // start pulse
  56. digitalWrite(CPPM_OUTPUT_PIN, CPPM::inst->onState ? HIGH : LOW);
  57. OCR1A = CPPM::inst->pulseLength << 1;
  58. CPPM::inst->state = 0;
  59. } else {
  60. // end pulse and calculate when to start the next pulse
  61. digitalWrite(CPPM_OUTPUT_PIN, CPPM::inst->onState ? LOW : HIGH);
  62. CPPM::inst->state = 1;
  63. if (CPPM::inst->currentChannel >= CPPM::inst->channels) {
  64. CPPM::inst->currentChannel = 0;
  65. CPPM::inst->calcRest += CPPM::inst->pulseLength;
  66. OCR1A = (CPPM::inst->frameLength - CPPM::inst->calcRest) << 1;
  67. CPPM::inst->calcRest = 0;
  68. } else {
  69. OCR1A = (CPPM::inst->data[CPPM::inst->currentChannel] - CPPM::inst->pulseLength) << 1;
  70. CPPM::inst->calcRest += CPPM::inst->data[CPPM::inst->currentChannel];
  71. CPPM::inst->currentChannel++;
  72. }
  73. }
  74. }