1 | /* _ _ _ _ _ _ _ _ _ _
|
2 | * /\ \ /\ \ /\ \ /\_\ / /\ /\ \ /\ \ /\_\/\_\ _ /\ \
|
3 | * / \ \ \_\ \ / \ \ / / / _ / / \ \_\ \ / \ \ / / / / //\_\ / \ \
|
4 | * / /\ \ \ /\__ \ / /\ \ \ \ \ \__ /\_\ / / /\ \__ /\__ \ / /\ \ \ /\ \/ \ \/ / /__/ /\ \ \
|
5 | * / / /\ \_\ / /_ \ \ / / /\ \ \ \ \___\ / / // / /\ \___\ / /_ \ \ / / /\ \ \ / \____\__/ //___/ /\ \ \
|
6 | * / / /_/ / / / / /\ \ \ / / / \ \_\ \__ / / / / \ \ \ \/___// / /\ \ \ / / / \ \_\ / /\/________/ \___\/ / / /
|
7 | * / / /__\/ / / / / \/_// / / \/_/ / / / / / / \ \ \ / / / \/_// / / / / // / /\/_// / / / / /
|
8 | * / / /_____/ / / / / / / / / / / / /_ \ \ \ / / / / / / / / // / / / / / / / / _
|
9 | * / / /\ \ \ / / / / / /________ / / /___/ / //_/\__/ / / / / / / / /___/ / // / / / / / \ \ \__/\_\
|
10 | * / / / \ \ \/_/ / / / /_________\/ / /____\/ / \ \/___/ / /_/ / / / /____\/ / \/_/ / / / \ \___\/ /
|
11 | * \/_/ \_\/\_\/ \/____________/\/_________/ \_____\/ \_\/ \/_________/ \/_/ \/___/_/
|
12 | *
|
13 | *
|
14 | * DMX Receiver for ATxMega
|
15 | * Tested with ATxMega256A3U
|
16 | * Uses external 16 MHz oscillator together with internal PLL to generate 32MHz system clock
|
17 | *
|
18 | *
|
19 | *
|
20 | * Released under the "Don't care" license
|
21 | * Feel free to use this code in any way you want
|
22 | * Also no support will be given in any way
|
23 | *
|
24 | * Code V1.0
|
25 | * 25.09.2015
|
26 | */
|
27 |
|
28 | #include <avr/io.h>
|
29 | #include <stdio.h>
|
30 | #include <avr/interrupt.h>
|
31 |
|
32 | //Buffer to store the DMX stream (start code + 512 channels)
|
33 | volatile unsigned int dmx_buffer[513];
|
34 |
|
35 | void Clock_init(void){
|
36 | //Xosc Bit 7&6 to 11 | Bit 3 to 0 as 1011
|
37 | OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
|
38 | //Bit 3 to 1 to enable external oscillator
|
39 | OSC.CTRL |= OSC_XOSCEN_bm;
|
40 | //wait for stable clock
|
41 | while(!(OSC.STATUS & OSC_XOSCRDY_bm));
|
42 | //Disable register protection for 4 clocks
|
43 | CCP = CCP_IOREG_gc;
|
44 | //Set Bit 2:0 to 011 for external oscillator
|
45 | CLK.CTRL = CLK_SCLKSEL_XOSC_gc;
|
46 | }
|
47 |
|
48 | void PLL_init(void){
|
49 | //Bit 7:0 to 11 for external oscillator as PLL source | 2 as multiplication value
|
50 | OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 0x02;
|
51 | //enable PLL
|
52 | OSC.CTRL |= OSC_PLLEN_bm;
|
53 | //wait for stable oscillation
|
54 | while (!(OSC.STATUS & OSC_PLLRDY_bm));
|
55 | //Disable register protection for 4 clocks
|
56 | CCP = CCP_IOREG_gc;
|
57 | //Set Bit 2:0 for PLL as clock source
|
58 | CLK.CTRL = CLK_SCLKSEL_PLL_gc;
|
59 | }
|
60 |
|
61 | void UART_init(void){
|
62 | // Pin from USARTC0 TxD C3 set to input
|
63 | PORTC.DIRCLR = PIN6_bm;
|
64 | // Asynchronous Modus
|
65 | USARTC1.CTRLC = (USARTC0.CTRLC & ~USART_CMODE_gm ) | USART_CMODE_ASYNCHRONOUS_gc;
|
66 | // No parity
|
67 | USARTC1.CTRLC = (USARTC0.CTRLC & ~USART_PMODE_gm ) | USART_PMODE_DISABLED_gc;
|
68 | // 8 data bits
|
69 | USARTC1.CTRLC = (USARTC0.CTRLC & ~USART_CHSIZE_gm ) | USART_CHSIZE_8BIT_gc;
|
70 | // 2 stop bits
|
71 | USARTC1.CTRLC = (USARTC0.CTRLC & ~USART_SBMODE_bm) | (0x01<<3);
|
72 | // 250 kBaud
|
73 | USARTC1.BAUDCTRLA = 07;
|
74 | // 250 kBaud
|
75 | USARTC1.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(07 >> 8);
|
76 | // Set interrupt level of RX Int to low
|
77 | USARTC1.CTRLA = (USARTC1.CTRLA & ~USART_RXCINTLVL_gm) | USART_RXCINTLVL_LO_gc;
|
78 | // activate USARTC1
|
79 | USARTC1.CTRLB = USART_RXEN_bm;
|
80 |
|
81 | }
|
82 |
|
83 | int main (void){
|
84 |
|
85 | //Start-Up external crystal
|
86 | Clock_init();
|
87 | //Use PLL to generate 32 MHz tact from external crystal
|
88 | PLL_init();
|
89 | //Init UART
|
90 | UART_init();
|
91 |
|
92 | /* Enable LO interrupt level. */
|
93 | PMIC.CTRL |= PMIC_LOLVLEN_bm;
|
94 | //Global Interrupts Enable
|
95 | sei();
|
96 |
|
97 | while (1)
|
98 | {
|
99 | }
|
100 |
|
101 | return 0;
|
102 | }
|
103 |
|
104 | //Interupt vector for USART C1 RX complete
|
105 | ISR (USARTC1_RXC_vect){
|
106 | //Let's count the dmx channels
|
107 | static unsigned int dmx_channel_rx_count = 0;
|
108 | //And check if dmx is valid
|
109 | static unsigned char dmx_valid = 0;
|
110 | //Tmp is never wrong
|
111 | unsigned char tmp = 0;
|
112 |
|
113 | //Store currently received byte into tmp variable
|
114 | tmp = USARTC1.DATA;
|
115 |
|
116 | //Check for framing error as start of dmx transmission
|
117 | if(USARTC1.STATUS & USART_FERR_bm)
|
118 | {
|
119 | //Start to count at first channel
|
120 | dmx_channel_rx_count = 0;
|
121 | //Copy tmp into our dmx buffer at position 0
|
122 | dmx_buffer[0] = tmp;
|
123 | //now check if this value was a 0 which is the start code for normal dmx transmissions
|
124 | if(dmx_buffer[0] == 0)
|
125 | {
|
126 | //ok dmx was valid
|
127 | dmx_valid = 1;
|
128 | //increase count to first dmx channel containing information
|
129 | dmx_channel_rx_count++;
|
130 | }
|
131 | else
|
132 | {
|
133 | //sorry but first byte was not a dmx start code, let's wait for the next frame error
|
134 | dmx_valid = 0;
|
135 | }
|
136 | return;
|
137 | }
|
138 |
|
139 | //yippy dmx was valid so we can process the other 512 channels
|
140 | if(dmx_valid)
|
141 | {
|
142 | //copy the received channel byte into the correct position of our dmx reception buffer
|
143 | dmx_buffer[dmx_channel_rx_count] = tmp;
|
144 | //repeat until we have gathered all 512 channels
|
145 | if(dmx_channel_rx_count < 513)
|
146 | {
|
147 | dmx_channel_rx_count++;
|
148 | }
|
149 | return;
|
150 | }
|
151 | }
|