Implementando la librería
Ahora que tengo pruebas de la viabilidad del proyecto, es el momento de comenzar a escribir una librería que simplifique el trabajo.
Abstracción del tipo de serial
La librería debería funcionar igual independientemente de si los datos se reciben por un HardwareSerial o por un SoftwareSerial. Su superclase común más cercana es la clase Stream.
Stream tiene los métodos de lectura, pero hereda de Print, que tiene los métodos de escritura.
Como el compilador para AVR de C++ no tiene dynamic_cast, incluiré un booleano para identificar qué tipo de serial se utiliza y hacer así un casting estático cuando sea necesario.
De momento solo es necesario hacer el casting en la inicialización, porque si Stream ni sus superclases tiene el método begin y de hecho es diferente para los dos tipos de serial. Por lo demás se comportan idénticamente.
Detección de tramas
Las tramas comienzan con un byte 0x00, acaban en un byte 0x00 y tienen 25 bytes. También sabemos que los cuatro últimos bits del penúltimo byte son siempre 0, pero esos 4 bits están reservados y podrían cambiar si fuera necesario, no se tendrán en cuenta.
El código que controla la detección de tramas tiene un contador para saber en qué byte está. Guarda en un buffer temporal la trama cruda. El contador aumenta cuando un byte se transfiere con éxito. Si hay un error de paridad SoftwareSerial ignora todo el byte es transparente para la librería SBUS. Si estamos en el byte 0 y el valor no es 0x0F el contador no aumenta, asume que hay un descuadre y continua descartando bytes hasta encontrar el inicio de una trama. Si estamos en el byte 24 pero el valor no es 0x00, algún byte se ha perdido, en lugar de actualizar los canales y reiniciar el contador, solo reinicia el contador descartando la trama completa.
Alternativamente se podría asumir que la trama empieza con dos bytes 0x00 y 0x0F y para aceptar una trama se debe empezar con la siguiente para verificar que la trama acaba sin que se pierdan bytes. Pero esta implementación solo resulta más eficiente en un caso muy específico y sería más costosa. Como ese fragmento de código se tiene que ejecutar muchas veces es mejor dejarlo como está.
Esta función se ha puesto a prueba a conciencia , de hecho la versión descrita aquí es la segunda iteración que he realizado. De momento no he logrado hacer fallar a esta nueva revisión.
El código que controla la detección de tramas tiene un contador para saber en qué byte está. Guarda en un buffer temporal la trama cruda. El contador aumenta cuando un byte se transfiere con éxito. Si hay un error de paridad SoftwareSerial ignora todo el byte es transparente para la librería SBUS. Si estamos en el byte 0 y el valor no es 0x0F el contador no aumenta, asume que hay un descuadre y continua descartando bytes hasta encontrar el inicio de una trama. Si estamos en el byte 24 pero el valor no es 0x00, algún byte se ha perdido, en lugar de actualizar los canales y reiniciar el contador, solo reinicia el contador descartando la trama completa.
Alternativamente se podría asumir que la trama empieza con dos bytes 0x00 y 0x0F y para aceptar una trama se debe empezar con la siguiente para verificar que la trama acaba sin que se pierdan bytes. Pero esta implementación solo resulta más eficiente en un caso muy específico y sería más costosa. Como ese fragmento de código se tiene que ejecutar muchas veces es mejor dejarlo como está.
Esta función se ha puesto a prueba a conciencia , de hecho la versión descrita aquí es la segunda iteración que he realizado. De momento no he logrado hacer fallar a esta nueva revisión.
División de canales
En una actualización anterior publiqué un código que realizaba la división y composición de los 16 canales de 11 bits en 22 bytes. Hacer funcionar la librería ha sido tan sencillo como copiar esos fragmentos de código en las funciones que descomponen y componen las tramas.
Siguiente paso
Dicho todo esto, la recepción de datos está completa. Me gustaría agregar funciones de utilidad para convertir tipos de datos fácilmente. pero eso puede esperar.
El próximo hito a conseguir es la transferencia de telemetría.