Servo control with ATMega128 and 4017 decade counter

Since moving to FreeRTOS Renoster's control system lost the use of Timer1 thus the ability to control 4 servos using PWM. After some scouring on the net using a 4017 decade counter seem to be the solution to get that functionality back. AUD0.90 later the counter was purchased and all that was left was code.

The first attempt was based on Larry Barello's great paper RC Pulse Generation on an AVR using a decade counter, unfortunately the implementation got messed up while trying to change it to use Timer 3. After some more scouring a pseudo solution presented itself in the Swordfish compiler forums.

A bit of hacking here and there and this is the end product... The ability to control up to 10 servo's using Timer3.

  1. uint16_t ServoPositions[9];
  2. uint16_t *CurrentServo;
  3.  
  4. uint16_t CalcCounterValue(int Time)
  5. {
  6. return (uint16_t)(65535 - (Time * 16) + 1);
  7. }
  8.  
  9. void InitServo()
  10. {
  11. DDRE = _BV(PE3);
  12. DDRA = _BV(PA1);
  13.  
  14. for (int i = 0; i < 9; i++)
  15. ServoPositions[i] = 1500;
  16. CurrentServo = &ServoPositions[0];
  17.  
  18. PORTA |= _BV(PA1);
  19. TCCR3B = (1 << CS30);
  20. TCNT3 = CalcCounterValue(*CurrentServo++);
  21. ETIMSK = (1 << TOIE3);
  22. PORTA &= ~_BV(PA1);
  23. }
  24.  
  25. ISR(TIMER3_OVF_vect)
  26. {
  27. PORTE |= _BV(PE3);
  28. TCNT3 = CalcCounterValue(*CurrentServo++);
  29. PORTE &= ~_BV(PE3);
  30.  
  31. if (CurrentServo > &ServoPositions[8])
  32. CurrentServo = &ServoPositions[0];
  33. }

Schematic:

Below is an image of output 0 of the 4017 connected to a scope.