1 | // Einbinden von bestehenden Modulen
|
2 | #include <avr/io.h> // AVR Standart IO Register Definitionen
|
3 | #include <stdio.h> // Standart IO Register
|
4 | #include <avr/iom644.h> // ATMega644 Register Definitionen
|
5 | #include <avr/iomxx4.h> // ATMegaXX4 Register Definitionen
|
6 | #include <avr/interrupt.h> // Interrupt Register Definitionen
|
7 | #include "arrays.h"
|
8 |
|
9 | //------------------------------------------------------------------------------
|
10 | // Definitionen
|
11 | #define LED_green_on (PORTD |= (1<<5))
|
12 | #define LED_green_off (PORTD &= (~(1<<5)))
|
13 | #define LED_red_on (PORTB |= (1<<3))
|
14 | #define LED_red_off (PORTB &= (~(1<<3)))
|
15 | #define LED_blue_on (PORTD |= (1<<7))
|
16 | #define LED_blue_off (PORTD &= (~(1<<7)))
|
17 | #define X_select (PORTB &= (~(1<<0)))
|
18 | #define Y_select (PORTB &= (~(1<<1)))
|
19 | #define no_select ((PORTB |= (1<<0)) & (PORTB |= (1<<1)))
|
20 |
|
21 | #define search 0
|
22 | #define waitSOH 1
|
23 | #define waitCONTROL 2
|
24 | #define waitAXIS 3
|
25 | #define waitEOT 4
|
26 | #define Buf_max 49
|
27 | #define RXTX_Reg UDR0
|
28 | #define ENQ 0x05
|
29 | #define SOH 0x01 // Start of Header
|
30 | #define EOT 0x04 // End of Transmission
|
31 |
|
32 | #define F_CPU 24000000 // Quarzfrequenz
|
33 | #define BAUDRATE 3000000 // Baudrate für Kommunikation
|
34 |
|
35 | int uart_putchar(char c, FILE *stream); //privat für printf
|
36 | static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
|
37 |
|
38 | //------------------------------------------------------------------------------
|
39 | // Variablen
|
40 | static volatile int SysCount = 0; // Nutz-Counter
|
41 | static volatile int index_rxBuf_R = 0; // Index wo zuletzt gelesen wurde
|
42 | static volatile int index_rxBuf_W = 0; // Index wo zuletzt geschrieben wurde
|
43 | static volatile int rxBuf[Buf_max+1]; // RX Buffer
|
44 |
|
45 | //int control[600]={};
|
46 | //uint16_t x_achse[600]={};
|
47 | //uint16_t y_achse[600]={};
|
48 |
|
49 | //------------------------------------------------------------------------------
|
50 | // Funktionen
|
51 | void DAC_Output(uint16_t val){ // converts 12Bit to the DA Converter
|
52 | if(val & (1<<8)){
|
53 | PORTC |= (1<<3);
|
54 | }
|
55 | else{
|
56 | PORTC &= (~(1<<3));
|
57 | }
|
58 | if(val & (1<<9)){
|
59 | PORTC |= (1<<2);
|
60 | }
|
61 | else{
|
62 | PORTC &= (~(1<<2));
|
63 | }
|
64 | if(val & (1<<10)){
|
65 | PORTC |= (1<<1);
|
66 | }
|
67 | else{
|
68 | PORTC &= (~(1<<1));
|
69 | }
|
70 | if(val & (1<<11)){
|
71 | PORTC |= (1<<0);
|
72 | }
|
73 | else{
|
74 | PORTC &= (~(1<<0));
|
75 | }
|
76 | PORTA = val;
|
77 | }
|
78 | void SysInit(){
|
79 | int i = 0;
|
80 |
|
81 | DDRA = 0xFF; // IO Definieren
|
82 | DDRB = 0x1B;
|
83 | DDRC = 0x0F;
|
84 | PORTC = 0xF0; // Pull up einschalten
|
85 | DDRD = 0xF0;
|
86 |
|
87 | UBRR0H = ((F_CPU/(BAUDRATE*8L)-1) >> 8); // calc Baud
|
88 | UBRR0L = (uint8_t)(F_CPU/(BAUDRATE*8L)-1); // Double speed
|
89 | UCSR0A |= (1<<U2X0); // RS232 Settings: double speed
|
90 | UCSR0B |= (1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0); // Complete Interrupts, RX und TX einschalten
|
91 | UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00); // Asynchron, 8-Bit
|
92 |
|
93 | TCCR2A |= (1<<WGM21); // Timer2 löst mit 100kHz Interrupt aus
|
94 | TCCR2B |= (1<<CS21);
|
95 | TIMSK2 |= (1<<OCIE2A);
|
96 | OCR2A = 30;
|
97 |
|
98 | for(i=0;i<=Buf_max;i++){
|
99 | rxBuf[i] = 0;
|
100 | }
|
101 | DAC_Output(2048);
|
102 | X_select;
|
103 | Y_select;
|
104 | no_select;
|
105 |
|
106 | stdout = &mystdout;
|
107 |
|
108 | sei(); // Global Interrupts einschalten
|
109 | }
|
110 |
|
111 | int uart_putchar(char c, FILE *stream) //Nur für Ausgabe mit printf
|
112 | {
|
113 | if (c == '\n')
|
114 | uart_putchar('\r', stream);
|
115 | loop_until_bit_is_set(UCSR0A, UDRE0);
|
116 | UDR0 = c;
|
117 | return 0;
|
118 | }
|
119 |
|
120 |
|
121 | void RS232(void){
|
122 | static int RS232_state = 0; // Protokollstatus
|
123 | static int index_par = 0; // Array-Variable für Parameters
|
124 | static uint16_t k = 0;
|
125 | if(index_rxBuf_W == index_rxBuf_R){ // Buffer Error abgleichen
|
126 | return; // Wenn Error => aus Funktion heraus springen
|
127 | }
|
128 | if(index_rxBuf_R == Buf_max){ // Erhöhen
|
129 | index_rxBuf_R = 0;
|
130 | }
|
131 | else{
|
132 | index_rxBuf_R ++;
|
133 | }
|
134 | switch (RS232_state){ // RS232 Protokoll
|
135 | case search:
|
136 | if(rxBuf[index_rxBuf_R] == '@'){
|
137 | RS232_state = waitSOH;
|
138 | printf("dac_board_v1");
|
139 | }
|
140 | break;
|
141 | case waitSOH:
|
142 | switch (rxBuf[index_rxBuf_R]){
|
143 | case SOH:
|
144 | RS232_state = waitCONTROL; // In nächsten State wechselnd
|
145 | break;
|
146 | case EOT:
|
147 | RS232_state = waitSOH;
|
148 | break;
|
149 | default:
|
150 | RXTX_Reg = NACK;
|
151 | break;
|
152 | }
|
153 | break;
|
154 | case waitCONTROL:
|
155 | control[k] = rxBuf[index_rxBuf_R];
|
156 | RS232_state = waitAXIS;
|
157 | break;
|
158 | case waitAXIS:
|
159 | switch (index_par){
|
160 | case 0:
|
161 | x_achse[k] = (rxBuf[index_rxBuf_R] << 4);
|
162 | index_par ++;
|
163 | break;
|
164 | case 1:
|
165 | x_achse[k] |= (x_achse[k - 1] | (rxBuf[index_rxBuf_R] >> 4));
|
166 | k ++;
|
167 | y_achse[k] = ((rxBuf[index_rxBuf_R] & 0x0F) << 8);
|
168 | index_par ++;
|
169 | break;
|
170 | case 2:
|
171 | y_achse[k] |= (y_achse[k - 1] | (rxBuf[index_rxBuf_R]));
|
172 | index_par = 0;
|
173 | RS232_state = waitEOT;
|
174 | break;
|
175 | }
|
176 | break;
|
177 | case waitEOT:
|
178 | if(rxBuf[index_rxBuf_R] == EOT){
|
179 | RS232_state = waitSOH;
|
180 | }
|
181 | break;
|
182 | }
|
183 | if(k == 599) k = 0;
|
184 | else k ++;
|
185 | }
|
186 | void Output(){
|
187 | static uint16_t p = 0;
|
188 | if((control[p] & (1<<7)) != 0){
|
189 | LED_red_on;
|
190 | }
|
191 | else{
|
192 | LED_red_off;
|
193 | }
|
194 | if((control[p] & (1<<6)) != 0){
|
195 | LED_green_on;
|
196 | }
|
197 | else{
|
198 | LASER_green_off;
|
199 | }
|
200 | if((control[p] & (1<<5)) != 0){
|
201 | LED_blue_on;
|
202 | }
|
203 | else{
|
204 | LED_blue_off;
|
205 | }
|
206 | if((control[p] & 0x1F) == SysCount){
|
207 | DAC_Output(x_achse[p]);
|
208 | X_select;
|
209 | no_select;
|
210 | DAC_Output(y_achse[p]);
|
211 | Y_select;
|
212 | no_select;
|
213 | if((p == 299) || (p == 599)) RXTX_Reg = ENQ;
|
214 | if(p == 574) p = 0;
|
215 | else p ++;
|
216 | SysCount = 0;
|
217 | }
|
218 | }
|
219 | //------------------------------------------------------------------------------
|
220 | // INTERRUPS
|
221 | ISR(TIMER2_COMPA_vect){ // Mit 100kHz SysCount erhöhen
|
222 | SysCount ++;
|
223 | }
|
224 | ISR(USART0_RX_vect){ // Received Complete Interrupt
|
225 | if(index_rxBuf_W == Buf_max){ // Damit Buffer nicht überläuft
|
226 | index_rxBuf_W = 0;
|
227 | }
|
228 | else{
|
229 | index_rxBuf_W ++;
|
230 | }
|
231 | if(index_rxBuf_W == index_rxBuf_R){ // Wenn Write-Index Read-Index eingeholt hat
|
232 | return;
|
233 | }
|
234 | else{ // Daten speichern
|
235 | rxBuf[index_rxBuf_W] = RXTX_Reg;
|
236 | }
|
237 | }
|
238 | //------------------------------------------------------------------------------
|
239 | // Hauptfunktion (wird beim Start ausgeführt)
|
240 | int main(void){
|
241 | SysInit(); // Systeminitialisierung
|
242 | while(1){
|
243 | RS232();
|
244 | Output();
|
245 | }
|
246 | return 0;
|
247 | }
|
248 | //------------------------------------------------------------------------------
|