added tildes before cite and ref

master
Ondřej Hruška 7 years ago
parent f325d9b551
commit d36267a820
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 8
      ch.existing_solutions.tex
  2. 14
      ch.fat16.tex
  3. 14
      ch.freertos.tex
  4. 26
      ch.fw_structure.tex
  5. 4
      ch.gex_units.tex
  6. 30
      ch.hw_buses.tex
  7. 30
      ch.hw_functions.tex
  8. 2
      ch.introduction.tex
  9. 40
      ch.pc_software.tex
  10. 12
      ch.requirement_analysis.tex
  11. 6
      ch.tinyframe.tex
  12. 2
      ch.unit.1wire.tex
  13. 2
      ch.unit.dac.tex
  14. 2
      ch.unit.fcap.tex
  15. 2
      ch.unit.i2c.tex
  16. 2
      ch.unit.npx.tex
  17. 6
      ch.unit.spi.tex
  18. 2
      ch.unit.touch.tex
  19. 2
      ch.unit.usart.tex
  20. 30
      ch.usb.tex
  21. 48
      ch.wireless.tex
  22. 2
      chrisper.py
  23. 12
      formalize2.sh
  24. BIN
      thesis.pdf

@ -30,7 +30,7 @@ The Raspberry Pi could be used for the same quick evaluations or experiments we
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth] {img/buspirate.jpg}
\caption{\label{fig:buspirate}Bus Pirate v.4 (photo taken from \cite{buspirate-product-page})}
\caption{\label{fig:buspirate}Bus Pirate v.4 (photo taken from~\cite{buspirate-product-page})}
\end{figure}
%http://dangerousprototypes.com/blog/about/
@ -44,7 +44,7 @@ The board is based on a PIC16 microcontroller running at 32\,MHz. Its \gls{ADC}
\section{Professional DAQ Modules}
Various professional tools that would fulfill our needs exist on the market, but their high price makes them inaccessible for users with a limited budget, such as hobbyists or students who would like to keep such a device for personal use. An example is the National Instruments \IIC/SPI Interface Device which also includes several \gls{GPIO} lines, their USB DAQ module, or some of the Total Phase \IIC/SPI gadgets (figure \ref{fig:profidaq}).
Various professional tools that would fulfill our needs exist on the market, but their high price makes them inaccessible for users with a limited budget, such as hobbyists or students who would like to keep such a device for personal use. An example is the National Instruments \IIC/SPI Interface Device which also includes several \gls{GPIO} lines, their USB DAQ module, or some of the Total Phase \IIC/SPI gadgets (figure~\ref{fig:profidaq}).
The performance GEX can provide may not always match that of those professional tools, but in many cases it'll be a sufficient substitute at a fraction of the cost.
@ -65,7 +65,7 @@ The performance GEX can provide may not always match that of those professional
\includegraphics[width=.95\linewidth]{img/total-phase-spi-i2c.jpg}
\caption{Total Phase SPI/\IIC Host "Aardwark"}
\end{subfigure}
\caption[Professional tools that GEX can replace]{\label{fig:profidaq}An example of professional tools that GEX could replace in less demanding scenarios \textit{(pictures taken from marketing materials: \cite{nidevice1, nidevice2, tphasedevice})}}
\caption[Professional tools that GEX can replace]{\label{fig:profidaq}An example of professional tools that GEX could replace in less demanding scenarios \textit{(pictures taken from marketing materials:~\cite{nidevice1, nidevice2, tphasedevice})}}
\end{figure}
%http://www.ni.com/en-gb/shop/select/i2c-spi-interface-device}
@ -77,6 +77,6 @@ The performance GEX can provide may not always match that of those professional
Firmata is a communication protocol based on MIDI (\textit{Musical Instrument Digital Interface}) for passing data to and from embedded microcontrollers. MIDI is mainly used for attaching electronic musical instruments, such as synthesizers, keyboards, mixers etc., to each other or to a PC. Firmata was designed for Arduino as a high-level abstraction for its connection to the PC, typically using a FTDI chip or equivalent.
Implementing Firmata in the GEX firmware would make it possible to use existing Firmata libraries on the PC side. However, the protocol is limited by the encompassing MIDI format and is not very flexible.
Implementing Firmata in the GEX firmware would make it possible to use existing Firmata libraries on the PC side. However, the protocol is limited by the encompassing MIDI format and is not very flexible.
\fi

@ -1,6 +1,6 @@
\chapter{The FAT16 File System and Its Emulation} \label{sec:fat16}
A \gls{FS} is used by GEX to provide a comfortable access to the configuration files. By emulating a Mass Storage \gls{USB} device, the module appears as a thumb drive on the host \gls{PC}, and the user can edit its configuration using their preferred text editor. The FAT16 file system was selected for its simplicity and a good cross-platform support \cite{os-support-table}.
A \gls{FS} is used by GEX to provide a comfortable access to the configuration files. By emulating a Mass Storage \gls{USB} device, the module appears as a thumb drive on the host \gls{PC}, and the user can edit its configuration using their preferred text editor. The FAT16 file system was selected for its simplicity and a good cross-platform support~\cite{os-support-table}.
Three variants of the \gls{FAT} file system exist: FAT12, FAT16, and FAT32. FAT12 was used on floppy disks and it is similar to FAT16, except for additional size constraints and a \gls{FAT} entry packing scheme. FAT16 and FAT32 are FAT12's later developments from the time when hard disks became more common and the old addressing scheme could not support their larger capacity.
@ -8,7 +8,7 @@ This chapter will explain the structure of FAT16 and the challenges faced when t
\section{The General Structure of the FAT File System}
An overview will be presented here without going into too many details that would overwhelm the reader and can be looked up elsewhere. Several resources \cite{ms-fat,fat16-brainy,fat16-maverick,fat16-phobos,fat-whitepaper} were consulted during the development of the GEX firmware which provide a more complete description of the FAT16 file system, with \cite{fat-whitepaper}, the Microsoft white paper, giving the most detailed overview.
An overview will be presented here without going into too many details that would overwhelm the reader and can be looked up elsewhere. Several resources~\cite{ms-fat,fat16-brainy,fat16-maverick,fat16-phobos,fat-whitepaper} were consulted during the development of the GEX firmware which provide a more complete description of the FAT16 file system, with~\cite{fat-whitepaper}, the Microsoft white paper, giving the most detailed overview.
The storage medium is organized into \textit{sectors} (or \textit{blocks}), usually 512 bytes long. Those are the smallest addressing unit in the disk structure. The disk starts with a \textit{boot sector}, also called a \gls{MBR}). That is followed by optional reserved sectors, one or two copies of the file allocation table, and the root directory. All disk areas are aligned to a sector boundary:
@ -31,7 +31,7 @@ The storage medium is organized into \textit{sectors} (or \textit{blocks}), usua
\subsection{Boot Sector}
This is a 1-sector structure which holds the \gls{OS} bootstrap code for bootable disks. The first 3 bytes are a jump instruction to the actual bootstrap code located later in the sector. What matters to us when implementing the file system is that the boot sector also contains data fields describing how the disk is organized, what file system is used, who formatted it, etc. The size of the \gls{FAT} and the root directory is defined here. The exact structure of the boot sector can be found in either of \cite{ms-fat,fat16-brainy,fat16-maverick,fat16-phobos,fat-whitepaper} or in the attached GEX source code.
This is a 1-sector structure which holds the \gls{OS} bootstrap code for bootable disks. The first 3 bytes are a jump instruction to the actual bootstrap code located later in the sector. What matters to us when implementing the file system is that the boot sector also contains data fields describing how the disk is organized, what file system is used, who formatted it, etc. The size of the \gls{FAT} and the root directory is defined here. The exact structure of the boot sector can be found in either of~\cite{ms-fat,fat16-brainy,fat16-maverick,fat16-phobos,fat-whitepaper} or in the attached GEX source code.
\subsection{File Allocation Table}
@ -72,7 +72,7 @@ The root directory has the same structure as any other directories, which reside
\caption{\label{tab:fat16-dir-entry}Structure of a FAT16 directory entry}
\end{table}
A directory is organized in 32-byte entries representing individual files. Table \ref{tab:fat16-dir-entry} shows the structure of one such entry. The name and extension fields form together the well-known 8.3 filename format (referring to the byte size of the first two entries). Longer file names are encoded using a \gls{LFN} scheme \cite{fat-lfn} as special hidden entries stored in the directory table alongside the regular 8.3 entries, ensuring backward compatibility.
A directory is organized in 32-byte entries representing individual files. Table~\ref{tab:fat16-dir-entry} shows the structure of one such entry. The name and extension fields form together the well-known 8.3 filename format (referring to the byte size of the first two entries). Longer file names are encoded using a \gls{LFN} scheme~\cite{fat-lfn} as special hidden entries stored in the directory table alongside the regular 8.3 entries, ensuring backward compatibility.
\noindent
The first byte of the file name has a special meaning:
@ -86,7 +86,7 @@ The first byte of the file name has a special meaning:
The attributes field contains flags such as \textit{directory}, \textit{volume label}, \textit{read-only} and \textit{hidden}. Volume label is a special entry in the root directory, which defines the disk's label shown on the host \gls{PC}. A file with the directory bit set is actually a pointer to a subdirectory, meaning that when we open the linked cluster, we'll find a new directory table.
Figure \ref{fig:fat-example} shows a possible organization of the GEX file system with two INI files, one spanning two clusters, the other being entirely inside one. The clusters need not be used completely; an exact file size is stored in the directory entries.
Figure~\ref{fig:fat-example} shows a possible organization of the GEX file system with two INI files, one spanning two clusters, the other being entirely inside one. The clusters need not be used completely; an exact file size is stored in the directory entries.
\begin{figure}[h]
\centering
@ -101,13 +101,13 @@ The FAT16 file system is relatively straightforward to implement. However, it is
\subsection{DAPLink Emulator}
A FAT16 emulator was developed as part of the open-source Arm Mbed DAPLink project \cite{daplink}. It is used there for a drag-and-drop flashing of firmware images to the target microcontroller, taking advantage of the inherent cross-platform support (it uses the same software driver as any thumb drive, as discussed in \ref{sec:msc}). Arm Mbed also uses a browser-based \gls{IDE} and cloud build servers, thus the end user does not need to install or set up any software to program a compatible development kit.
A FAT16 emulator was developed as part of the open-source Arm Mbed DAPLink project~\cite{daplink}. It is used there for a drag-and-drop flashing of firmware images to the target microcontroller, taking advantage of the inherent cross-platform support (it uses the same software driver as any thumb drive, as discussed in~\ref{sec:msc}). Arm Mbed also uses a browser-based \gls{IDE} and cloud build servers, thus the end user does not need to install or set up any software to program a compatible development kit.
The GEX firmware adapts several parts of the DAPLink code, optimizing its \gls{RAM} usage and porting it to work with FreeRTOS. Those modified files are located in the folder \mono{User/vfs} of the GEX source code repository; the original Apache 2.0 open source software license headers, as well as file names, have been retained.
\subsection{Handling a Read Access}
As shown in table \ref{tab:fat16-disk-areas}, the disk consists of several areas. The boot sector is immutable and can be stored in and read from the Flash memory. The handling of the other disk areas (\gls{FAT}, data area) depends on the type of access: read or write.
As shown in table~\ref{tab:fat16-disk-areas}, the disk consists of several areas. The boot sector is immutable and can be stored in and read from the Flash memory. The handling of the other disk areas (\gls{FAT}, data area) depends on the type of access: read or write.
The user can only read files that already exist on the disk, in our case, \verb|UNITS.INI| and \verb|SYSTEM.INI|. Those files are generated from the binary settings storage, and conversely, parsed, line-by-line, without ever existing in their full form. This fact makes our task more challenging, as the files cannot be easily measured and there's no obvious way to read a sector from the middle of a longer file. We solve this by implementing two additional functions in the INI file writer: a \textit{read window} and a \textit{dummy read mode}.

@ -1,6 +1,6 @@
\chapter{FreeRTOS} \label{sec:freertos}
FreeRTOS is a free, open-source real time operating system kernel targeted at embedded systems and ported to many different microcontroller architectures \cite{freertos-ports-list}. FreeRTOS provides the task scheduler, forming the central part of the RTOS, and implements queues, semaphores, and mutexes for message passing and synchronization between concurrent tasks (summarily called synchronization objects\footnote{In this chapter sometimes simply called ``objects''.}). FreeRTOS is compact and designed to be easy to understand; it is written in C, with the exception of some architecture-specific routines which use assembly. A complete overview of the system is available in the FreeRTOS reference manual \cite{freertos-rm} and its guide book \cite{freertos-book}.
FreeRTOS is a free, open-source real time operating system kernel targeted at embedded systems and ported to many different microcontroller architectures~\cite{freertos-ports-list}. FreeRTOS provides the task scheduler, forming the central part of the RTOS, and implements queues, semaphores, and mutexes for message passing and synchronization between concurrent tasks (summarily called synchronization objects\footnote{In this chapter sometimes simply called ``objects''.}). FreeRTOS is compact and designed to be easy to understand; it is written in C, with the exception of some architecture-specific routines which use assembly. A complete overview of the system is available in the FreeRTOS reference manual~\cite{freertos-rm} and its guide book~\cite{freertos-book}.
FreeRTOS is used in GEX for its synchronization objects that make it easy to safely pass messages between interrupts and working threads, without deadlocks or race conditions. The built-in stack overflow protection helps with a more efficient memory allocation, and the heap allocator provided by FreeRTOS enables a thread-safe dynamic allocation with a shared heap.
@ -8,7 +8,7 @@ FreeRTOS is used in GEX for its synchronization objects that make it easy to saf
\subsection{Tasks}
Threads in FreeRTOS are called \textit{tasks}. Each task is assigned a memory area to use as its stack space, and a holding structure with its name, saved \textit{context}, and other metadata used by the kernel. A task context includes the program counter, stack pointer and other register values. Task switching is done by saving and restoring this context by manipulating the values on the stack before leaving and interrupt. The FreeRTOS website provides an example with the AVR port \cite{freertos-task-switching} demonstrating how its internal functionality is implemented, including the context switch.
Threads in FreeRTOS are called \textit{tasks}. Each task is assigned a memory area to use as its stack space, and a holding structure with its name, saved \textit{context}, and other metadata used by the kernel. A task context includes the program counter, stack pointer and other register values. Task switching is done by saving and restoring this context by manipulating the values on the stack before leaving and interrupt. The FreeRTOS website provides an example with the AVR port~\cite{freertos-task-switching} demonstrating how its internal functionality is implemented, including the context switch.
At start-up the firmware initializes the kernel, registers tasks to run and starts the scheduler. From this point onward the scheduler is in control and runs the tasks using a round robin scheme, always giving a task one tick of run time (usually 1\,ms) before interrupting it. Which task should run is primarily determined by their priority numbers, but there are other factors.
@ -20,7 +20,7 @@ Tasks can be in one of four states: Suspended, Ready, Blocked, Running. The Susp
Task switching occurs periodically in a timer interrupt, usually every 1\,ms; in Cortex-M, this is typically the SysTick interrupt, a timer designed for this purpose that is included in the Arm core itself and thus available on all derived platforms.
After one tick of run time, the Running task is paused (enters Ready state), or continues to run if no higher priority task is available. If a higher priority task waits for an object and this is made available in an interrupt, the previously running task is paused and the waiting task is resumed immediately (enters the Running state). FreeRTOS defines an interrupt-friendly variant of some of the \gls{API} functions intended for this purpose.
After one tick of run time, the Running task is paused (enters Ready state), or continues to run if no higher priority task is available. If a higher priority task waits for an object and this is made available in an interrupt, the previously running task is paused and the waiting task is resumed immediately (enters the Running state). FreeRTOS defines an interrupt-friendly variant of some of the \gls{API} functions intended for this purpose.
Only a subset of the FreeRTOS \gls{API} can be accessed from interrupt routines this way, for example it is not possible to use the delay function or wait for an object with a timeout, because the SysTick interrupt, which increments the tick counter, has the lowest priority and could not run. This is by design, to prevent unexpected context switching in application interrupts.
@ -32,11 +32,11 @@ FreeRTOS provides binary and counting semaphores, mutexes and queues. Each of th
\begin{itemize}
\item \textbf{Binary semaphores} can be used for task notifications, e.g. a task waits for a semaphore to be set by an interrupt when a byte is received on the serial port. This makes the task Ready and if it has a higher priority than the previously running task, it is immediately resumed to process the event.
\item \textbf{Counting semaphores} are used to represent available resources. A pool of software or hardware resources is accompanied by a counting semaphore, so that tasks can wait for a resource to become available in the pool and then subtract the semaphore value. After finishing with a resource, the semaphore is incremented again and another task can use it.
\item \textbf{Mutexes} (locks), unlike semaphores, must be taken and released in the same thread (task). They're used to guard exclusive access to a resource, such as writing to a serial port, or accessing a shared memory. When a mutex is taken, a different task which needs to use it enters the Blocked state and is resumed once the mutex becomes available (at which point the task is resumed and simultaneously takes it).
\item \textbf{Queues} are used for passing messages between tasks, or from interrupts to tasks. Both sending and receiving of queue messages can block the task until the operation becomes possible. A queue handing task is often simply a loop which tries to read from the queue with an infinite timeout and processes the received data once the reading succeeds.
\end{itemize}
@ -46,5 +46,5 @@ It must be noted that synchronization objects like mutexes and semaphores can he
Each task in FreeRTOS is assigned a block of \gls{RAM} to use as its stack when it runs. This is where the stack pointer is restored to in the context switch. It can happen that a insufficient stack is exceeded and the stack pointer moves outside the designated area. Without countermeasures this would mean that we are overwriting bytes in some unrelated memory structure, perhaps another task's control block or a stack.
A stack overflow protection can be enabled by a flag in the FreeRTOS configuration file (more details in \cite{freertos-stackov}). This function works in two ways: the more obvious is a simple check that the stack pointer remains in the designated area; however, as the check may be performed only in the scheduler interrupt, it can happen that the stack pointer exceeds the bounds only temporarily and returns back before the stack can be checked for overflow. The stack is thus filled with a known filler value before starting the task, and the last few bytes are then tested to match this value. Not only can we detect a stack overflow more reliably, this feature also makes it possible to estimate the peak stack usage by counting the remaining filler values in the stack area. Naturally, we cannot distinguish between the original filler values and the same value stored on the stack; still, this method proves remarkably successful in the detection of misconfigured stack size.
A stack overflow protection can be enabled by a flag in the FreeRTOS configuration file (more details in~\cite{freertos-stackov}). This function works in two ways: the more obvious is a simple check that the stack pointer remains in the designated area; however, as the check may be performed only in the scheduler interrupt, it can happen that the stack pointer exceeds the bounds only temporarily and returns back before the stack can be checked for overflow. The stack is thus filled with a known filler value before starting the task, and the last few bytes are then tested to match this value. Not only can we detect a stack overflow more reliably, this feature also makes it possible to estimate the peak stack usage by counting the remaining filler values in the stack area. Naturally, we cannot distinguish between the original filler values and the same value stored on the stack; still, this method proves remarkably successful in the detection of misconfigured stack size.

@ -2,13 +2,13 @@
GEX is designed to be modular and easy to extend. It is composed of a set of functional blocks (also called \textit{units}), sometimes available in more than one instance, which can be configured by the user to fit their application needs. The firmware is built around a \textit{core framework} which provides services to the functional blocks, such as a settings storage, resource allocation, message delivery and periodic updates.
In this chapter we will focus on the general function of the GEX module and will look at the services provided by the core framework. Individual functional blocks and the communication protocol will be described in chapters \ref{sec:tinyframe} and \ref{sec:units-overview}.
In this chapter we will focus on the general function of the GEX module and will look at the services provided by the core framework. Individual functional blocks and the communication protocol will be described in chapters~\ref{sec:tinyframe} and~\ref{sec:units-overview}.
\iffalse
This and the following parts were written after implementing and evaluating the first hardware prototype and its firmware, therefore rather than describing the development process, it tends to talk about the completed solution and the decisions taken.
\fi
\section{User's View of GEX}
\section{User's View of GEX}
Before going into implementation details, we'll have a look at GEX from the outside, how the end user will see it. This should give the reader some context to better orient themselves in the following sections and chapters investigating the internal structure of the firmware and the communication protocol.
@ -22,14 +22,14 @@ The GEX firmware can be flashed to a STM32 Nucleo or Discovery board or a custom
After powering on, GEX loads its configuration from the Flash memory, configures its peripherals, sets up the function blocks and enables the selected communication interface(s). From this point, the module is operational and can be configured or used as needed by the user.
The physical user interface of the module is shown in figure \ref{fig:users-view-of-gex}. When a \gls{USB} cable connects the board to a \gls{PC}, the \gls{PC} \gls{OS} enumerates it and either recognizes the communication interface as \gls{CDCACM} (Virtual serial port), or leaves it without a software driver attached, to be accessed directly as raw \gls{USB} endpoints, based on GEX settings.
The physical user interface of the module is shown in figure~\ref{fig:users-view-of-gex}. When a \gls{USB} cable connects the board to a \gls{PC}, the \gls{PC} \gls{OS} enumerates it and either recognizes the communication interface as \gls{CDCACM} (Virtual serial port), or leaves it without a software driver attached, to be accessed directly as raw \gls{USB} endpoints, based on GEX settings.
The connection using a physical UART and a USB/UART adapter works in a very similar way, as does the wireless connection (described in more detail below).
\subsection{Updating GEX Settings}
Two ways exist in which the module's settings can be modified: via the virtual Mass Storage disk, and through the control interface. We'll look at the file system method here; the API for a programmatic loading and updating of configuration will be explained in section \ref{sec:tf-bulk-rw}.
Two ways exist in which the module's settings can be modified: via the virtual Mass Storage disk, and through the control interface. We'll look at the file system method here; the API for a programmatic loading and updating of configuration will be explained in section~\ref{sec:tf-bulk-rw}.
The board is equipped with a button or a jumper labeled Lock. When the button is pressed or the jumper removed (or inserted, the polarity is configured in the firmware), the Mass Storage \gls{USB} interface is enabled. For the user, this means that a new disk will appear on their computer which they can open in a file manager. The disk provides a read/write access to configuration files.
The board is equipped with a button or a jumper labeled Lock. When the button is pressed or the jumper removed (or inserted, the polarity is configured in the firmware), the Mass Storage \gls{USB} interface is enabled. For the user, this means that a new disk will appear on their computer which they can open in a file manager. The disk provides a read/write access to configuration files.
The user edits a file as needed and saves it back to the disk. GEX processes the new content, tries to apply the changes and generates an updated version that includes any error messages or newly generated sections (when a new unit was registered). For the \gls{PC} \gls{OS} to recognize this change, the Mass Storage device momentarily reports that the media is unavailable to force the \gls{OS} to reload it. This is a similar mechanism to what happens when a memory card is removed from a reader. Now the user can reload the file in their editor, inspect the updated content and correct any possible mistakes. The settings, when applied successfully, should be immediately available to test using the communication interface. When everything is to the user's satisfaction, the updated settings are committed to the device's Flash memory by pressing the LOCK button again, or replacing the jumper.
@ -45,7 +45,7 @@ Now that GEX is connected and configured, the user can start using it. This invo
\section{Internal Structure Block Diagram}
The data flows and other internal logic of the firmware are depicted in figure \ref{fig:gex-internal}, with more explanation following in this chapter. The interchangeable role of the three communication interfaces can be clearly seen in the diagram, as well as the central role of the message queue which decouples interrupts from the processing thread.
The data flows and other internal logic of the firmware are depicted in figure~\ref{fig:gex-internal}, with more explanation following in this chapter. The interchangeable role of the three communication interfaces can be clearly seen in the diagram, as well as the central role of the message queue which decouples interrupts from the processing thread.
\begin{figure}[h]
\centering
@ -59,11 +59,11 @@ The firmware is built on FreeRTOS (\ref{sec:freertos}) and a number of its synch
\subsection{Message and Job Queue}
The message and job queue, seen in figure \ref{fig:gex-internal}, is used to decouple asynchronous interrupts from message transmission. All three communication interfaces use interrupts for the asynchronous handling of incoming messages. The same interrupt handler receives an event after a transmission was completed. The queue ensures that messages can be received during the transmission of a large response that demands the use of multiple transmissions.
The message and job queue, seen in figure~\ref{fig:gex-internal}, is used to decouple asynchronous interrupts from message transmission. All three communication interfaces use interrupts for the asynchronous handling of incoming messages. The same interrupt handler receives an event after a transmission was completed. The queue ensures that messages can be received during the transmission of a large response that demands the use of multiple transmissions.
The ``transmission complete'' interrupt signals this fact to the message processing task using a binary semaphore. The semaphore is released in the interrupt and take before a new block of data is transmitted. If more data needs to be transmitted, the queue task waits on the semaphore and enters a Blocked state until the semaphore becomes available again.
Two mutexes are used in the firmware: one that guards access to TinyFrame until the previous message was fully transmitted, and one to guard a shared memory buffer used, among other, by unit drivers during the serialization and parsing of a configuration file. The hardware resource registry (explained in \ref{sec:res-allocation}) does not need mutexes for individual resources, as a concurrent access to those fields can never happen thanks to the way the system is organized.
Two mutexes are used in the firmware: one that guards access to TinyFrame until the previous message was fully transmitted, and one to guard a shared memory buffer used, among other, by unit drivers during the serialization and parsing of a configuration file. The hardware resource registry (explained in~\ref{sec:res-allocation}) does not need mutexes for individual resources, as a concurrent access to those fields can never happen thanks to the way the system is organized.
\section{Functional Blocks} \label{sec:units-function}
@ -118,7 +118,7 @@ The unit driver handles commands sent from the host \gls{PC}, initializes and de
\caption{\label{fig:repo-structure} The general structure of the source code repository}
\end{wrapfigure}
Looking at the source code repository (fig. \ref{fig:repo-structure}), at the root we'll find the device specific driver libraries and support files provided by ST Microelectronics, the FreeRTOS middleware, and a folder called \verb|User| containing the GEX application code. This division is useful when porting the firmware to a different microcontroller, as the GEX folder is mostly platform-independent and can be simply copied (of course, adjustments are needed to accompany different hardware peripheral versions etc.). The GEX core framework consists of everything in the \verb|User| folder, excluding the \verb|units| directory in which the individual units are implemented. Each unit driver must be registered in the file \verb|platform.c| to be available for the user to select. The file \verb|plat_compat.c| includes platform-specific headers and defines e.g. which pin to use for a status \gls{LED} or the LOCK button.
Looking at the source code repository (fig.~\ref{fig:repo-structure}), at the root we'll find the device specific driver libraries and support files provided by ST Microelectronics, the FreeRTOS middleware, and a folder called \verb|User| containing the GEX application code. This division is useful when porting the firmware to a different microcontroller, as the GEX folder is mostly platform-independent and can be simply copied (of course, adjustments are needed to accompany different hardware peripheral versions etc.). The GEX core framework consists of everything in the \verb|User| folder, excluding the \verb|units| directory in which the individual units are implemented. Each unit driver must be registered in the file \verb|platform.c| to be available for the user to select. The file \verb|plat_compat.c| includes platform-specific headers and defines e.g. which pin to use for a status \gls{LED} or the LOCK button.
The \gls{USB} Device library, which had to be modified to support a composite class, is stored inside the \verb|User| folder too, as it is compatible with all STM32 microcontrollers that support \gls{USB}.
@ -150,7 +150,7 @@ When the firmware needs to be ported to a different STM32 microcontroller, the c
The microcontroller provides a number of hardware resources that require exclusive access: GPIO pins, peripheral blocks (\gls{SPI}, \gls{I2C}, \gls{UART}\textellipsis), \gls{DMA} channels. If two units tried to control the same pin, the results would be unpredictable; similarly, with a multiple access to a serial port, the output would be a mix of the data streams and completely useless.
To prevent a multiple access, the firmware includes a \textit{resource registry} (fig. \ref{fig:resource-repository}). Each individual resource is represented by a field in a resource table together with its owner's callsign. Initially all resources are free, except for those not available on the particular platform (i.e. a GPIO pin PD1 may be disabled if not present on the microcontroller's package).
To prevent a multiple access, the firmware includes a \textit{resource registry} (fig.~\ref{fig:resource-repository}). Each individual resource is represented by a field in a resource table together with its owner's callsign. Initially all resources are free, except for those not available on the particular platform (i.e. a GPIO pin PD1 may be disabled if not present on the microcontroller's package).
The resources used by the core framework are taken by a virtual unit \verb|SYSTEM| on start-up to prevent conflicts with the user's units. This is the case of the status \gls{LED}, the LOCK button, \gls{USB} pins, the communication \gls{UART}, the pins and an \gls{SPI} peripheral connecting the wireless module, pins used for the crystal oscillator, and the timer/counter which provides the system timebase.
@ -189,13 +189,13 @@ This is identical to the \gls{USB} connection from the \gls{PC} application's si
The wireless connection uses an on-board communication module and a separate device, a wireless gateway, that connects to the \gls{PC}. The wireless gateway is interfaced differently from the GEX board itself, but it also shows as a virtual serial port on the host \gls{PC}. This is required to allow communicating with the gateway itself through the \gls{CDCACM} interface in addition to addressing the end devices.
This interface will be explained in more detail in chapter \ref{sec:wireless}.
This interface will be explained in more detail in chapter~\ref{sec:wireless}.
\subsection{Message Passing} \label{sec:message_passing}
One of the key functions of the core framework is to deliver messages from the host \gls{PC} to the right units. This functionality resides above the framing protocol, which will be described in chapter \ref{sec:tinyframe}.
One of the key functions of the core framework is to deliver messages from the host \gls{PC} to the right units. This functionality resides above the framing protocol, which will be described in chapter~\ref{sec:tinyframe}.
A message that is not a response in a multi-part session (this is handled by the framing library) is identified by its Type field. Two main groups of messages exist: \textit{system messages} and \textit{unit messages}. System messages can access the INI files, query a list of the available units, restart the module etc. Unit messages are addressed to a particular unit by their callsign (see \ref{sec:units-function}), and their payload format is defined by the unit driver. The framework reads the message type, then the callsign byte, and tries to find a matching unit in the unit list. If no unit with the callsign is found, an error response is sent back, otherwise the unit driver is given the message to handle it as required.
A message that is not a response in a multi-part session (this is handled by the framing library) is identified by its Type field. Two main groups of messages exist: \textit{system messages} and \textit{unit messages}. System messages can access the INI files, query a list of the available units, restart the module etc. Unit messages are addressed to a particular unit by their callsign (see~\ref{sec:units-function}), and their payload format is defined by the unit driver. The framework reads the message type, then the callsign byte, and tries to find a matching unit in the unit list. If no unit with the callsign is found, an error response is sent back, otherwise the unit driver is given the message to handle it as required.
The framework provides one more messaging service to the units: event reporting. An asynchronous event, such as an external interrupt, an \gls{ADC} trigger or an \gls{UART} data reception needs to be reported to the host. This message is annotated by the unit callsign so the user application knows its origin.

@ -2,7 +2,7 @@
This chapter describes all functional blocks (units) implemented in GEX, version 1.0. The term ``unit'' will be used here to refer to both unit types (drivers) or their instances where the distinction is not important.
Each unit's description will be accompanied by a corresponding snippet from the configuration file, and a list of supported commands and events. The commands and events described here form the payload of TinyFrame messages 0x10 (Unit Request) and 0x11 (Unit Report), as described in section \ref{sec:unit_requests_reports}.
Each unit's description will be accompanied by a corresponding snippet from the configuration file, and a list of supported commands and events. The commands and events described here form the payload of TinyFrame messages 0x10 (Unit Request) and 0x11 (Unit Report), as described in section~\ref{sec:unit_requests_reports}.
The number in the first column of the command (or event) tables, marked as ``Code'', is the command number (or report type) used in the payload to identify how the message data should be treated. When the request or response payload is empty, it is omitted from the table. The same applies to commands with no response, in which case adding 0x80 to the command number triggers a SUCCESS response after the command is finished.
@ -20,7 +20,7 @@ Several units facilitate an access to a group of GPIO pins, such as the digital
\caption{\label{fig:pin-packing}Pin packing}
\end{figure}
For instance, we could only have the pins 0, 1, 12--15 available on a \gls{GPIO} port. GEX provides a helpful abstraction to bridge the gaps in the port: The selected pins are packed together and represented, in commands and events, as a block of six pins (0x3F) instead of their original positions in the register (0xF003). This scheme is shown in figure \ref{fig:pin-packing}. The translation is done in the unit driver and works transparently, as if the block of pins had no gaps---all the referenced pins are updated simultaneously without glitches. Where pin numbers are used, the order in the packed word should be provided---in our example, that would be 0--5, counting from the least significant bit.
For instance, we could only have the pins 0, 1, 12--15 available on a \gls{GPIO} port. GEX provides a helpful abstraction to bridge the gaps in the port: The selected pins are packed together and represented, in commands and events, as a block of six pins (0x3F) instead of their original positions in the register (0xF003). This scheme is shown in figure~\ref{fig:pin-packing}. The translation is done in the unit driver and works transparently, as if the block of pins had no gaps---all the referenced pins are updated simultaneously without glitches. Where pin numbers are used, the order in the packed word should be provided---in our example, that would be 0--5, counting from the least significant bit.
% here are the unit sections, all following a common pattern
\input{ch.unit.do}

@ -14,9 +14,9 @@ The \acrfull{USART} has a long history and is still in widespread use today. It
\gls{UART} and \gls{USART} are two variants of the same interface. \gls{USART} includes a separate clock signal, while the \gls{UART} timing relies on a well-known clock speed and the bit clock is synchronized by start bits. \gls{USART} was historically used in modems to achieve higher bandwidth, but is now mostly obsolete.
\gls{USART}, as implemented by microcontrollers such as the STM32 family, is a two-wire full duplex interface that uses 3.3\,V or 5\,V logic levels. The data lines are in the high logical level when idle. An \gls{USART} frame, shown in figure \ref{fig:uart-frame}, starts by a start-bit (low level for the period of one bit) followed by \textit{n} data bits (typically eight), an optional parity bit and a period of high level called a stop bit (or stop bits), dividing consecutive frames.
\gls{USART}, as implemented by microcontrollers such as the STM32 family, is a two-wire full duplex interface that uses 3.3\,V or 5\,V logic levels. The data lines are in the high logical level when idle. An \gls{USART} frame, shown in figure~\ref{fig:uart-frame}, starts by a start-bit (low level for the period of one bit) followed by \textit{n} data bits (typically eight), an optional parity bit and a period of high level called a stop bit (or stop bits), dividing consecutive frames.
RS-232 uses the \gls{UART} framing, but its levels are different: logical 1 is represented by negative voltages $-3$ to $-25$\,V and logical 0 uses the same range, but positive. To convert between RS232 levels and \gls{TTL} (5\,V) levels, a level-shifting circuit such as the MAX232 can be used. In RS-232, the two data lines (Rx and Tx) are accompanied by \gls{RTS}, \gls{CTS}, and \gls{DTR}, which facilitate handshaking and hardware flow control. In practice, those additional signals are often unused or their function differs from their historical meaning; for instance, Arduino boards (using a USB-serial converter) use the \gls{DTR} line as a reset signal to automatically enter their bootloader for firmware flashing \cite{arduinodtr}.
RS-232 uses the \gls{UART} framing, but its levels are different: logical 1 is represented by negative voltages $-3$ to $-25$\,V and logical 0 uses the same range, but positive. To convert between RS232 levels and \gls{TTL} (5\,V) levels, a level-shifting circuit such as the MAX232 can be used. In RS-232, the two data lines (Rx and Tx) are accompanied by \gls{RTS}, \gls{CTS}, and \gls{DTR}, which facilitate handshaking and hardware flow control. In practice, those additional signals are often unused or their function differs from their historical meaning; for instance, Arduino boards (using a USB-serial converter) use the \gls{DTR} line as a reset signal to automatically enter their bootloader for firmware flashing~\cite{arduinodtr}.
\subsection{Examples of Devices Using UART}
@ -29,7 +29,7 @@ RS-232 uses the \gls{UART} framing, but its levels are different: logical 1 is r
\section{SPI} \label{sec:theory-spi}
\acrfull{SPI} is a point-to-point or multi-drop master-slave interface based on shift registers. The \gls{SPI} connection with multiple slave devices is depicted in figure \ref{fig:spi-multislave}. It uses at least 4 wires: \gls{SCK}, \gls{MOSI}, \gls{MISO} and \gls{SS}. \gls{SS} is often marked \gls{CSB} or \gls{NSS} to indicate that its active state is 0. Slave devices are addressed using their \gls{SS} input while the data connections are shared. A slave that's not addressed releases the \gls{MISO} line to a high impedance state so it doesn't interfere in ongoing communication.
\acrfull{SPI} is a point-to-point or multi-drop master-slave interface based on shift registers. The \gls{SPI} connection with multiple slave devices is depicted in figure~\ref{fig:spi-multislave}. It uses at least 4 wires: \gls{SCK}, \gls{MOSI}, \gls{MISO} and \gls{SS}. \gls{SS} is often marked \gls{CSB} or \gls{NSS} to indicate that its active state is 0. Slave devices are addressed using their \gls{SS} input while the data connections are shared. A slave that's not addressed releases the \gls{MISO} line to a high impedance state so it doesn't interfere in ongoing communication.
\begin{figure}[h]
\centering
@ -43,7 +43,7 @@ RS-232 uses the \gls{UART} framing, but its levels are different: logical 1 is r
\caption[SPI master with multiple slaves]{\label{fig:spi-multislave}A SPI bus with 1 master and 3 slaves, each enabled by its own Slave Select signal}
\end{figure}
Transmission and reception on the \gls{SPI} bus happen simultaneously. A bus master asserts the \gls{SS} pin of a slave it wishes to address and then sends data on the \gls{MOSI} line while receiving a response on \gls{MISO}. The slave normally responds with 0x00 or a status register as the first byte of the response, before it can process the received command. A timing diagram is shown in figure \ref{fig:spi-timing}, including two configurable parameters: \gls{CPOL} and \gls{CPHA}.
Transmission and reception on the \gls{SPI} bus happen simultaneously. A bus master asserts the \gls{SS} pin of a slave it wishes to address and then sends data on the \gls{MOSI} line while receiving a response on \gls{MISO}. The slave normally responds with 0x00 or a status register as the first byte of the response, before it can process the received command. A timing diagram is shown in figure~\ref{fig:spi-timing}, including two configurable parameters: \gls{CPOL} and \gls{CPHA}.
\gls{SPI} devices often provide a number of control, configuration and status registers that can be read and written by the bus master. The first byte of a command usually contains one bit that determines if it is a read or write access, and an address field selecting the target register. The slave then either stores the following \gls{MOSI} byte(s) into the register, or sends its content back on \gls{MISO} (or both simultaneously).
@ -60,27 +60,27 @@ Transmission and reception on the \gls{SPI} bus happen simultaneously. A bus mas
\item \textbf{L6470} - intelligent stepper motor driver
\item \textbf{AD9833} - waveform generator (\gls{MOSI} only)
\item \textbf{ADE7912} - triple $\Sigma$-$\Delta$ \gls{ADC} for power metering applications
\item \textbf{SD cards} \cite{sd-spec}
\item \textbf{SD cards}~\cite{sd-spec}
\item SPI-interfaced EEPROM and Flash memories
\end{itemize}
\section{I\textsuperscript{2}C} \label{sec:theory-i2c}
\acrfull{I2C} is a two-wire, open-drain bus that supports multi-master operation.
It uses two connections (plus \gls{GND}): \gls{SDA} and \gls{SCL}, both open-drain with a pull-up resistor.
\acrfull{I2C} is a two-wire, open-drain bus that supports multi-master operation.
It uses two connections (plus \gls{GND}): \gls{SDA} and \gls{SCL}, both open-drain with a pull-up resistor.
The protocol was developed by Philips Semiconductor (now NXP Semiconductors) and its implementors were required to pay licensing fees, until 2006, leading to the development of compatible implementations with different names, such as Atmel's \gls{TWI} or Dallas Semiconductor's ``Serial 2-wire Interface'' (e.g. used in the DS1307 \gls{RTC} chip). \gls{I2C} is a basis of the \gls{SMBus} and \gls{PMBus}, which add additional constraints and rules for a more robust operation.
The frame format is shown and explained in figure \ref{fig:i2c-frame}; more details may be found in the specification \cite{i2c-spec} or application notes and datasheets offered by chip vendors, such as the white paper from Texas Instruments \cite{understanding-i2c}. A frame starts with a start condition and stops with a stop condition, defined by an \gls{SDA} edge while the \gls{SCL} is high. The address and data bytes are acknowledged by the slave by sending a 0 on the open-drain \gls{SDA} line in the following clock cycle. A slave can terminate the transaction by sending 1 in place of the acknowledge bit. Slow slave devices may stop the master from sending more data by holding the SCL line low at the end of a byte, a feature called \textit{Clock Stretching}. As the bus is open-drain, the line cannot go high until all participants release it.
The frame format is shown and explained in figure~\ref{fig:i2c-frame}; more details may be found in the specification~\cite{i2c-spec} or application notes and datasheets offered by chip vendors, such as the white paper from Texas Instruments~\cite{understanding-i2c}. A frame starts with a start condition and stops with a stop condition, defined by an \gls{SDA} edge while the \gls{SCL} is high. The address and data bytes are acknowledged by the slave by sending a 0 on the open-drain \gls{SDA} line in the following clock cycle. A slave can terminate the transaction by sending 1 in place of the acknowledge bit. Slow slave devices may stop the master from sending more data by holding the SCL line low at the end of a byte, a feature called \textit{Clock Stretching}. As the bus is open-drain, the line cannot go high until all participants release it.
Two addressing modes are defined: 7-bit and 10-bit. Due to the small address space, exacerbated by many devices implementing only the 7-bit addressing, collisions between different chips on a shared bus are common; many devices thus offer several pins to let the board designer choose a few bits of the address by connecting them to different logic levels.
Two addressing modes are defined: 7-bit and 10-bit. Due to the small address space, exacerbated by many devices implementing only the 7-bit addressing, collisions between different chips on a shared bus are common; many devices thus offer several pins to let the board designer choose a few bits of the address by connecting them to different logic levels.
The bus supports multi-master operation, which leads to the problem of collisions. Multi-master capable devices must implement a bus arbitration scheme as specified by the \gls{I2C} standard \cite{i2c-spec}. This feature is not used often in intelligent sensors and modules; the most common topology is multi-drop single-master, similar to \gls{SPI}, with the advantage of using only two pins on the microcontroller.
The bus supports multi-master operation, which leads to the problem of collisions. Multi-master capable devices must implement a bus arbitration scheme as specified by the \gls{I2C} standard~\cite{i2c-spec}. This feature is not used often in intelligent sensors and modules; the most common topology is multi-drop single-master, similar to \gls{SPI}, with the advantage of using only two pins on the microcontroller.
\begin{figure}[h]
\centering
\includegraphics[width=.9\textwidth] {img/i2c-frame.png}
\caption[\IIC message diagram]{\label{fig:i2c-frame}An \gls{I2C} message diagram (\textit{taken from the \gls{I2C} specification \cite{i2c-spec}})}
\caption[\IIC message diagram]{\label{fig:i2c-frame}An \gls{I2C} message diagram (\textit{taken from the \gls{I2C} specification~\cite{i2c-spec}})}
\end{figure}
\subsection{Examples of Devices Using \IIC}
@ -99,7 +99,7 @@ The 1-Wire bus, developed by Dallas Semiconductor (acquired by Maxim Integrated)
1-Wire uses an open-drain connection for the data line, similar to \gls{I2C}, though the protocol demands it to be connected directly to V$_dd$ in some places when the parasitic mode is used; this is accomplished using an external transistor, or by reconfiguring the GPIO pin as output and setting it to 1, provided the microcontroller is able to supply a sufficient current.
The communication consists of short pulses sent by the master and (for bit reading) the line continuing to be held low by the slave for a defined amount of time. The pulse timing determines whether it is a read or write operation and which value is encoded. It can be implemented either in software as delay loops, or by abusing \gls{UART} peripheral, as explained in \cite{ow-uart}. Detailed timing diagrams can be found in the DS18x20 \cite{ow-datasheet}. 1-Wire transactions include a checksum byte to ensure an error-free communication.
The communication consists of short pulses sent by the master and (for bit reading) the line continuing to be held low by the slave for a defined amount of time. The pulse timing determines whether it is a read or write operation and which value is encoded. It can be implemented either in software as delay loops, or by abusing \gls{UART} peripheral, as explained in~\cite{ow-uart}. Detailed timing diagrams can be found in the DS18x20~\cite{ow-datasheet}. 1-Wire transactions include a checksum byte to ensure an error-free communication.
\begin{figure}[h]
\centering
@ -107,7 +107,7 @@ The communication consists of short pulses sent by the master and (for bit readi
\caption{\label{fig:1w-topology}1-Wire connection topology with four slave devices}
\end{figure}
Devices are addressed by their unique 64-bit ID numbers called ROM codes or ROMs; they can be found by the bus master, with a cooperation from slaves, using a ROM Search algorithm. The search algorithm is explained in \cite{ow-appnote}, including a possible implementation example. If only one device is connected, a wild card command Skip ROM can be used to address the device without a known ROM code.
Devices are addressed by their unique 64-bit ID numbers called ROM codes or ROMs; they can be found by the bus master, with a cooperation from slaves, using a ROM Search algorithm. The search algorithm is explained in~\cite{ow-appnote}, including a possible implementation example. If only one device is connected, a wild card command Skip ROM can be used to address the device without a known ROM code.
\subsection{Examples of Devices Using 1-Wire}
@ -130,9 +130,9 @@ Since 1-Wire is a proprietary protocol, there is a much smaller choice of availa
\section{NeoPixel} \label{sec:theory-neo}
NeoPixel is a marketing name of the \textbf{WS2812} and compatible intelligent \gls{LED} drivers that are commonly used in ``addressable \gls{LED} strips''. Additional technical details about the chips and their protocol may be found in the WS2812B datasheet \cite{neopixel-ds}. Those chips include the control logic, PWM drivers and the \gls{LED} diodes all in one 5$\times$5\,mm SMD package.
NeoPixel is a marketing name of the \textbf{WS2812} and compatible intelligent \gls{LED} drivers that are commonly used in ``addressable \gls{LED} strips''. Additional technical details about the chips and their protocol may be found in the WS2812B datasheet~\cite{neopixel-ds}. Those chips include the control logic, PWM drivers and the \gls{LED} diodes all in one 5$\times$5\,mm SMD package.
The NeoPixel protocol is unidirectional, using only one data pin. The \gls{LED} drivers are chained together. Ones and zeros are encoded by pulses of a defined length on the data pin; after the color data was loaded into the \gls{LED} string, a longer "reset" pulse (low level) is issued by the bus master and the set colors are displayed. The timing constraints are listed in table \ref{fig:ws2812-dia}.
The NeoPixel protocol is unidirectional, using only one data pin. The \gls{LED} drivers are chained together. Ones and zeros are encoded by pulses of a defined length on the data pin; after the color data was loaded into the \gls{LED} string, a longer "reset" pulse (low level) is issued by the bus master and the set colors are displayed. The timing constraints are listed in table~\ref{fig:ws2812-dia}.
The NeoPixel timing is sensitive to pulse length accuracy; a deviation from the specified timing may cause the data to be misinterpreted by the drivers. Some ways to implement the timing use hardware timers or the \gls{I2S} peripheral. An easier method that does not require any additional hardware resources beyond the \gls{GPIO} pin is to implement the timing using delay loops in the firmware; care must be taken to disable interrupts in the sensitive parts of the timing; it may be advantageous to implement it in assembly for a tighter control.

@ -1,22 +1,22 @@
\chapter{Non-communication Hardware Functions}
In addition to communication buses, described in chapter \ref{ch:hw_buses}, GEX implements several measurement and output functions that take advantage of the microcontroller's peripheral blocks, such as timers/counters and \gls{DAC}. The more complicated ones are described here; simpler functions, such as the raw \gls{GPIO} access, will be described later together with their control \gls{API}.
In addition to communication buses, described in chapter~\ref{ch:hw_buses}, GEX implements several measurement and output functions that take advantage of the microcontroller's peripheral blocks, such as timers/counters and \gls{DAC}. The more complicated ones are described here; simpler functions, such as the raw \gls{GPIO} access, will be described later together with their control \gls{API}.
\section{Frequency Measurement} \label{sec:theory-fcap}
Applications like motor speed measurement and the reading of a \gls{VCO} or \gls{VCO}-based sensor's output demand a tool capable of measuring frequency. This can be done using a laboratory instrument such as the Agilent 53131A. A low-cost solution can be realized using a timer/counter peripheral of a microcontroller.
\noindent
Two basic methods to measure frequency exist \cite{fcap-twotypes}, each with its advantages and drawbacks:
Two basic methods to measure frequency exist~\cite{fcap-twotypes}, each with its advantages and drawbacks:
\begin{itemize}
\item The \textit{direct method} (fig. \ref{fig:fcap-direct-dia}) is based on the definition of frequency as a number of cycles $n$ in a fixed-length time window $\tau$ (usually 1\,s); the frequency is then calculated as $f=n/\tau$.
\item The \textit{direct method} (fig.~\ref{fig:fcap-direct-dia}) is based on the definition of frequency as a number of cycles $n$ in a fixed-length time window $\tau$ (usually 1\,s); the frequency is then calculated as $f=n/\tau$.
One timer generates the time window and its output gates the input of another, configured as a pulse counter. At the end of the measurement window an interrupt is generated and we can read the pulse count from the counter's register.
The direct method has a resolution of 1\,Hz with a sampling window of 1\,s (only a whole number of pulses can me counted). The resolution can be increased by using a longer time window, provided the measured signal is stable enough to make averaging possible without distorting the result. Further increase of precision is possible through analog or digital interpolation \cite{fcap-increasing}, a method used in some professional equipment.
The direct method has a resolution of 1\,Hz with a sampling window of 1\,s (only a whole number of pulses can me counted). The resolution can be increased by using a longer time window, provided the measured signal is stable enough to make averaging possible without distorting the result. Further increase of precision is possible through analog or digital interpolation~\cite{fcap-increasing}, a method used in some professional equipment.
\item The \textit{indirect} or \textit{reciprocal method} (fig. \ref{fig:fcap-reci-dia}) measures one period $T$ as the time interval between two pulses and this is then converted to frequency as $f=1/T$.
\item The \textit{indirect} or \textit{reciprocal method} (fig.~\ref{fig:fcap-reci-dia}) measures one period $T$ as the time interval between two pulses and this is then converted to frequency as $f=1/T$.
This method needs only one timer/counter. Cycles of the system clock are counted for the duration of one period on the input pin (between two rising edges). If we additionally detect the falling edge in between, the counter's value gives us the duty cycle when related to the overall period length.
@ -38,7 +38,7 @@ Two basic methods to measure frequency exist \cite{fcap-twotypes}, each with its
\caption{\label{fig:fcap-reci-dia}Reciprocal frequency measurement method}
\end{figure}
Which method to use depends on the frequency we want to measure; the worst-case measurement errors of both methods, assuming an ideal 48\,MHz system clock, are plotted in figure \ref{fig:freqmethods-graph}. It can be seen that the reciprocal method leads in performance up to 7\,kHz where the direct method overtakes it. If a higher error is acceptable, the reciprocal method could be used also for higher frequencies to avoid a reconfiguration and to take advantage of its higher speed.
Which method to use depends on the frequency we want to measure; the worst-case measurement errors of both methods, assuming an ideal 48\,MHz system clock, are plotted in figure~\ref{fig:freqmethods-graph}. It can be seen that the reciprocal method leads in performance up to 7\,kHz where the direct method overtakes it. If a higher error is acceptable, the reciprocal method could be used also for higher frequencies to avoid a reconfiguration and to take advantage of its higher speed.
\begin{figure}[h]
\centering
@ -46,7 +46,7 @@ Which method to use depends on the frequency we want to measure; the worst-case
\caption[Frequency measurement methods comparison]{\label{fig:freqmethods-graph}Worst-case error using the two frequency measurement methods with an ideal 48\,MHz timer clock. The crossing lies at 7\,kHz with an error of 0.015\,\%, or 1.05\,Hz.}
\end{figure}
A good approach to a universal measurement, for cases where we do not know the expected frequency beforehand, could be to obtain an estimate using the direct method first, and if the frequency is below the worst-case error crossing point (here 7\,kHz, according to figure \ref{fig:freqmethods-graph}), to take a more precise measurement using the reciprocal method.
A good approach to a universal measurement, for cases where we do not know the expected frequency beforehand, could be to obtain an estimate using the direct method first, and if the frequency is below the worst-case error crossing point (here 7\,kHz, according to figure~\ref{fig:freqmethods-graph}), to take a more precise measurement using the reciprocal method.
The system clock's frequency, which we use to measure pulse lengths and to gate the pulse counter, will be affected by tolerances of the used components, the layout of the \gls{PCB}, temperature effects etc., causing measurement errors. A higher accuracy could be achieved using a \gls{TCO}, or, in the direct method, with the synchronization pulse provided by a \gls{GPS} receiver to time the measurement interval.
@ -62,9 +62,9 @@ A very common need in experiments involving the measurement of physical properti
\caption{\label{fig:adc-sar}A diagram of the SAR type ADC}
\end{figure}
The \gls{ADC} type commonly available in microcontrollers, including our STM32F072, uses a \textit{successive approximation} method. It is called the \textit{SAR type \gls{ADC}}, after its main component, the \gls{SAR}. A diagram of this \gls{ADC} is shown in figure \ref{fig:adc-sar}.
The \gls{ADC} type commonly available in microcontrollers, including our STM32F072, uses a \textit{successive approximation} method. It is called the \textit{SAR type \gls{ADC}}, after its main component, the \gls{SAR}. A diagram of this \gls{ADC} is shown in figure~\ref{fig:adc-sar}.
The \gls{SAR} type converter uses a \gls{DAC}, controlled by the value in the \gls{SAR}, which approximates the input voltage, bit by bit, following the algorithm described in \cite{adc-sar} and outlined below:
The \gls{SAR} type converter uses a \gls{DAC}, controlled by the value in the \gls{SAR}, which approximates the input voltage, bit by bit, following the algorithm described in~\cite{adc-sar} and outlined below:
\begin{enumerate}
\item The \gls{SAR} is cleared to all zeros.
@ -84,7 +84,7 @@ The \gls{DAC} peripheral can produce a \gls{DC} level on the output pin based on
\subsection{Waveform Generation with DMA and a Timer} \label{sec:theory-dac-simple}
A straightforward, intuitive implementation of the waveform generator is illustrated in figure \ref{fig:wavegen-naive}. This approach has its advantages: it is simple and works autonomously, with no interrupt handling or interventions from the program. It could be implemented without the use of \gls{DMA} as well, using a loop periodically updating the \gls{DAC} values; of course, such approach is less flexible and we would run into problems with interrupt handling affecting the timing accuracy.
A straightforward, intuitive implementation of the waveform generator is illustrated in figure~\ref{fig:wavegen-naive}. This approach has its advantages: it is simple and works autonomously, with no interrupt handling or interventions from the program. It could be implemented without the use of \gls{DMA} as well, using a loop periodically updating the \gls{DAC} values; of course, such approach is less flexible and we would run into problems with interrupt handling affecting the timing accuracy.
\begin{figure}[h]
\centering
@ -98,7 +98,7 @@ A major disadvantage of this simple generation method is given by the limitation
\subsection{Direct Digital Synthesis} \label{sec:theory-dac-dds}
There are situations where the simple waveform generation method is not sufficient, particularly when a fine tuning or on-line frequency and phase changes are required. Those are the strengths of \gls{DDS}, an advanced digital waveform generation method well explained in \cite{all-about-dds}.
There are situations where the simple waveform generation method is not sufficient, particularly when a fine tuning or on-line frequency and phase changes are required. Those are the strengths of \gls{DDS}, an advanced digital waveform generation method well explained in~\cite{all-about-dds}.
\begin{figure}[h]
\centering
@ -106,7 +106,7 @@ There are situations where the simple waveform generation method is not sufficie
\caption{\label{fig:wavegen-dds}A block diagram of a DDS-based waveform generator}
\end{figure}
A diagram of a possible \gls{DDS} implementation in the STM32 firmware is shown in figure \ref{fig:wavegen-dds}. It is based on a \gls{NCO}. The \gls{NCO} consists of a \textit{phase accumulator} register and a \textit{tuning word} which is periodically added to it at a constant rate in a timer interrupt handler. The value of the tuning word determines the output waveform frequency. The look-up table must have a power-of-two length so that it can be addressed by the \textit{n} most significant bits of the phase accumulator. An additional control word could be added to this address to implement a phase offset for applications like a phase-shift modulation.
A diagram of a possible \gls{DDS} implementation in the STM32 firmware is shown in figure~\ref{fig:wavegen-dds}. It is based on a \gls{NCO}. The \gls{NCO} consists of a \textit{phase accumulator} register and a \textit{tuning word} which is periodically added to it at a constant rate in a timer interrupt handler. The value of the tuning word determines the output waveform frequency. The look-up table must have a power-of-two length so that it can be addressed by the \textit{n} most significant bits of the phase accumulator. An additional control word could be added to this address to implement a phase offset for applications like a phase-shift modulation.
The output frequency is calculated as \(f_\mathrm{out} = \dfrac{M\cdot f_\mathrm{c}}{2^n}\), where $M$ is the tuning word, $n$ is the bit length of the phase accumulator, and $f_c$ is the frequency of the phase-updating interrupt. The number of bits used to address the look-up table does not affect the output frequency; the table can be as large as the storage space allows. A tuning word value exceeding the lower part of the phase accumulator (including bits which directly enter the look-up address) will cause some values from the table to be skipped. A smaller tuning word, conversely, makes some values appear on the output more than once. This can be observed as steps or flat areas on the output. When the tuning word does not evenly divide $2^n$, that is, the modulo is non-zero, we can also observe jitter.
@ -118,7 +118,7 @@ DDS may be implemented in hardware, including the look-up table, often together
The used microcontroller, STM32F072, includes a \gls{TSC} peripheral block. It can be accessed from GEX as a demonstration of capacitive touch sensing, and could possibly be used for simple touch sensors as well, such as measuring the level of water in a tank.
The TSC requires a specific topology with a sampling capacitor connected close to the microcontroller pin, which may not be possible on a universal GEX module; for this reason, the touch sensing feature is best demonstrated on the STM32F072 Discovery development kit, which includes a 4-segment touch slider shown in figure \ref{fig:disco-touch}.
The TSC requires a specific topology with a sampling capacitor connected close to the microcontroller pin, which may not be possible on a universal GEX module; for this reason, the touch sensing feature is best demonstrated on the STM32F072 Discovery development kit, which includes a 4-segment touch slider shown in figure~\ref{fig:disco-touch}.
\begin{figure}[h]
\centering
@ -126,7 +126,7 @@ The TSC requires a specific topology with a sampling capacitor connected close t
\caption{\label{fig:disco-touch}The touch slider on a STM32F072 Discovery board}
\end{figure}
The principle of capacitive touch sensing using the \gls{TSC} is well explained in the microcontroller's reference manual \cite{f072-rm}, the \gls{TSC} product training materials \cite{stm-tsc-training, stm-tsc-ppt} and application notes from ST Microelectronics \cite{stm-tsc-an1, stm-tsc-an2, stm-tsc-an3, stm-tsc-an4}. A key part of the \gls{TSC} is a set of analog switches which can be combined to form several different signal paths between external pins, Vdd, \gls{GND}, and an analog comparator. Two input pins are needed for every touch sensing channel: the sensing pad connects to one, the other is connected through a sampling capacitor (47\,nF on the Discovery board) to \gls{GND}.
The principle of capacitive touch sensing using the \gls{TSC} is well explained in the microcontroller's reference manual~\cite{f072-rm}, the \gls{TSC} product training materials~\cite{stm-tsc-training, stm-tsc-ppt} and application notes from ST Microelectronics~\cite{stm-tsc-an1, stm-tsc-an2, stm-tsc-an3, stm-tsc-an4}. A key part of the \gls{TSC} is a set of analog switches which can be combined to form several different signal paths between external pins, Vdd, \gls{GND}, and an analog comparator. Two input pins are needed for every touch sensing channel: the sensing pad connects to one, the other is connected through a sampling capacitor (47\,nF on the Discovery board) to \gls{GND}.
\begin{figure}[h]
\centering
@ -145,7 +145,7 @@ Capacitive sensing is a sequential process described in the following steps:
\end{enumerate}
\noindent
A real voltage waveform measured on the sensing pad using an oscilloscope is shown in figure \ref{fig:tsc-wfm}.
A real voltage waveform measured on the sensing pad using an oscilloscope is shown in figure~\ref{fig:tsc-wfm}.
\begin{figure}
\centering

@ -18,7 +18,7 @@ The design and implementation of such a universal instrument is the object of th
\section{The Project's Expected Outcome}\label{sec:expected-outcome}
It has been a desire of the author for many years to create a universal instrument connecting low-level hardware to a computer, and, with this project, it is finally being realized. Several related projects approaching this problem from different angles can be found on the internet; those will be presented in chapter \ref{sec:prior-art}. This project should not end with yet another tinkering tool that will be produced in a few prototypes and then forgotten. By building an extensible, open-source platform, GEX can become the foundation for future projects which others can expand, re-use and adapt to their specific needs.
It has been a desire of the author for many years to create a universal instrument connecting low-level hardware to a computer, and, with this project, it is finally being realized. Several related projects approaching this problem from different angles can be found on the internet; those will be presented in chapter~\ref{sec:prior-art}. This project should not end with yet another tinkering tool that will be produced in a few prototypes and then forgotten. By building an extensible, open-source platform, GEX can become the foundation for future projects which others can expand, re-use and adapt to their specific needs.
\iffalse
\begin{figure}[H]

@ -1,6 +1,6 @@
\chapter{Client Software}
With the communication protocol clearly defined in chapters \ref{sec:tinyframe} and \ref{sec:units-overview}, respective \ref{sec:wireless} for the wireless gateway, the implementation of a client software is relatively straightforward. Two proof-of-concept client libraries have been developed, in languages C and Python.
With the communication protocol clearly defined in chapters~\ref{sec:tinyframe} and~\ref{sec:units-overview}, respective~\ref{sec:wireless} for the wireless gateway, the implementation of a client software is relatively straightforward. Two proof-of-concept client libraries have been developed, in languages C and Python.
\section{General Library Structure}
@ -8,20 +8,20 @@ The structure of a GEX support library is in all cases similar:
\begin{itemize}
\item \textbf{USB or serial port access}
This is the only platform-dependent part of the library. Unix-based systems provide a standardized POSIX API to configure the serial port. A raw access to \gls{USB} endpoints is possible using the libUSB C library. Access to the serial port or \gls{USB} from C on MS Windows has not been investigated, but should be possible using proprietary APIs.
This is the only platform-dependent part of the library. Unix-based systems provide a standardized POSIX API to configure the serial port. A raw access to \gls{USB} endpoints is possible using the libUSB C library. Access to the serial port or \gls{USB} from C on MS Windows has not been investigated, but should be possible using proprietary APIs.
Accessing the serial port or \gls{USB} endpoints from Python is more straightforward thanks to the cross platform libraries \textit{PySerial} and \textit{PyUSB}.
\item \textbf{TinyFrame}
\item \textbf{TinyFrame}
The \textit{TinyFrame} protocol library can be used directly in desktop C applications, and it has been ported to Python and other languages.
\item \textbf{Higher-level GEX logic}
The host side of the communication protocol described in chapter \ref{sec:tinyframe} should be implemented as a part of the library. This includes the reading and writing of configuration files, unit list read-out, command payload building, and asynchronous event parsing.
Additional utilities may be defined on top of this basic protocol support for the command API of different GEX units, as described in \ref{sec:units-overview}. Those unit-specific ``drivers'' are available in the provided Python library.
\item \textbf{Higher-level GEX logic}
The host side of the communication protocol described in chapter~\ref{sec:tinyframe} should be implemented as a part of the library. This includes the reading and writing of configuration files, unit list read-out, command payload building, and asynchronous event parsing.
Additional utilities may be defined on top of this basic protocol support for the command API of different GEX units, as described in~\ref{sec:units-overview}. Those unit-specific ``drivers'' are available in the provided Python library.
\end{itemize}
\section{Python Library}
@ -32,20 +32,20 @@ The library is composed of a \textit{transport}, the core class called \textit{c
\begin{itemize}
\item \mono{TrxSerialSync} -- virtual serial port access with polling for a response
\item \mono{TrxSerialThread} -- virtual serial port access with a polling thread and semaphore-based notifications
\item \mono{TrxRawUSB} -- similar to \mono{TrxSerialThread}, but using a raw USB endpoint access
\end{itemize}
The unit classes wrap the command and event \gls{API} described in chapter \ref{sec:units-overview}; all classes and methods are annotated by documentation comments for easy understanding.
The unit classes wrap the command and event \gls{API} described in chapter~\ref{sec:units-overview}; all classes and methods are annotated by documentation comments for easy understanding.
An example Python program showing a pattern with the \gls{LED} matrix driver IS31FL3730 is presented below as an illustration of the library usage. A photo of the produced pattern can be seen in figure \ref{fig:pydemo}.
An example Python program showing a pattern with the \gls{LED} matrix driver IS31FL3730 is presented below as an illustration of the library usage. A photo of the produced pattern can be seen in figure~\ref{fig:pydemo}.
\todo[inline]{add left line next to this listing}
\begin{minted}{python}
#!/bin/env python3
import gex
import gex
with gex.Client(gex.TrxRawUSB()) as client:
bus = gex.I2C(client, 'i2c')
addr = 0x61
@ -74,13 +74,13 @@ with gex.Client(gex.TrxRawUSB()) as client:
\section{MATLAB integration}
The Python library can be accessed from MATLAB scripts thanks to the MATLAB's two-way Python integration \cite{matlabpy}. Controlling GEX from MATLAB may be useful when additional processing is required, e.g. with data from the \gls{ADC}; however, in many cases, an open source alternative native to Python exists that could be used for the same purpose, such as the NumPy and SciPy libraries \cite{numpyscipy}.
The Python library can be accessed from MATLAB scripts thanks to the MATLAB's two-way Python integration~\cite{matlabpy}. Controlling GEX from MATLAB may be useful when additional processing is required, e.g. with data from the \gls{ADC}; however, in many cases, an open source alternative native to Python exists that could be used for the same purpose, such as the NumPy and SciPy libraries~\cite{numpyscipy}.
\todo[inline]{add a matlab example}
\section{C Library}
The C library is more simplistic than the Python one; it supports only the serial port transport (\gls{UART} or \gls{CDCACM}) and does not implement asynchronous polling or the unit support drivers. What \textit{is} implement---the transport, a basic protocol handler, and payload building and parsing utilities---is sufficient for most applications, though less convenient than the Python library.
The C library is more simplistic than the Python one; it supports only the serial port transport (\gls{UART} or \gls{CDCACM}) and does not implement asynchronous polling or the unit support drivers. What \textit{is} implement---the transport, a basic protocol handler, and payload building and parsing utilities---is sufficient for most applications, though less convenient than the Python library.
This low-level library is intended for applications where the performance of the Python implementation is insufficient, or where an integration with existing C code is required. The full \gls{API} can be found in the library header files. A C version of the example Python script controlling a \gls{LED} matrix driver follows:

@ -28,7 +28,7 @@ Generating an analog signal is possible using a \gls{PWM} or by a dedicated digi
\subsection{Logic Level Input and Output}
We've covered some more advanced features, but skipped the simplest feature: a direct access to \gls{GPIO} pins. Considering the latencies of \gls{USB} and the \gls{PC}'s operating system, this cannot be used reliably for ``bit banging'', however we can still accomplish a lot with just changing logic levels - e.g. to control character \glspl{LCD}, or emulate some interfaces that include a clock line, like \gls{SPI}. As mentioned in \ref{sec:uses-digital-ifaces}, many digital sensors and modules use plain \glspl{GPIO} in addition to the communication bus for out-of-band signaling or features like chip selection or reset.
We've covered some more advanced features, but skipped the simplest feature: a direct access to \gls{GPIO} pins. Considering the latencies of \gls{USB} and the \gls{PC}'s operating system, this cannot be used reliably for ``bit banging'', however we can still accomplish a lot with just changing logic levels - e.g. to control character \glspl{LCD}, or emulate some interfaces that include a clock line, like \gls{SPI}. As mentioned in~\ref{sec:uses-digital-ifaces}, many digital sensors and modules use plain \glspl{GPIO} in addition to the communication bus for out-of-band signaling or features like chip selection or reset.
\subsection{Pulse Generation and Measurement}
@ -56,7 +56,7 @@ Let's now summarize the features we wish to support in the GEX firmware, based o
\begin{itemize}
\item \textbf{Hardware interfacing functions}
\begin{itemize}
\begin{itemize}
\item I/O pin direct access (read, write), pin change interrupt
\item Analog input: voltage measurement, sampled capture
\item Analog output: static level, waveform generation
@ -64,7 +64,7 @@ Let's now summarize the features we wish to support in the GEX firmware, based o
\item Single pulse and \gls{PWM} generation
\item \gls{SPI}, \gls{I2C}, \gls{UART}/\gls{USART}
\item Dallas 1-Wire
\item NeoPixel (addressable \gls{LED} strips)
\item NeoPixel (addressable \gls{LED} strips)
\end{itemize}
\pagebreak[0]
\item \textbf{Communication with the host computer}
@ -83,7 +83,7 @@ Let's now summarize the features we wish to support in the GEX firmware, based o
\section{Microcontroller Selection}
As discussed in section \ref{sec:expected-outcome}, this project will be based on microcontrollers from the STM32 family. The STM32F072 model was selected for the initial hardware and firmware design due to its low cost, advanced peripherals, and the availability of development boards. The firmware can be ported to other \glspl{MCU} later (e.g. to STM32L072, STM32F103 or STM32F303).
As discussed in section~\ref{sec:expected-outcome}, this project will be based on microcontrollers from the STM32 family. The STM32F072 model was selected for the initial hardware and firmware design due to its low cost, advanced peripherals, and the availability of development boards. The firmware can be ported to other \glspl{MCU} later (e.g. to STM32L072, STM32F103 or STM32F303).
The STM32F072 is a Cortex M0 device with 128\,KiB of flash memory, 16\,KiB of \gls{RAM} and running at 48\,MHz. It is equipped with a \gls{USB} Full Speed peripheral block, a 12-bit \gls{ADC} and \gls{DAC}, a number of general-purpose timers/counters, SPI, I$^2$C, and USART peripherals, among others. It supports crystal-less \gls{USB}, using the USB SOF packet for synchronization of the internal 48\,MHz RC oscillator; naturally, a real crystal resonator will provide better timing accuracy.
@ -91,9 +91,9 @@ To effectively utilize the time available for this work, only the STM32F072 firm
\section{Form Factor Considerations}
While the GEX firmware can be used with existing evaluation boards from ST Microelectronics (see figure \ref{fig:discovery} for an example of one such board), we wish to design and realize a few custom hardware prototypes that will be smaller and more convenient to use.
While the GEX firmware can be used with existing evaluation boards from ST Microelectronics (see figure~\ref{fig:discovery} for an example of one such board), we wish to design and realize a few custom hardware prototypes that will be smaller and more convenient to use.
Three possible form factors are drawn in figure \ref{fig:ff-sketches}. The use of a common connector layout and pin assignments, here Arduino and Raspberry Pi, makes it possible to reuse add-on boards from those platforms. When we copy the physical form factor of another product, in this example the Raspberry Pi Zero, we can further take advantage of existing enclosures designed for it.
Three possible form factors are drawn in figure~\ref{fig:ff-sketches}. The use of a common connector layout and pin assignments, here Arduino and Raspberry Pi, makes it possible to reuse add-on boards from those platforms. When we copy the physical form factor of another product, in this example the Raspberry Pi Zero, we can further take advantage of existing enclosures designed for it.
\begin{figure}[h]
\centering

@ -4,7 +4,7 @@ GEX can be controlled through a hardware \gls{UART}, the \gls{USB} or over a wir
The communication is organized in transactions. A transaction consists of one or more messages going in either direction. Messages can be stand-alone, or chained with a response or a follow-up message using the transaction ID. Both peers, GEX and the client application running on the host PC, are equal in the communication: either side can independently initiate a transaction at any time.
GEX uses a framing library \textit{TinyFrame} \cite{tinyframerepo}, developed likewise by the author, but kept as a separate project for easier re-use in different applications. The library implements frame building and parsing, checksum calculation and a system of message listeners.
GEX uses a framing library \textit{TinyFrame}~\cite{tinyframerepo}, developed likewise by the author, but kept as a separate project for easier re-use in different applications. The library implements frame building and parsing, checksum calculation and a system of message listeners.
\section{Frame Structure}
@ -15,7 +15,7 @@ Message frames have the following structure (all little-endian):
\cfield{u16} frame ID
\cfield{u16} payload length
\cfield{u8} frame type
\cfield{u8} header checksum
\cfield{u8} header checksum
\cfield{u8[]} payload
\cfield{u8} payload checksum (omitted for empty payloads)
\end{boxedpayload}
@ -106,7 +106,7 @@ The reason for splitting a long file into multiple messages, rather than sending
A read or write transaction can be aborted by a frame 0x08 (Bulk Abort) at any time, though aborting a write transaction may leave the configuration in a corrupted state. As hinted in the introduction of this chapter, a transaction is defined by sharing a common frame ID. Thus, all frames in a bulk transaction must have the same ID, otherwise the ID listeners won't be called for the subsequent messages, and the transaction will time out.
Figure \ref{fig:bulk-rw} shows a diagram of the bulk read and write data flow.
Figure~\ref{fig:bulk-rw} shows a diagram of the bulk read and write data flow.
\begin{figure}
\centering

@ -1,6 +1,6 @@
\section{1-Wire Unit}
The 1-Wire unit implements the Dallas Semiconductor's 1-Wire protocol, most commonly used to interface smart thermometers (DS18x20). The protocol is explained in section \ref{sec:theory-1wire}.
The 1-Wire unit implements the Dallas Semiconductor's 1-Wire protocol, most commonly used to interface smart thermometers (DS18x20). The protocol is explained in section~\ref{sec:theory-1wire}.
This unit implements the ROM Search algorithm that is used to find the ROM codes of all 1-Wire devices connected to the bus. The algorithm can find up to 32 devices in one run; more devices can be found by issuing the SEARCH\_CONTINUE command.

@ -2,7 +2,7 @@
The digital/analog unit works with the two-channel \gls{DAC} hardware peripheral. It can be used in two modes: \gls{DC} output, and waveform generation.
The waveform mode implements direct digital synthesis (explained in section \ref{sec:theory-dac-dds}) of a sine, rectangle, sawtooth or triangle wave. The generated frequency can be set with a sub-hertz precision up to the lower tens of kHz. The two outputs can use a different waveform shape, can be synchronized, and their phase offset and frequency are dynamically adjustable.
The waveform mode implements direct digital synthesis (explained in section~\ref{sec:theory-dac-dds}) of a sine, rectangle, sawtooth or triangle wave. The generated frequency can be set with a sub-hertz precision up to the lower tens of kHz. The two outputs can use a different waveform shape, can be synchronized, and their phase offset and frequency are dynamically adjustable.
\subsection{DAC Configuration}

@ -1,7 +1,7 @@
\section{Frequency Capture Unit}
The frequency capture unit implements both the frequency measurement methods explained in section \ref{sec:theory-fcap}: direct and reciprocal.
The frequency capture unit implements both the frequency measurement methods explained in section~\ref{sec:theory-fcap}: direct and reciprocal.
The unit has several operational modes: idle, reciprocal continuous, reciprocal burst, direct continuous, direct burst, free counting, and single pulse. Burst mode is an on-demand measurement with optional averaging. Continuous mode doesn't support averaging, but the latest measurement can be read at any time without a delay.

@ -1,6 +1,6 @@
\section{\IIC Unit}
The \gls{I2C} unit provides access to one of the microcontroller's \gls{I2C} peripherals. More on the \IIC bus can be found in section \ref{sec:theory-i2c}.
The \gls{I2C} unit provides access to one of the microcontroller's \gls{I2C} peripherals. More on the \IIC bus can be found in section~\ref{sec:theory-i2c}.
The unit can be configured to use either of the three standard speeds (Standard, Fast and Fast+) and supports both 10-bit and 7-bit addressing. 10-bit addresses can be used in commands by setting their highest bit (0x8000), as a flag to the unit; the 7 or 10 least significant bits will be used as the actual address.

@ -1,6 +1,6 @@
\section{NeoPixel Unit}
The NeoPixel unit implements the protocol needed to control a digital \gls{LED} strip with WS2812, WS2811, or compatible \gls{LED} driver chips. The NeoPixel protocol (explained in section \ref{sec:theory-neo}) is implemented in software, therefore it is available on any \gls{GPIO} pin of the module.
The NeoPixel unit implements the protocol needed to control a digital \gls{LED} strip with WS2812, WS2811, or compatible \gls{LED} driver chips. The NeoPixel protocol (explained in section~\ref{sec:theory-neo}) is implemented in software, therefore it is available on any \gls{GPIO} pin of the module.
The color data can be loaded in five different format: as packed bytes (3$\times$8 bits color), or as the little- or big-endian encoding of colors in a 32-bit format: 0x00RRGGBB or 0x00BBGGRR. The 32-bit format is convenient when the colors are already represented as an array of 32-bit integers, e.g. extracted from a screen capture or an image.

@ -1,10 +1,10 @@
\section{SPI Unit}
The \gls{SPI} unit provides access to one of the microcontroller's \gls{SPI} peripherals. The unit can be configured to any of the hardware-supported speeds, clock polarity, and clock phase settings. Explanation of those options, including diagrams, can be found in section \ref{sec:theory-spi}.
The \gls{SPI} unit provides access to one of the microcontroller's \gls{SPI} peripherals. The unit can be configured to any of the hardware-supported speeds, clock polarity, and clock phase settings. Explanation of those options, including diagrams, can be found in section~\ref{sec:theory-spi}.
The unit handles up to 16 slave select (\gls{NSS}) signals and supports message multi-cast (addressing more than one slaves at once). Protection resistors should be used if a multi-cast transaction is issued with \gls{MISO} connected to prevent a short circuit between slaves transmitting the opposite logical level.
The QUERY command of this unit, illustrated by figure \ref{fig:spi_query}, is flexible enough to support all types of \gls{SPI} transactions: read-only, write-only, and read-write, with different request and response lengths and paddings. The slave select signal is asserted during the entire transaction.
The QUERY command of this unit, illustrated by figure~\ref{fig:spi_query}, is flexible enough to support all types of \gls{SPI} transactions: read-only, write-only, and read-write, with different request and response lengths and paddings. The slave select signal is asserted during the entire transaction.
\begin{figure}[h]
\centering
@ -42,7 +42,7 @@ pins=0
\begin{cmdlist}
0 & \cname{QUERY}
Exchange bytes with a slave device; see the diagram in figure \ref{fig:spi_query}
Exchange bytes with a slave device; see the diagram in figure~\ref{fig:spi_query}
& \begin{cmdreq}
\cfield{u8} slave number 0--16
\cfield{u16} response padding

@ -1,6 +1,6 @@
\section{Touch Sense Unit}
The touch sensing unit provides an access to the \gls{TSC} peripheral, explained in section \ref{sec:theory-touch}. The unit configures the \gls{TSC} and reads the output values of each enabled touch pad. Additionally, a threshold-based digital input function is implemented to make the emulation of touch buttons easier. The hysteresis and debounce time can be configured in the configuration file or set using a command. The threshold of individual pads must be set using a command.
The touch sensing unit provides an access to the \gls{TSC} peripheral, explained in section~\ref{sec:theory-touch}. The unit configures the \gls{TSC} and reads the output values of each enabled touch pad. Additionally, a threshold-based digital input function is implemented to make the emulation of touch buttons easier. The hysteresis and debounce time can be configured in the configuration file or set using a command. The threshold of individual pads must be set using a command.
\subsection{Touch Sense Configuration}

@ -1,6 +1,6 @@
\section{USART Unit}
The \gls{USART} unit provides access to one of the microcontroller's \gls{USART} peripherals. See section \ref{sec:theory-usart} for more information about the interface.
The \gls{USART} unit provides access to one of the microcontroller's \gls{USART} peripherals. See section~\ref{sec:theory-usart} for more information about the interface.
Most \gls{USART} parameters available in the hardware peripheral's configuration registers can be adjusted to match the application's needs. The peripheral is capable of driving RS-485 transceivers, using the \gls{DE} output for switching between reception and transmission.

@ -1,6 +1,6 @@
\chapter{Universal Serial Bus}
This chapter presents an overview of the \acrfull{USB} Full Speed interface, with focus on the features used in the GEX firmware. \gls{USB} is a versatile and powerful interface which replaces several older technologies; for this reason its specification is very complex and going into all details is hardly possible. We will cover the basic principles and terminology of \gls{USB} and focus on the parts relevant for the GEX project. More information about the bus can be found in the official specification \cite{usbif-spec}, related documents published by the USB Implementers Forum, and other on-line resources \cite{usb-nutshell,usb-made-simple}.
This chapter presents an overview of the \acrfull{USB} Full Speed interface, with focus on the features used in the GEX firmware. \gls{USB} is a versatile and powerful interface which replaces several older technologies; for this reason its specification is very complex and going into all details is hardly possible. We will cover the basic principles and terminology of \gls{USB} and focus on the parts relevant for the GEX project. More information about the bus can be found in the official specification~\cite{usbif-spec}, related documents published by the USB Implementers Forum, and other on-line resources~\cite{usb-nutshell,usb-made-simple}.
\section{Basic Principles and Terminology}
@ -10,7 +10,7 @@ This chapter presents an overview of the \acrfull{USB} Full Speed interface, wit
\caption[USB hierarchical structure]{\label{fig:usb-hierarchy}The hierarchical structure of the USB bus}
\end{figure}
\gls{USB} is a hierarchical bus with a single master (\textit{host}) and multiple slave devices. A \gls{USB} device that provides functionality to the host is called a \textit{function} \cite{usb-function}.
\gls{USB} is a hierarchical bus with a single master (\textit{host}) and multiple slave devices. A \gls{USB} device that provides functionality to the host is called a \textit{function}~\cite{usb-function}.
\subsection{Pipes and Endpoints}
@ -39,7 +39,7 @@ There are four types of data transfers defined in \gls{USB}: control, bulk, isoc
The function's endpoints are grouped into \textit{interfaces}. An interface describes a logical connection of endpoints, such as the reception and transmission endpoints that belong together. An interface is assigned a \textit{class} defining how it should be used.
Standard classes are defined by the USB specification \cite{usb-class-list} to provide a uniform way of interfacing devices of the same type, such as human-interface devices (mice, keyboards, gamepads) or mass storage devices. The use of standard classes makes it possible to re-use the same driver software for devices from different manufacturers.
Standard classes are defined by the USB specification~\cite{usb-class-list} to provide a uniform way of interfacing devices of the same type, such as human-interface devices (mice, keyboards, gamepads) or mass storage devices. The use of standard classes makes it possible to re-use the same driver software for devices from different manufacturers.
The class used for the GEX's ``virtual COM port'' function was originally meant for telephone modems, a common way of connecting to the Internet at the time the first versions of USB were developed. A device using this class will show as \verb|/dev/ttyACM0| on Linux and as a COM port on Windows, provided the system supports it natively or the right driver is installed.
@ -51,18 +51,18 @@ Each descriptor starts with a declaration of its length (in bytes), followed by
The topmost descriptor holds information about the entire function, including the vendor and product IDs which uniquely identifies the device model. It is followed by a Configuration descriptor, grouping a set of interfaces. More than one configuration may be present and available for the host to choose from; however, this is rarely used or needed. Each configuration descriptor is followed by one or more interface descriptors, each with its class-specific sub-descriptors and/or endpoint descriptors.
The descriptor table used by GEX is captured in figure \ref{fig:gex-descriptors} for illustration. The vendor and product IDs were obtained from the pid.codes repository \cite{pidcodes} providing free product codes to open source projects. The official way of obtaining the unique code involves high recurring fees (\$4000 per annum) to the USB Implementers Forum, Inc. and is therefore not affordable for non-commercial use; alternatively, a product code may be obtained from some \gls{MCU} vendors if their product is used in the device.
The descriptor table used by GEX is captured in figure~\ref{fig:gex-descriptors} for illustration. The vendor and product IDs were obtained from the pid.codes repository~\cite{pidcodes} providing free product codes to open source projects. The official way of obtaining the unique code involves high recurring fees (\$4000 per annum) to the USB Implementers Forum, Inc. and is therefore not affordable for non-commercial use; alternatively, a product code may be obtained from some \gls{MCU} vendors if their product is used in the device.
\newpage
\input{fig.gex-descriptors}
\section{USB Physical Layer}
\gls{USB} uses differential signaling with \gls{NRZI} encoding and bit stuffing (the insertion of dummy bits to prevent long intervals in the same \gls{DC} level). The encoding, together with frame formatting, checksum verification, retransmission, and other low-level aspects of the \gls{USB} connection are entirely handled by the \gls{USB} physical interface block in the microcontroller's silicon. Normally we do not need to worry about those details; nonetheless, a curious reader may find more information in chapters 7 and 8 of \cite{usbif-spec}. What needs our attention are the electrical characteristics of the physical connection, which need to be understood correctly for a successful schematic and \gls{PCB} design.
\gls{USB} uses differential signaling with \gls{NRZI} encoding and bit stuffing (the insertion of dummy bits to prevent long intervals in the same \gls{DC} level). The encoding, together with frame formatting, checksum verification, retransmission, and other low-level aspects of the \gls{USB} connection are entirely handled by the \gls{USB} physical interface block in the microcontroller's silicon. Normally we do not need to worry about those details; nonetheless, a curious reader may find more information in chapters 7 and 8 of~\cite{usbif-spec}. What needs our attention are the electrical characteristics of the physical connection, which need to be understood correctly for a successful schematic and \gls{PCB} design.
The \gls{USB} cable contains 4 conductors: V$_\mathrm{BUS}$ (+5\,V), D+, D--, and \gls{GND}. The data lines, D+ and D--, are also commonly labeled DP and DM. This differential pair should be routed in parallel on the \gls{PCB} and kept at the same length.
\gls{USB} versions that share the same connector are backwards compatible. The desired bus speed is requested by the device using a 1.5\,k$\Omega$ pull-up resistor to 3.3\,V on one of the data lines: D+ pulled high for Full Speed (shown in figure \ref{fig:usb-pullup-fs}), D-- pulled high for Low Speed. The polarity of the differential signals is also inverted depending on the used speed, as the idle level changes. Some microcontrollers integrate the correct pull-up resistor inside the \gls{USB} peripheral block (including out STM32F072), removing the need for an external resistor.
\gls{USB} versions that share the same connector are backwards compatible. The desired bus speed is requested by the device using a 1.5\,k$\Omega$ pull-up resistor to 3.3\,V on one of the data lines: D+ pulled high for Full Speed (shown in figure~\ref{fig:usb-pullup-fs}), D-- pulled high for Low Speed. The polarity of the differential signals is also inverted depending on the used speed, as the idle level changes. Some microcontrollers integrate the correct pull-up resistor inside the \gls{USB} peripheral block (including out STM32F072), removing the need for an external resistor.
\begin{figure}[h]
\centering
@ -70,15 +70,15 @@ The \gls{USB} cable contains 4 conductors: V$_\mathrm{BUS}$ (+5\,V), D+, D--, an
\caption[USB pull-ups]{\label{fig:usb-pullup-fs}Pull-up and pull-down resistors near the host and a Full Speed function, as prescribed by the USB specification rev. 2.0}
\end{figure}
When a function needs to be re-enumerated by the host, which causes a reload of the descriptor table and the re-attachment of software drivers, it can momentarily remove the pull-up resistor, which the host will interpret as if the device was disconnected. With an internal pull-up, this can be done by flipping a bit in a control register. An external resistor may be connected through a transistor controlled by a \gls{GPIO} pin. As discussed in \cite{eev-gpio-pu}, a GPIO pin might be used to drive the pull-up directly, though this has not been verified by the author.
When a function needs to be re-enumerated by the host, which causes a reload of the descriptor table and the re-attachment of software drivers, it can momentarily remove the pull-up resistor, which the host will interpret as if the device was disconnected. With an internal pull-up, this can be done by flipping a bit in a control register. An external resistor may be connected through a transistor controlled by a \gls{GPIO} pin. As discussed in~\cite{eev-gpio-pu}, a GPIO pin might be used to drive the pull-up directly, though this has not been verified by the author.
The V$_\mathrm{BUS}$ line supplies power to \textit{bus-powered} devices. \textit{Self-powered} devices can leave this pin unconnected and instead use an external power supply. The maximal current drawn from the V$_\mathrm{BUS}$ line is configured using a descriptor and should not be exceeded, but experiments suggest this is often not enforced.
\noindent More details about the electrical and physical connection may be found in \cite{usb-nutshell}, sections \textit{Connectors} through \textit{Power}.
\noindent More details about the electrical and physical connection may be found in~\cite{usb-nutshell}, sections \textit{Connectors} through \textit{Power}.
\section{USB Classes}
This section explains the classes used in the GEX firmware. A list of all standard classes with a more detailed explanation can be found in \cite{usb-class-list}.
This section explains the classes used in the GEX firmware. A list of all standard classes with a more detailed explanation can be found in~\cite{usb-class-list}.
\subsection{Mass Storage Class} \label{sec:msc}
@ -87,22 +87,22 @@ The \gls{MSC} is supported by all modern operating systems (MS Windows, MacOS, G
%http://www.usb.org/developers/docs/devclass_docs/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf
%http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf
The \gls{MSC} specification \cite{usbif-msco} defines multiple \textit{transport protocols} that can be selected using the descriptors. The \gls{BOT} \cite{usbif-bot} will be used for its simplicity. \gls{BOT} uses two bulk endpoints for reading and writing blocks of data and for the exchange of control commands and status messages.
The \gls{MSC} specification~\cite{usbif-msco} defines multiple \textit{transport protocols} that can be selected using the descriptors. The \gls{BOT}~\cite{usbif-bot} will be used for its simplicity. \gls{BOT} uses two bulk endpoints for reading and writing blocks of data and for the exchange of control commands and status messages.
For the mass storage device to be recognized by the host operating system, it must also implement a \textit{command set}. Most mass storage devices use the \textit{\gls{SCSI} Transparent command set}
\footnote{To confirm this assertion, the descriptors of five thumb drives and an external hard disk were analyzed using \verb|lsusb|. All but one device used the SCSI command set, one (the oldest thumb drive) used \textit{SFF-8070i}. A list of possible command sets can be found in \cite{usbif-msco}}.
\footnote{To confirm this assertion, the descriptors of five thumb drives and an external hard disk were analyzed using \verb|lsusb|. All but one device used the SCSI command set, one (the oldest thumb drive) used \textit{SFF-8070i}. A list of possible command sets can be found in~\cite{usbif-msco}}.
Unfortunately, the \gls{SCSI} Transparent command set appears to have been deliberately left unspecified for license or copyright reasons (see discussion in \cite{usb-tscsi-wtf} and the surrounding thread) and the protocol now used under this name is an industry standard without a clear definition. Some pointers may be found in \cite{usb-tscsi} and by examining the source code of the USB Device driver library provided by ST Microelectronics.
Unfortunately, the \gls{SCSI} Transparent command set appears to have been deliberately left unspecified for license or copyright reasons (see discussion in~\cite{usb-tscsi-wtf} and the surrounding thread) and the protocol now used under this name is an industry standard without a clear definition. Some pointers may be found in~\cite{usb-tscsi} and by examining the source code of the USB Device driver library provided by ST Microelectronics.
This command set lets the host read information about the attached storage, such as its capacity, and check for media presence and readiness to write or detach. This is used e.g. for the ``Safely Remove'' function, which ensures that all internal buffers have been written to Flash.
In order to emulate a mass storage device without having a physical storage medium, we need to generate and parse the file system on-the-fly as the host \gls{OS} tries to access it. This will be discussed in chapter \ref{sec:fat16}.
In order to emulate a mass storage device without having a physical storage medium, we need to generate and parse the file system on-the-fly as the host \gls{OS} tries to access it. This will be discussed in chapter~\ref{sec:fat16}.
\subsection{CDC/ACM Class} \label{sec:cdc-acm}
%https://www.keil.com/pack/doc/mw/USB/html/group__usbd__cdc_functions__acm.html
Historically meant for modem communication, \gls{CDCACM} is now the de facto standard way of making \gls{USB} devices appear as serial ports on the host \gls{OS}. Its specification can be found in \cite{usbif-cdc}. \gls{CDCACM} is a combination of two related classes, \gls{CDC} handling the data communication and \gls{ACM}, which defines control commands. Three endpoints are used: bulk IN, bulk OUT, and interrupt OUT.
Historically meant for modem communication, \gls{CDCACM} is now the de facto standard way of making \gls{USB} devices appear as serial ports on the host \gls{OS}. Its specification can be found in~\cite{usbif-cdc}. \gls{CDCACM} is a combination of two related classes, \gls{CDC} handling the data communication and \gls{ACM}, which defines control commands. Three endpoints are used: bulk IN, bulk OUT, and interrupt OUT.
The interrupt endpoint is used for control commands, such as toggling the auxiliary lines of RS-232 or setting the baud rate. Since GEX does not translate the data communication to any physical UART, those commands are not applicable and can be silently ignored.
@ -110,7 +110,7 @@ An interesting property of the \gls{CDC} class is that the bulk endpoints transp
\subsection{Interface Association: Composite Class}
The original \gls{USB} specification expected that each function will have only one interface enabled at a time. After it became apparent that there is a need to have multiple unrelated interfaces working in parallel, the \gls{IAD} \cite{usbif-iad} was introduced as a workaround.
The original \gls{USB} specification expected that each function will have only one interface enabled at a time. After it became apparent that there is a need to have multiple unrelated interfaces working in parallel, the \gls{IAD}~\cite{usbif-iad} was introduced as a workaround.
The \gls{IAD} is an entry in the descriptor table that defines which interfaces belong together and should be handled by the same software driver. To use the \gls{IAD}, the function's class must be set to 239 (0xEF), subclass 2 and protocol 1 in the top level descriptor, so that the \gls{OS} knows to look for this descriptor before binding drivers to any interfaces.

@ -1,8 +1,8 @@
\chapter{Wireless Interface} \label{sec:wireless}
Four methods of a wireless connection have been considered: Bluetooth (e.g. with CC2541), WiFi with ESP8266, a 868\,MHz long range link with SX1276, and a 2.4\,GHz link with nRF24L01+. Bluetooth was dismissed early for its complexity, and ESP8266 for its high consumption in continuous reception mode, although both solutions might be viable for certain applications and with more development time.
Four methods of a wireless connection have been considered: Bluetooth (e.g. with CC2541), WiFi with ESP8266, a 868\,MHz long range link with SX1276, and a 2.4\,GHz link with nRF24L01+. Bluetooth was dismissed early for its complexity, and ESP8266 for its high consumption in continuous reception mode, although both solutions might be viable for certain applications and with more development time.
The Semtech SX1276 \cite{semtech-manual} and Nordic Semiconductor nRF24L01+ \cite{nrf-manual} transceivers have both been tested using the first GEX prototype, proving its usefulness as a hardware development tool, and it has been confirmed they could fulfill the requirements of our application.
The Semtech SX1276~\cite{semtech-manual} and Nordic Semiconductor nRF24L01+ ~\cite{nrf-manual} transceivers have both been tested using the first GEX prototype, proving its usefulness as a hardware development tool, and it has been confirmed they could fulfill the requirements of our application.
\begin{figure}[h]
\centering
@ -12,11 +12,11 @@ The Semtech SX1276 \cite{semtech-manual} and Nordic Semiconductor nRF24L01+ \ci
\section{Modulations Overview}
A brief overview of the different signal modulation techniques is presented here to aid the reader with understanding of table \ref{fig:nrf-sx-comparison} and the rest of the chapter.
A brief overview of the different signal modulation techniques is presented here to aid the reader with understanding of table~\ref{fig:nrf-sx-comparison} and the rest of the chapter.
\subsection{On-Off Keying (OOK)}
In \gls{OOK}, the carrier generator is switched on and off to transmit ones and zeros.
In \gls{OOK}, the carrier generator is switched on and off to transmit ones and zeros.
\subsection{Frequency Shift Keying (FSK)}
@ -40,7 +40,7 @@ LoRa is a patented proprietary modulation developed by Semtech. It uses a direct
\section{Comparing SX1276 and nRF24L01+}
The two transceivers are compared in table \ref{fig:nrf-sx-comparison}. It is apparent that each of them has its strengths and weaknesses, which will be discussed below.
The two transceivers are compared in table~\ref{fig:nrf-sx-comparison}. It is apparent that each of them has its strengths and weaknesses, which will be discussed below.
\begin{table}[h]
\centering
@ -70,7 +70,7 @@ SX1276 supports additional modulation modes, including a proprietary LoRa scheme
nRF24L01+ provides higher data rates at short distances. Its power consumption is comparable or lower than that of the SX1276. It lacks a dedicated reset pin, but that can be easily worked around using an external transistor to momentarily disconnect its Vdd pin.
Both devices implement some form of a packet engine with error checking; that of the nRF24L01+, called ShockBurst, is more advanced as it implements acknowledgment responses and automatic re-transmission, leading to a potentially more robust communication without an additional overhead on the side of the microcontroller.
Both devices implement some form of a packet engine with error checking; that of the nRF24L01+, called ShockBurst, is more advanced as it implements acknowledgment responses and automatic re-transmission, leading to a potentially more robust communication without an additional overhead on the side of the microcontroller.
\section{Integration of the nRF24L01+ into GEX}
@ -90,50 +90,50 @@ A separate device, the \textit{GEX wireless gateway}, was developed to provide t
\caption{A block diagram of the wireless connection}
\end{wrapfigure}
The gateway presents itself to the host as a \gls{CDCACM} device, much like the GEX modules themselves (here called \textit{nodes}) when connected over \gls{USB}. It implements a simple protocol which encapsulates the binary data sent to or from a connected node. The wrapped GEX protocol, which is described in chapter \ref{sec:tinyframe}, remains unchanged.
The gateway presents itself to the host as a \gls{CDCACM} device, much like the GEX modules themselves (here called \textit{nodes}) when connected over \gls{USB}. It implements a simple protocol which encapsulates the binary data sent to or from a connected node. The wrapped GEX protocol, which is described in chapter~\ref{sec:tinyframe}, remains unchanged.
The gateway has a 4-byte network ID, a number derived from the \gls{MCU}'s unique ID by calculating its 32-bit \gls{CRC}. The network ID must be entered into all nodes that wish to communicate with the gateway. Additionally, each module is assigned a 1-byte number which serves as its address in the network. The gateway can receive messages from up to 6 nodes.
All messages sent to or from the gateway are a multiple of 64 bytes long, padded with zeros if shorter. The message starts with a control byte determining its type, as summarized in the following table:
{
{
\tabulinesep=5pt
\begin{longtabu} to \textwidth {P{5em} X[5] X[4,l]}
\begin{longtabu} to \textwidth {P{5em} X[5] X[4,l]}
\toprule
\textbf{First byte} & \textbf{Function} & \textbf{Structure} \\
\midrule
\endhead
\bottomrule
\bottomrule
\endfoot
`r' (114) &
`r' (114) &
\cname{RESTART}
Restart the gateway, disconnecting all nodes. This is functionally equivalent to re-plugging it to the USB port.
& \\
`i' (105) &
\cname{GET\_NET\_ID}
Read the unique 4-byte network ID. This command has no side effects and may be used as ``ping'' to verify the USB connection. &
Read the unique 4-byte network ID. This command has no side effects and may be used as ``ping'' to verify the USB connection. &
\begin{cmdresp}
\cfield{0x01}
\cfield{u8[4]} network ID
\end{cmdresp}
\end{cmdresp}
\\
`n' (110) &
\cname{ADD\_NODES}
Configure the gateway to listen for messages from the given nodes.
Nodes may be removed using the RESTART command.
&
\begin{cmdreq}
&
\begin{cmdreq}
\cfield{u8} count
\cfield{u8[]} node addresses
\end{cmdreq}
\\
`m' (109)&
\cname{SEND\_MSG}
`m' (109)&
\cname{SEND\_MSG}
Send a binary message to one of the connected nodes. The message may span multiple 64-byte frames; the subsequent frames will contain only the payload bytes, or zero padding at the end of the last one.
& \begin{cmdreq}
\cfield{u8} node address
@ -142,10 +142,10 @@ All messages sent to or from the gateway are a multiple of 64 bytes long, padded
\cfield{u8[]} payload
\end{cmdreq} \\
0x02 &
0x02 &
\cname{INCOMING\_MSG}
A message was received from one of the configured nodes. This is an event frame sent by the gateway to the host.
& \begin{cmdpld}
& \begin{cmdpld}
\cfield{u8} node address
\cfield{u8} message length
\cfield{u8[]} payload

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2
import subprocess
import sys

@ -0,0 +1,12 @@
#/bin/bash
if [[ "$1" == "" ]]; then
echo "missing arg"
exit
fi
echo "Processing $1"
sed -i 's/ \\ref/~\\ref/g' "$1"
sed -i 's/ \cite/~\cite/g' "$1"
git diff --word-diff "$1"

Binary file not shown.
Loading…
Cancel
Save