source: firmware/InterlockArduino/src/fact++interface/fact++interface.tex @ 14247

Last change on this file since 14247 was 14247, checked in by neise, 7 years ago
moving forward
File size: 23.5 KB
Line 
1\documentclass{article}
2\usepackage{listings}
3\usepackage{color}
4
5 
6\definecolor{dkgreen}{rgb}{0,0.6,0}
7\definecolor{gray}{rgb}{0.5,0.5,0.5}
8\definecolor{mauve}{rgb}{0.58,0,0.82}
9 
10\lstset{ %
11  language=C++,                % the language of the code
12  basicstyle=\footnotesize,           % the size of the fonts that are used for the code
13  numbers=left,                   % where to put the line-numbers
14  numberstyle=\tiny\color{gray}% the style that is used for the line-numbers
15  stepnumber=2,                   % the step between two line-numbers. If it's 1, each line
16                                  % will be numbered
17  numbersep=5pt,                  % how far the line-numbers are from the code
18  backgroundcolor=\color{white},      % choose the background color. You must add \usepackage{color}
19  showspaces=false,               % show spaces adding particular underscores
20  showstringspaces=false,         % underline spaces within strings
21  showtabs=false,                 % show tabs within strings adding particular underscores
22  frame=single,                   % adds a frame around the code
23  rulecolor=\color{black},        % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. commens (green here))
24  tabsize=2,                      % sets default tabsize to 2 spaces
25  captionpos=b,                   % sets the caption-position to bottom
26  breaklines=true,                % sets automatic line breaking
27  breakatwhitespace=false,        % sets if automatic breaks should only happen at whitespace
28  title=\lstname,                   % show the filename of files included with \lstinputlisting;
29                                  % also try caption instead of title
30  keywordstyle=\color{blue},          % keyword style
31  commentstyle=\color{dkgreen},       % comment style
32  stringstyle=\color{mauve},         % string literal style
33  escapeinside={\%*}{*)},            % if you want to add a comment within your code
34  morekeywords={*,...}               % if you want to add more keywords to the set
35}
36
37\begin{document}
38\title{FACT Arduino ethernet communication Interface }
39\author{D.Neise}
40\maketitle
41\tableofcontents
42\newpage
43
44\section{Introduction}
45Arduino is the name of a series of open source
46microcontroller equipped boards. The
47microcontroller in use is out of Atmels ATmega family.
48The FACT telescope uses mostly the Arduino Ethernet board to
49monitor and control certain auxiliary systems like the motors of the camera
50shutter.
51This board was chosen since the needed hardware for ethernet access,
52like a dedicated ethernet controller (Wiznet W5100) and the jack, are already
53in place. In addition the programming of the board as comparably easy.
54Setting up a TCP/IP server (using either a fix IP or a DHCP server) as well as
55raw byte-stream communication with clients is handled by the Ethernet library,
56which comes with the Arduino IDE.
57There is a variety of open source extension boards available for the Arduino,
58both from the Arduino group as well as from unrelated developers. These
59extension boards are usually called shields.
60The shields can be connected to the ATmega port pins via 100mil headers,
61which can be used to quickly connect custom peripherals as well.
62Typical ATmega digital outputs can drive up to 10mA at 5.0V and thus allow for
63quick connection of LEDs for software tests or similar quick hacks.
64There exists an open source C cross compiler for ATmega MCUs as well a std-lib
65implementation. The Arduino group created not only a user friendly
66(maybe not power user friendly) IDE but also supplies the beginner with a
67bunch of useful libraries from serial communication to LCD interfacing.
68
69\newpage
70\subsection{std C vs. Arduinos C++ dialect}
71The Arduino IDE provides the beginner with a simple programming enviroment.
72While a standard microcontroller program usually is composed of an init section
73and a never ending while loop which contains the actual job of the microcontroller,
74e.g. like this:
75\begin{lstlisting}
76void main (void){
77
78    // set up peripherals and I/O pins
79    // e.g:
80    DDRD |= 1<<PD6;  // define pin PD6 to be an output
81   
82    // here the actual 'job' is performed
83    while(1){
84        // toggle the output
85        PORTD ^= 1<<PD6;
86    }
87}
88\end{lstlisting}
89
90This would look like this in the Arduino C++ dialect:
91\begin{lstlisting}
92// On the Arduino board there are numbers printed
93// next to the 100mil header sockets.
94// The ATmega pin PD6 is named '6' on the Arduino board.
95const int my_output_pin = 6;
96boolean output_pin_state = false;
97
98setup(){
99    pinMode( my_output_pin , OUTPUT);
100}
101
102loop(){
103    // toggle the variable...
104    output_pin_state = !output_pin_state;
105    // write the value of the variable, to the pin
106    digitalWrite( my_output_pin , output_pin_state);
107}
108\end{lstlisting}
109
110In many cases, the code written in the Arduino-C++ dialect does not
111produce the optimal binary, but one can always fall back to standard C
112or even inline assembler, if needed.
113
114\subsection{ scheduling on microcontrollers }
115There is nothing like a scheduler running on a microcontroller, so one can not
116produce concurrent running code by using threads. The developer needs
117in such a case to implement a form of time sharing himself.
118(Although there might be libraries easing the pain a little.)
119
120%Assume the following task:
121%The ATmegas internal ADC should be used to measure a voltage as soon
122%as an attached button is pressed. Since we expect some noise, the ADC should
123%sample the voltage 100 times and return the mean and the std deviation.
124%Since the user is expected to be slow, when pressing a button, 50 of the samples
125%shoule be taken, before the user pressed the button.
126%We assume the CPU frequency is 16MHz. And the serial communication to run at
127%9600 baud.
128%The ADC needs about 130us for a conversion.
129
130\subsubsection{simple time sharing}
131
132The most prominent solution maybe looks like this
133\begin{lstlisting}
134loop(){
135    check_if_a_button_was_pressed();        // < 1us
136    check_if_the_ADC_has_a_valid_reading(); // < 1us
137    calculate_something();                  // approx 1ms
138    communicate(); //9600 baud              // 1ms per byte
139}
140\end{lstlisting}
141Each of these functions \emph{might} run for a well know and limited amount
142of time.
143This is important in case one wants to ensure, the user experience is immediate.
144As an example, one might assume the button, which is checked in the first function, is a kind of emergency
145shutdown button. In this case, one has to ensure, that the communicate function
146will never block and thus inhibit the checking of the button and so inhibit
147the emergency shutdown.
148
149
150\subsubsection{Interrupts}
151Another solution is the use of hardware interrupts. The ATmega comes
152with quite a lot of interrupt routines, such as:
153\begin{itemize}
154\item ADC ready
155\item timer overflow \\there are typically 3 timers
156\item timer reached certain value \\typically 2 values per timer
157\item special interrupt pin state changed \\good for emergency buttons
158\item serial transfer complete (USART) \\i.e. the Arduino USB connection
159\item SPI transfer complete \\the W5100 is connected via SPI
160\end{itemize}
161
162Each of these interrupt sources can stop the running program and let the controller
163jump to a special, often very tiny, so called interrupt service routine.
164In case the developer connected the emergency button to one of the dedicated
165interrupt pins, the program might look like this:
166\newpage
167\begin{lstlisting}
168// global variables for data transfer
169// between interrupt service routines
170// and 'normal' user code
171volatile boolean got_enough_adc_readings = false;
172char adc_buffer[ADC_BUFFER_SIZE];
173char adc_value_counter = 0;
174
175setup(){
176    enable_external_pin_irq();
177    enable_adc_irq();
178}
179
180loop(){
181    // this might take about 1ms
182    if (got_enough_adc_readings == true){
183        calculate_something();
184        enable_adc_irq();
185    }
186    // this might take several 10ms, since 9600 baud is so slow.
187    communicate(); //9600 baud serial communication
188}
189
190// this should take less than 16 cycles = 1us
191adc_interrupt_service_routine(){
192    short reading = ADC_REGISTER;
193    adc_buffer[adc_value_counter] = reading;
194    adc_value_counter++;
195    if (adc_value_counter == ADC_BUFFER_SIZE){
196        got_enough_adc_readings = true;
197        disable_adc_irq();
198    }
199}
200// this should also take hardly any time ...
201external_pin_toggle_service_routine(){
202    do_emergency_stuff();
203}
204\end{lstlisting}
205
206Writing the code in this manner does ensure, that even in case of very
207long communication of several hundred bytes, the emergency button press is immediately
208reacted on. In addition, the ADC samples are aquired faster than in the previous
209solution, since the ADC is read when ever it finished a conversion (about every 100us)
210and not after each communication.
211
212This solution is not very complicated, however the use of interrupts is connected
213to some caveats, which are connected to non atomic access of 2-byte variables,
214and compiler optimizations.
215
216In addition this solution is clearly to be used, in case a developer needs to ensure
217a certain action is performed with a fixed rate, like monitoring the status
218of a certain peripheral. This can be easily acomplished using one of the hardware
219timer overflow interrupts.
220
221\section{Reliability}
222Having the previous considerations in mind, one should also not forget,
223that a remote device might not even have an emergency button, since the
224ethernet connection is the only way for the user to interact with the deivce.
225In such a case, the ethernet communication should be realiable and quick.
226
227Consider the flodding case:\\
228Flodding might be caused by impatient users or buggy client software.
229In such a case, the requests might come in faster, than they can be reacted on,
230so the ethernet input buffer starts to fill up.
231
232In such a case, the device should at least, realize that the client is flodding
233and in addition to the normal command execution answer, send a warning, that
234the input buffer is e.g. 50\% filled.
235
236The client software should at least understand such a warning and stop sending
237requests for a while.
238
239\section{Protocol}
240In order to be quick and reliable, the protocol should be fairly easy.
241Thus I recommend a fixed size binary, with unequal message sizes
242for client to server requests and server to client messages.
243
244\subsection{client to server}
245While the client to server communication is merely used
246to send commands and settings,
247the messages can be rather short. For example
248
249\begin{tabular}{|l|l|l|}
250\hline
251desc. & content & size \\
252\hline
253header      & 0xF1              & 1 char\\
254address     &                   & 1 char\\
255access type & \verb=SET|NAND|OR|XOR|READ=   & 1 char\\
256data        &                   & 1 char\\
257footer      & 0xB4              & 1 char\\
258\hline
259\end{tabular}
260
261All commands and other requests are handled via access to some (virtual) registers.
262Which are further pointed out in chapter \ref{sec_registers}. The registers space
263is devided into com-registers, which are used to control the communication interface
264itself, like activating automatic messaging or request certain register content,
265and user-registers.
266The address space looks like this
267
268\begin{tabular}{|l|l|}
269\hline
2700x00 & CSTR \\ \hline
2710x01 & CTDR \\ \hline
2720x02 & URNR \\ \hline
2730x03 & URCR \\ \hline
2740x04 & URER \\ \hline
2750x05 & CMDR \\ \hline
2760x06 & CSTR \\ \hline
2770x07 & start of user register address space \\ 
278 ... & ... \\
2790xFF & end of user register address space \\ \hline 
280\end{tabular}\\
281
282The access type may be used by the client to make sure not to accidentally
283alter registers content, which was not itendet to be changed. \\
284
285\textbf{examples:}
286
287\begin{tabular}{ll}
288\verb= 0xF1 0x06 OR   0x02 0xB4=      & set only bit 2 in CSTR register \\
289\verb= 0xF1 0x01 NAND 0x40 0xB4 =   & clear only bit 7 in CTDR register \\
290\verb= 0xF1 0x0A XOR  0xC0 0xB4 =    & toggle only bit 3 and 4 in a user register \\
291\verb= 0xF1 0x00 SET  0x00 0xB4 =    & set the entire CSTR register to zeros \\
292\verb= 0xF1 0x02 READ 0x12 0xB4 =   & read the URNR register \\
293\end{tabular}\\
294
295To encode the different register access types I propose:
296
297\begin{tabular}{|l|l|}
298\hline
299SET  & 0x00 \\ \hline
300NAND & 0x01 \\ \hline
301OR   & 0x02 \\ \hline
302XOR  & 0x03 \\ \hline
303READ & 0x05 \\ \hline
304n/a  & the rest \\ \hline
305\end{tabular}
306
307In case unknown codes are submitted for the access type, the request is discarded.
308the data field, for a READ access is discarded.
309Each of the register access requests, triggers an answer, as long as the
310request response (RR) bit in CPMR is set.
311
312\subsection{server to client}
313Server to client communication on the other hand is meant to be rather informative.
314The client is not only interested whether the last command which was sent, was received
315and successfully executed, but also whether any other system status might have changed
316unforseen.
317Thus the client might be interested in:
318\begin{itemize}
319\item service messages, i.e. messages, which are sent in regular intervals
320\item process messages, i.e. messages, which are sent upon certain events like:
321    \begin{itemize}
322    \item request reception
323    \item successfull command execution
324    \item error occurenaces(?)
325    \end{itemize}
326\end{itemize}
327
328And in addition for the sake of speed, one might consider to define different sizes
329for different messages. While process messages might be rather short, service messages
330might be the entire register content, at least in case one wants to debug something.
331
332\subsubsection{request response}
333    The request response is a special form of a process message.
334    Process message in this context mean, any message send from the server
335    to the client, because something happened.
336    The request response is send back to the client automatically in order
337    to inform it about the reception of the request. The mere request response
338    does not mean, that the associated user command (in case there was one) execution
339    started.
340   
341    The request response protocol might look like this.
342   
343    \begin{tabular}{|l|l|l|}
344    \hline
345    start byte & content & size (byte)\\ \hline
346    0x00 & general header & 1 \\ \hline
347    0x01 & special request response header & 1 \\ \hline
348    0x02 & request counter & 2 byte\\ \hline 
349    0x04 & real time in ms& 4 byte \\ \hline
350    0x08 & address & 1 byte \\ \hline
351    0x09 & data & 1 byte \\ \hline
352    0x0A & crc(?) & 1 byte \\ \hline
353    0x0B & footer & 1 byte \\ \hline
354    \end{tabular}
355   
356    I am not sure what kind of crc I would like to implement or if I should
357    implement one at all, but the experience with the FSC shows ... I should.
358   
359\subsubsection{ process message protocol}
360    A process message can be send, because something happened.
361    I guess in the most cases, the message is send, because the user code started
362    executing a user command, or the user code finished executing a user command.
363    Or in more technical terms,
364    a process message is sent, in case either the user command register (UCR) or the
365    user execution registers(UER) are altered by the user code.
366    In addition a process message is send, in case the FACT++Interface detected an error.
367   
368    So for these process message I propose this protocol
369   
370    \begin{tabular}{|l|l|l|}
371    \hline
372    start byte & content & size (byte)\\ \hline
373    0x00 & general header & 1 \\ \hline
374    0x01 & special process message header & 1 \\ \hline
375    0x02 & real time in ms & 4 byte \\ \hline
376    0x06 & address & 1 byte \\ \hline
377    0x07 & data & 1 byte \\ \hline
378    0x08 & crc(?) & 1 byte \\ \hline
379    0x09 & footer & 1 byte \\ \hline
380    \end{tabular}
381   
382    The address points to the register, which was altered an so caused
383    the sending of this message.
384    The data contains the data of that particular register.
385    I guess counting these messages makes no sense.
386   
387   
388\subsubsection{service message protocol}
389
390    The term service message referes to a form of message that is send in
391    regular time intervals (as regular as possible). These messages are send in
392    order to inform the client about the system status.
393    In addition by monitoring the system status carefully one might be
394    able to track down bugs in the program.
395    So it seems feasible to sent down the entire register content.
396   
397    The protocol I propose is this
398    \begin{tabular}{|l|l|l|}
399    \hline
400    start byte & content & size (byte)\\ \hline
401    0x00 & general header & 1 \\ \hline
402    0x01 & special service message header & 1 \\ \hline
403    0x02 & real time in ms & 4 byte \\ \hline
404    0x07 & com registers & 7 byte \\ \hline
405    0x0E & user registers & URNR byte \\ \hline
406    0x08 & crc(?) & 1 byte \\ \hline
407    0x09 & footer & 1 byte \\ \hline
408    \end{tabular}
409   
410    The length depends on the user code.
411
412
413\section{Registers}
414\label{sec_registers}
415
416The registers are implemented as \\
417\verb=char register[NUMBER_OF_REGISTERS]=.
418There are two types of registers. The com-registers are members of the
419Interface described in this document and the user-registers are entirely
420in the hand of the user code. The interface just gets a pointer to the beginning
421of the user-register space and its size. In addidtion the interface is informed
422which of the user-registers are write-only, read-only and read-write registers.
423I currently do not support 2byte registers, because in case the client wants
424to read a 2byte register, the interface would need to make a copy first,
425to ensure integrity at least to some extend.
426
427\subsection{Com Registers}
428The following com-registers exists
429
430\begin{tabular}{|l|l|l|}
431\hline
432CSTR & R & com status register \\ \hline
433CTDR & R & com time delay register \\ \hline
434CSMR & W & com service message register \\ \hline
435CPMR & R & com process message register \\ \hline
436URNR & R & user register number register \\ \hline
437URCR & R & address of user command register \\ \hline
438URER & R & address of user execution register \\ \hline
439
440\end{tabular}
441
442
443
444\subsubsection{CSTR - com status register(R)}
445    The com status register contains information about the status of the
446    communication interface
447
448    \begin{tabular}{|c|c|c|c|c|c|c|c|}
449    \hline
450    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
451    \multicolumn{3}{|c|}{NWR} & unused & unused & unused& unused& unused \\ \hline
452    \end{tabular}
453   
454\subsubsection{CTDR - com time delay register(R)}
455    The com time delay register can be used, to find out, how much
456    time went by between two consecutive calls of FACT++Interface::com().
457    This might help debugging user code.
458
459    \begin{tabular}{|c|c|c|c|c|c|c|c|}
460    \hline
461    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
462    \multicolumn{8}{|c|}{TIME} \\ \hline
463    \end{tabular}
464
465    TIME is in units of 5ms.
466
467\subsubsection{CSMR - com servive message register(RW)}
468    The com servive message register controls the behaviour of the interface
469    regarding service messages
470
471    \begin{tabular}{|c|c|c|c|c|c|c|c|}
472    \hline
473    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
474    SME & \multicolumn{7}{|c|}{SM\_INT} \\ \hline
475    \end{tabular}
476\\
477details
478
479    \begin{tabular}{|l|l|l|}
480    \hline
481    abbr & description & default value \\ \hline
482    SME & service message enable & 1 \\ \hline
483    SM\_INT & service message interval (unit 0.1 seconds) & 50 \\ \hline
484    \end{tabular}
485
486\subsubsection{CPMR - com process message register(RW)}
487 
488    The com process message register controls the behaviour regarding
489    process messages
490
491    \begin{tabular}{|c|c|c|c|c|c|c|c|}
492    \hline
493    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
494    PME & CRME & CEME & RRME & unused&unused&unused&unused \\ \hline
495    \end{tabular}
496\\
497details
498
499    \begin{tabular}{|l|l|l|}
500    \hline
501    abbr & description & default value \\ \hline
502    PME & process message enable & 1 \\ \hline
503    CRME & command received message enable & 1 \\ \hline
504    CEME & command executed message enable & 1 \\ \hline
505    RRME & request response message enable & 1 \\ \hline
506    \end{tabular}
507
508\subsubsection{URNR - user register number register(R)}
509    The user-register number register stores the number of user registers
510   
511    \begin{tabular}{|c|c|c|c|c|c|c|c|}
512    \hline
513    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
514    \multicolumn{8}{|c|}{number of user registers} \\ \hline
515    \end{tabular}
516
517\subsubsection{URCR - user command register address(R)}
518    The user-register number register stores the address of the user command register
519   
520    \begin{tabular}{|c|c|c|c|c|c|c|c|}
521    \hline
522    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
523    \multicolumn{8}{|c|}{address} \\ \hline
524    \end{tabular}
525
526\subsubsection{URER - user-execute register address(R)}
527    The user-register number register stores the address of the user execute register
528   
529    \begin{tabular}{|c|c|c|c|c|c|c|c|}
530    \hline
531    7 & 6 & 5 & 4 & 3 & 2 & 1 & 0 \\ \hline
532    \multicolumn{8}{|c|}{address} \\ \hline
533    \end{tabular}
534
535
536
537
538\subsection{User Registers}
539The user registers are implemented outside of the scope of the FACT++Interface
540class. When constructed, the class gets a pointer to the beginning and the number
541of user registers.
542
543The User may define special user registers. The \emph{User Command Register} and
544the \emph{User Execution Register}.
545
546\subsubsection{User Command Register - UCR}
547Every User Register can be used to inform the user code, about a request
548by the client. Since the FACT++Interface cannot know, when and if the User code
549starts to react on that command, in cannot inform the client about it.
550
551The special User Command register(UCR) ist monitored by the FACT++interface.
552Assume the client requested to set a bit in the UCR.
553Then the FACT++Interface sets this bit and makes an internal copy of the UCR.
554In each call of FACT++Interface::com() is checked, if the user code changed the UCR.
555In case the bit is cleared the FACT++Interface can inform the client, about the
556starting execution of the requested command.
557
558\subsubsection{User Execute Register- UER}
559The User Execute Register(EUR) is used to inform the FACT++Interface about the
560execution of a command. In this case the client gets a meesage about this,
561and the FACT++Interface cleares the bit, in order to inform the user code
562and get a clean interface again.
563
564
565\section{Usage}
566
567Here I will give an example, which methods should be called when.
568It will look a little bit like this:
569\newpage
570\begin{lstlisting}
571#define NUMBER_OF_REGS 7
572
573byte mac[] = { 0xFA, 0xC7, 0xFC, 0xB1, 0x00, 0x01 };
574EthernetServer server(80);
575
576// this set of registers provides the interface
577// between the FACT++interface class
578// and the user code.
579volatile char register[NUMBER_OF_REGISTERS];
580
581// set up the interface
582FACT++Interface interface(server, register, NUMBER_OF_REGS);
583// enable the sending of service messages
584interface.service_msg(true);
585// set the delay between service messages to 100, i.e. 10sec
586interface.set_service_msg_delay(100);
587
588// inform the interface, that reg[6] & reg[7] serve as
589// command interface between user code and FACT++Interface class
590interface.set_command_register(6,7);
591
592setup(){
593    Ethernet.begin(mac);
594    server.begin();
595    interface.begin();
596}
597
598loop(){
599    // here the ethernet communication takes place
600    // the method is ensured to take <100ms ... or so.
601    interface.com();
602}
603
604// ensured to run every 10ms
605timer_overflow_ISR(){
606
607    // the user code checks certain registers
608    // to find out, if the client send a command
609    if(register[6]&(1<<4)){
610        register[6] &= ~(1<<4); // clear the command bit
611        // other registers can be used, to return values to the client.
612        register[2] = do_someting();
613        register[7] |= 1<<4; // set the execution bit
614    }
615
616    if( !motors_ok() ){
617            stop_motors();
618            register[3] |= 1<<5;
619        }
620    }
621\end{lstlisting}
622
623\section{Implementation}
624
625Here I will explain a little more about certain details of the
626implementation, in case I feel this is needed.
627
628Definitely I will say how the files are named, and how to get them...
629
630
631%\section{Summary}
632
633\end{document}
Note: See TracBrowser for help on using the repository browser.