Advertisement
teplofizik

dmx.c

May 27th, 2013
712
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.17 KB | None | 0 0
  1. //
  2. // dmx.c
  3. // Протокол DMX
  4. //
  5.  
  6. #include "dmx.h"
  7. #include "../drivers.h"
  8. #include <string.h>
  9.  
  10. typedef struct
  11. {
  12.     TUart    Uart;
  13.     TPin     Direction;
  14. } TDMXPort;
  15.  
  16. typedef enum
  17. {
  18.     BREAK,
  19.     MAB,
  20.     DATA
  21. } TTXState;
  22.  
  23. typedef struct
  24. {
  25.     bool      Transmit;
  26.     bool      Receive;
  27.    
  28.     bool      Received;
  29.     bool      Transmitted;
  30.    
  31.     bool      Active;
  32.    
  33.     TTXState  State;
  34.    
  35.     void (*   onReceive)(uint8_t *, uint16_t);
  36.     void (*   onTransmit)(void);
  37.    
  38.     uint16_t  Index;
  39.     uint8_t   Buffer[513];
  40. } TDMXState;
  41.  
  42. static const TDMXPort  Ports[] = {
  43.     { UART1, { PA, 0 } },
  44.     { UART2, { PA, 1 } },
  45.     { UART3, { PA, 2 } }
  46. };
  47.  
  48. static TDMXState States[sizeof(Ports)/sizeof(Ports[0])];
  49. static const int PortCount = sizeof(Ports)/sizeof(Ports[0]);
  50.  
  51. // Принят Break
  52. static void dmx_onBreak(uint32_t Port)
  53. {
  54.     if(States[Port].Receive) States[Port].Received = true;
  55.    
  56.     States[Port].Index = 0;
  57. }
  58.  
  59. // Принят байт
  60. static void dmx_onReceive(uint32_t Port, uint8_t Data)
  61. {
  62.     if(!(States[Port].Receive && States[Port].Active)) return;
  63.    
  64.     {
  65.         uint16_t Index = States[Port].Index;
  66.        
  67.         if(Index > 512) return;
  68.         States[Port].Buffer[Index] = Data;
  69.         States[Port].Index = Index + 1;
  70.     }
  71. }
  72.  
  73. // Установить скорость передачи на основе длины одного байта в мкс
  74. static void dmx_SetBaudrateByWidth(uint32_t Port, uint32_t Microseconds)
  75. {
  76.     // Вычислим частоту, при которой время передачи каддра (11 бит) будет
  77.     // примерно равна заданной величине
  78.  
  79.     // При заданной частоте BaudRate 1 бит передаётся за 1000000UL / Baudrate микросекунд.
  80.     // В кадре 11 бит: 1 стартовый + 8 бит данных + 2 стоповых.
  81.     //
  82.     // частота = 11 (бит) * 1000000 (перевод секунд в микросекунды) / количество микросекунд.
  83.     uint32_t BaudRate = 11 * 1000000UL / Microseconds;
  84.        
  85.     uart_SetBaudrate(Ports[Port].Uart, BaudRate);
  86. }
  87.  
  88. // Отправить BREAK
  89. static void dmx_SendBreak(uint32_t Port)
  90. {
  91.     // Отправим BREAK 120 uS (133)
  92.     uart_GPIOMode(Ports[Port].Uart, false);
  93.     dmx_SetBaudrateByWidth(Ports[Port].Uart, 120);
  94.     uart_SendByte(Ports[Port].Uart, 0x00);
  95. }
  96.  
  97. // Отправить MAB
  98. static void dmx_SendMarkAfterBreak(uint32_t Port)
  99. {
  100.     // Отправим MAB 20 uS (38)
  101.     uart_GPIOMode(Ports[Port].Uart, true);
  102.     dmx_SetBaudrateByWidth(Ports[Port].Uart, 20);
  103.     uart_SendByte(Ports[Port].Uart, 0x00);
  104. }
  105.  
  106. // Отправить данные, вернт false, если буфер закончился
  107. static void dmx_SendData(uint32_t Port)
  108. {
  109.     int32_t Sended = 0;
  110.     const int32_t Size = sizeof(States[Port].Buffer);
  111.    
  112.     uart_Send(Ports[Port].Uart, &States[Port].Buffer[States[Port].Index], Size - States[Port].Index, &Sended);
  113.     States[Port].Index += Sended;
  114. }
  115.  
  116. // Буфер передачи пуст
  117. static void dmx_onTransmitted(uint32_t Port)
  118. {
  119.     switch(States[Port].State)
  120.     {
  121.     case DATA:
  122.         if(States[Port].Index < 513) dmx_SendData(Port);
  123.         break;
  124.     }
  125. }
  126.  
  127. // Передача завершена
  128. static void dmx_onTransmitCompleted(uint32_t Port)
  129. {
  130.     switch(States[Port].State)
  131.     {
  132.     case BREAK:
  133.         States[Port].State = MAB;
  134.         dmx_SendMarkAfterBreak(Port);
  135.         break;
  136.     case MAB:
  137.         States[Port].Index = 0;
  138.         States[Port].State = DATA;
  139.         uart_SetBaudrate(Ports[Port].Uart, 250000UL);
  140.         uart_UARTMode(Ports[Port].Uart);
  141.         dmx_SendData(Port);
  142.         break;
  143.     case DATA:
  144.         if(States[Port].Index == 513)
  145.         {
  146.             States[Port].Transmitted = true;
  147.             if(States[Port].Transmit && States[Port].Active)
  148.             {
  149.                 dmx_SendBreak(Port);
  150.                 States[Port].State = BREAK;
  151.             }
  152.         }
  153.         break;
  154.     }
  155.    
  156.     if(!States[Port].Transmit) return;
  157. }
  158.  
  159. // Вывод направления - прим
  160. static void rs485_Receive(uint32_t Port)
  161. {
  162.     gpio_LowLevel(&Ports[Port].Direction);
  163. }
  164.  
  165. // Вывод направления - передача
  166. static void rs485_Transmit(uint32_t Port)
  167. {
  168.     gpio_HighLevel(&Ports[Port].Direction);
  169. }
  170.  
  171. static void dmx_Reset(uint32_t Port)
  172. {
  173.     memset(&States[Port].Buffer[0], 0, sizeof(States[Port].Buffer));
  174.  
  175.     States[Port].Active   = false;
  176.     States[Port].Receive  = false;
  177.     States[Port].Transmit = false;
  178. }
  179.  
  180. // Настройка выбранного порта для работы с DMX
  181. void dmx_Init(uint32_t Port)
  182. {
  183.     if(Port >= PortCount) return;
  184.    
  185.     States[Port].onReceive = 0;
  186.     States[Port].onTransmit = 0;
  187.    
  188.     dmx_Reset(Port);
  189.    
  190.     // Управление направлением
  191.     gpio_DigitalOutput(&Ports[Port].Direction);
  192.     rs485_Receive(Port);
  193.    
  194.     {
  195.         TUart Uart = Ports[Port].Uart;
  196.        
  197.         uart_Init(Uart, 250000);
  198.         uart_StopBits(Uart, STOP_BITS_2);
  199.         uart_SetPortIndex(Uart, Port);
  200.         uart_SetHandler(Uart, UART_EVENT_ONBREAK, &dmx_onBreak);
  201.         uart_SetHandler(Uart, UART_EVENT_ONRECEIVE, &dmx_onReceive);
  202.         uart_SetHandler(Uart, UART_EVENT_ONTRANSMITTED, &dmx_onTransmitted);
  203.         uart_SetHandler(Uart, UART_EVENT_ONTRANSMITCOMPLETED, &dmx_onTransmitCompleted);
  204.     }
  205. }
  206.  
  207. // Начать приём
  208. void dmx_Receive(uint32_t Port)
  209. {
  210.     if(Port >= PortCount) return;
  211.     if(States[Port].Transmit) dmx_Reset(Port);
  212.    
  213.     States[Port].Receive = true;
  214.     States[Port].Active = true;
  215.    
  216.     uart_ReceiveEnable(Ports[Port].Uart, true);
  217.     uart_TransmitEnable(Ports[Port].Uart, false);
  218.     rs485_Receive(Port);
  219. }
  220.  
  221. // Начать передачу
  222. void dmx_Transmit(uint32_t Port)
  223. {
  224.     if(Port >= PortCount) return;
  225.     if(States[Port].Receive) dmx_Reset(Port);
  226.  
  227.     States[Port].Transmit = true;
  228.     States[Port].Active = true;
  229.     rs485_Transmit(Port);
  230.    
  231.     States[Port].State = BREAK;
  232.    
  233.    
  234.     dmx_SendBreak(Port);
  235.     uart_ReceiveEnable(Ports[Port].Uart, false);
  236.     uart_TransmitEnable(Ports[Port].Uart, true);
  237.    
  238. }
  239.  
  240. // Прекратить использование линии
  241. void dmx_Stop(uint32_t Port)
  242. {
  243.     if(Port >= PortCount) return;
  244.    
  245.     uart_ReceiveEnable(Ports[Port].Uart, false);
  246.     uart_TransmitEnable(Ports[Port].Uart, false);
  247.    
  248.     States[Port].Active = false;
  249. }
  250.  
  251. // Продолжить использование линии
  252. void dmx_Resume(uint32_t Port)
  253. {
  254.     if(Port >= PortCount) return;
  255.    
  256.     States[Port].Active = true;
  257.    
  258.     if(States[Port].Transmit) dmx_SendBreak(Port);
  259.    
  260.     uart_ReceiveEnable(Ports[Port].Uart, States[Port].Receive);
  261.     uart_TransmitEnable(Ports[Port].Uart, States[Port].Transmit);
  262. }
  263.  
  264.  
  265. // Обновить буфер передачи
  266. void dmx_Update(uint32_t Port, const uint8_t * Data, uint16_t Length)
  267. {
  268.     if(Port >= PortCount) return;
  269.    
  270.     memcpy(&States[Port].Buffer[1], Data, sizeof(States[Port].Buffer) - 1);
  271. }
  272.  
  273. // Установить обработчик
  274. void dmx_SetHandler(uint32_t Port, TDMXEvent Event, void * Handler)
  275. {
  276.     if(Port >= PortCount) return;
  277.    
  278.     switch(Event)
  279.     {
  280.     case DMX_EVENT_ONRECEIVE:  States[Port].onReceive  = (void(*)(uint8_t*,uint16_t))Handler; break;
  281.     case DMX_EVENT_ONTRANSMIT: States[Port].onTransmit = (void(*)(void))Handler; break;
  282.     }
  283. }
  284.  
  285. // Главный цикл
  286. void dmx_Main(void)
  287. {
  288.     int i;
  289.    
  290.     for(i = 0; i < PortCount; i++)
  291.     {
  292.         if(States[i].Transmitted)
  293.         {
  294.             States[i].Transmitted = false;
  295.             if(States[i].onTransmit) States[i].onTransmit();
  296.         }
  297.        
  298.         if(States[i].Received)
  299.         {
  300.             States[i].Received = false;
  301.            
  302.             // признак DMX проверим
  303.             if (States[i].Buffer[0] == 0)
  304.             {
  305.                 if(States[i].onReceive) States[i].onReceive(&States[i].Buffer[1], sizeof(States[i].Buffer) - 1);
  306.             }
  307.         }
  308.     }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement