source: projects/bull-anelex-project/trunk/anelex-interface/src/frontend.c @ 62

Last change on this file since 62 was 62, checked in by sven, 9 years ago

Bull-Anelex-Project, Anelex Interface:

  • Completely new RS232 I/O with ordinary Ring buffer (against FIFO in PC which still sends when CTS is low)
  • Integrated out-of-memory data printing, on button too (strange bug: uC resets when calling ?print X)
  • removed the toolchain.h (almost completely)
  • several improvements

-- sven @ workstation7

File size: 6.8 KB
Line 
1/**
2 * ANELEX PRINTER Interface Microcontroller
3 * RS232 client interaction
4 *
5 * This file collects all routines that directly communicate
6 * to the computer/PC/user/terminal/other uc/anything that is
7 * wired via the RS232 port.
8 *
9 * This file is part of the Bull Anelex Project
10 * Copyright (C) 2010, 2011 Sven Köppel, technikum29.de
11 *
12 * This program is free software; you can redistribute
13 * it and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software
15 * Foundation; either version 3 of the License, or (at
16 * your option) any later version.
17 *
18 * This program is distributed in the hope that it will
19 * be useful, but WITHOUT ANY WARRANTY; without even the
20 * implied warranty of MERCHANTABILITY or FITNESS FOR A
21 * PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 * You should have received a copy of the GNU General
25 * Public License along with this program; if not, see
26 * <http://www.gnu.org/licenses/>.
27 *
28 **/
29
30#include "frontend.h"
31#include "anelex.h"
32#include "data.h"
33
34
35// das hier ist write_advance fuer den print_buffer (pbuf)
36// nicht ISR, sondern INTERRUPTABLE machen! also selbst unterbrechbar!
37ISR(USART0_RX_vect) {
38        char c = UDR0;
39        // verbose debugging with states:
40        //printf("read %x, r=%d, w=%d, used=%d, loss=%d, dirt=%d, nl=%d, cts=%s\n",
41        //      c, pbuf.read_offset, pbuf.write_offset, pbuf.used_elements, pbuf.data_loss, pbuf.dirty_write, pbuf.line_counter, is_cts()?"on":"off");
42
43        if(c == '\r') {
44                switch(input_line_end) {
45                        case CRNL:
46                                // Windows default \r\n: Ignore CR, only obey NL
47                                return;
48                        case CR:
49                                // \r only as line end: just convert to ordinary unix style \n
50                                c = '\n';
51                        case NL:
52                                // just NL which is our standard mode.
53                                break;
54                } // switch
55        } // if CR
56
57        if(!is_cts()) pbuf.dirty_write++; // just for debugging
58
59        int8_t new_offset = (pbuf.write_offset + 1) % BUFFER_LEN;
60
61        if(new_offset == pbuf.read_offset) {
62                // no more space!
63                pbuf.data_loss++;
64                // wipe current data! Data Loss!
65                putchar('@');
66        } else {
67                // still space left
68                pbuf.buffer[new_offset] = c;
69                pbuf.write_offset = new_offset;
70                pbuf.used_elements++;
71                if(c == '\n') {
72                  pbuf.line_counter++;
73        }
74                putchar(c); // vorsicht bei Newlines - hier beabsichtigt (NL->NLCR)
75        }
76
77        // when space is running out then make PC stop sending.
78        if(pbuf.used_elements > BUFFER_LEN - 10)
79                stop_cts();
80
81        // line_state, number of lines, etc. is checked in readline()!
82}
83
84
85
86void readline() {
87        memset(&current_line, 0, LINE_LENGTH); // null the output buffer (important)
88
89        if(builtin_data.index) {
90                // read text from builtin memory (data.c).
91                PGM_P string = builtin_strings[builtin_data.index - 1];
92
93                int nlpos = strchr_P(string[builtin_data.read_offset], '\n');
94                if(nlpos > LINE_LENGTH) nlpos = LINE_LENGTH;
95                strncpy_P(current_line, string[builtin_data.read_offset], nlpos - builtin_data.read_offset);
96
97                builtin_data.read_offset += nlpos + 1; // one behind the newline
98                if(builtin_data.read_offset >= strlen_P(string)) {
99                        puts("Reached end of string!");
100                        builtin_data.index = 0;
101                        builtin_data.read_offset = 0;
102                }
103                return;
104        }
105
106        start_cts();          // let PC start sending! (important)
107        pbuf.data_loss = 0;   // reset statistics for
108        pbuf.dirty_write = 0; // new readline run.
109
110        // loop for first user input
111        for(;;) {
112                if(line_state == LINE_FINISHED && pbuf.line_counter) {
113                        // printer finished printing and is ready for new data.
114                        // and we have detected a full line in the buffer
115                        //_delay_ms(2000); // zum manuellen testen: schnell viele zeilen eingeben
116                        stop_cts();
117                        break;
118                } else if(is_button()) {
119                        // button pressed down - wait until raised again
120                        stop_cts();
121                        while(is_button());
122                        puts("Button pressed.");
123                        strcpy(current_line, "?print 1");
124                        return; // important: Quit readline now.
125                } else if(!is_cts()) {
126                        // apperantly the buffer is full and the ISR made a full stop.
127                        // Hence we must use current contents as a line (remark that the
128                        // line is not finished!). Since the buffer should be large, the
129                        // line is longer than the printer can print, anyway.
130                        puts("ctsoff");
131                        break;
132                }
133        }
134
135        // now copy one line from the buffer to the current_line
136        // output buffer for the anelex driver (which is already filled with 0x00)
137        for(int i=0; i < LINE_LENGTH; i++) {
138                // read advance:
139                pbuf.read_offset = (pbuf.read_offset + 1) % BUFFER_LEN;
140
141                char c = pbuf.buffer[pbuf.read_offset];
142                pbuf.buffer[pbuf.read_offset] = '\0';
143                pbuf.used_elements--;
144                if(c == '\n') {
145                        // end of line detected
146                        pbuf.line_counter--;
147                        break;
148                } else
149                        // store char to anelex driver buffer
150                        current_line[i] = c;
151               
152                if(!pbuf.used_elements)
153                        // buffer is absolutely empty
154                        break;
155        } // for
156
157        // checkout some statistics
158        if(pbuf.data_loss) {
159                printf("Lost %d chars!\n", pbuf.data_loss);
160        }
161
162} // readline()
163
164
165void exec_command() {
166        char* command = current_line + 1; // strip leading '?'
167        printf("Executing command %s\n", command);
168
169        if(strcasecmp(command, "help") == 0) {
170                builtin_print_help();
171        } else if(memcmp(command, "list", 4) == 0) { // 4 = strlen("list")
172                int i = atoi(command + 4); // returns 0 on error
173                if(i <= 0 || i > builtin_strings_length) {
174                        printf("! Usage: ?list ID with ID between 0 and %d\n", builtin_strings_length);
175                        builtin_print_list();
176                } else {
177                        // just print out text on terminal
178                        puts_P(builtin_strings[i-1]);
179                }
180        } else if(memcmp(command, "print", 5) == 0) { // 5 = strlen("print")
181                int i = atoi(command + 5);
182                if(i <= 0 || i > builtin_strings_length) {
183                        printf("! Same syntax like ?list, just prints out to the ANELEX.\n"
184                                "! Make sure you tested before on terminal, e.g ?list 5 => ?print 5\n");
185                } else {
186                        // print out text on ANELEX. That is:
187                        printf("! Now printing text no. %d on ANELEX printer\n", i);
188                        builtin_data.index = i;
189                        return; // read new line, all work is done in readline()
190                }
191        } else {
192                puts("! Command not understood. Please type ?help");
193        }
194} // exec_command
195
196int stdout_transmit(char c, FILE *stream) {
197        if (c == '\n')
198                stdout_transmit('\r', stream);
199        uart_transmit(c);
200        return 0;
201}
202
203void uart_init(uint32_t Baud) {
204    int BaudRate = F_CPU / (16 * Baud) - 1;
205
206    UBRR0H = (unsigned char) BaudRate>>8;
207    UBRR0L = (unsigned char) BaudRate;
208    //set BaudRate
209
210    UCSR0B = UCSR0B | (0b00011000);
211    // RXEN & TXEN enable (Bits 4, 3 = 1)
212
213    UCSR0C = (UCSR0C | (0b10000110));
214    // USART Register Select (Bit 7 = 1)
215    // 8 data bits per frame (Bit 2, 1 = 1)
216
217    UCSR0C = UCSR0C & 0b11110111;
218    // 1 Stop bit (Bit 3 = 0)
219
220        UCSR0B = UCSR0B | (1 << RXCIE0);
221        // Enable Recieve Interrupt (Print Buffer)
222}
223
224
225void print_bits(byte_t byte) {
226        char str[10];
227        puts(itoa(byte, str, 2));
228}
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License