replacing wrong dashes, cleveref etc

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

@ -44,7 +44,7 @@ The board is based on a PIC16 microcontroller running at 32\,MHz. Its \gls{ADC}
\section{Professional DAQ Modules} \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 (\cref{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. 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.
@ -63,7 +63,7 @@ The performance GEX can provide may not always match that of those professional
\begin{subfigure}{.5\textwidth} \begin{subfigure}{.5\textwidth}
\centering \centering
\includegraphics[width=.95\linewidth]{img/total-phase-spi-i2c.jpg} \includegraphics[width=.95\linewidth]{img/total-phase-spi-i2c.jpg}
\caption{Total Phase SPI/\IIC Host "Aardwark"} \caption{Total Phase SPI/\IIC Host ``Aardwark''}
\end{subfigure} \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} \end{figure}

@ -42,9 +42,9 @@ The \gls{FAT} acts as a look-up table combined with linked lists. In FAT16, it i
Files can span multiple clusters; each \gls{FAT} entry either holds the address of the following file cluster, or a special value: Files can span multiple clusters; each \gls{FAT} entry either holds the address of the following file cluster, or a special value:
\begin{itemize}[nosep] \begin{itemize}[nosep]
\item 0x0000 - free cluster \item 0x0000 -- free cluster
\item 0xFFFF - last cluster of the file (still including file data) \item 0xFFFF -- last cluster of the file (still including file data)
\item 0xFFF7 - bad cluster \item 0xFFF7 -- bad cluster
\end{itemize} \end{itemize}
The bad cluster mark, 0xFFF7, is used for clusters which are known to corrupt data due to a flaw in the storage medium, such us a bad memory cell. The bad cluster mark, 0xFFF7, is used for clusters which are known to corrupt data due to a flaw in the storage medium, such us a bad memory cell.
@ -72,21 +72,21 @@ 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} \caption{\label{tab:fat16-dir-entry}Structure of a FAT16 directory entry}
\end{table} \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. \Cref{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 \noindent
The first byte of the file name has a special meaning: The first byte of the file name has a special meaning:
\begin{itemize} \begin{itemize}
\item 0x00 - indicates that there are no more files when searching the directory \item 0x00 -- indicates that there are no more files when searching the directory
\item 0xE5 - marks a free slot; this is used when a file is deleted \item 0xE5 -- marks a free slot; this is used when a file is deleted
\item 0x05 - indicates that the first byte should actually be 0xE5, a code used in some character sets at the time, and the slot is \textit{not} free\footnote{The special meaning of 0xE5 appears to be a correction of a less than ideal design choice earlier in the development of the file system}. \item 0x05 -- indicates that the first byte should actually be 0xE5, a code used in some character sets at the time, and the slot is \textit{not} free\footnote{The special meaning of 0xE5 appears to be a correction of a less than ideal design choice earlier in the development of the file system}.
\item Any other value, except 0x20 (space) and characters forbidden in a DOS file name, starts a valid file entry. Generally, only space, A-Z, 0-9, \verb|-| and \verb|_| should be used in file names for maximum compatibility. \item Any other value, except 0x20 (space) and characters forbidden in a DOS file name, starts a valid file entry. Generally, only space, A--Z, 0--9, \verb|-| and \verb|_| should be used in file names for maximum compatibility.
\end{itemize} \end{itemize}
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. 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. \Cref{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] \begin{figure}[h]
\centering \centering
@ -101,13 +101,13 @@ The FAT16 file system is relatively straightforward to implement. However, it is
\subsection{DAPLink Emulator} \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 \cref{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. 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} \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 \cref{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}. 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}.

@ -2,7 +2,7 @@
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. 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 \cref{sec:tinyframe,sec:units-overview}.
\iffalse \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. 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.
@ -22,12 +22,12 @@ 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. 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 \cref{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). 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} \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 \cref{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.
@ -45,7 +45,7 @@ Now that GEX is connected and configured, the user can start using it. This invo
\section{Internal Structure Block Diagram} \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 \cref{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] \begin{figure}[h]
\centering \centering
@ -55,19 +55,19 @@ The data flows and other internal logic of the firmware are depicted in figure~\
\section{FreeRTOS Synchronization Objects Usage} \section{FreeRTOS Synchronization Objects Usage}
The firmware is built on FreeRTOS (\ref{sec:freertos}) and a number of its synchronization objects and patterns are used to make its operation more robust. The firmware is built on FreeRTOS (\cref{sec:freertos}) and a number of its synchronization objects and patterns are used to make its operation more robust.
\subsection{Message and Job Queue} \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 \cref{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. 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 \cref{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} \section{Functional Blocks} \label{sec:units-function}
GEX's user-facing functions are implemented in \textit{unit drivers}. Those are mutually independent modules in the firmware that the user can enable and configure using a configuration file. There can be multiple instances of each unit type. However, we are limited by hardware constraints: e.g., there may be only one \gls{ADC} peripheral, two \gls{SPI} ports and so on. The assignment of those hardware resources to units is handled by the \textit{resource registry} (\ref{sec:res-allocation}). GEX's user-facing functions are implemented in \textit{unit drivers}. Those are mutually independent modules in the firmware that the user can enable and configure using a configuration file. There can be multiple instances of each unit type. However, we are limited by hardware constraints: e.g., there may be only one \gls{ADC} peripheral, two \gls{SPI} ports and so on. The assignment of those hardware resources to units is handled by the \textit{resource registry} (\cref{sec:res-allocation}).
Each unit is defined by a section in the configuration file \verb|UNITS.INI|. It is given a name and a \textit{callsign}, which is a number that serves as an address for message delivery. A unit is internally represented by a data object with the following structure: Each unit is defined by a section in the configuration file \verb|UNITS.INI|. It is given a name and a \textit{callsign}, which is a number that serves as an address for message delivery. A unit is internally represented by a data object with the following structure:
@ -79,7 +79,7 @@ Each unit is defined by a section in the configuration file \verb|UNITS.INI|. It
\item A reference to the unit driver \item A reference to the unit driver
\end{itemize} \end{itemize}
The unit driver handles commands sent from the host \gls{PC}, initializes and de-initializes the unit based on its settings, and implements other aspects of the unit's function, such as periodic updates and interrupt handling. Unit drivers may expose public \gls{API} functions to make it possible to control the unit from a different driver, allowing the creation of "macro units". The unit driver handles commands sent from the host \gls{PC}, initializes and de-initializes the unit based on its settings, and implements other aspects of the unit's function, such as periodic updates and interrupt handling. Unit drivers may expose public \gls{API} functions to make it possible to control the unit from a different driver, allowing the creation of ``macro units''.
\section{Source Code Layout} \section{Source Code Layout}
@ -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} \caption{\label{fig:repo-structure} The general structure of the source code repository}
\end{wrapfigure} \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 (\cref{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}. 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}.
@ -128,13 +128,13 @@ The \gls{USB} Device library, which had to be modified to support a composite cl
The core framework forms the skeleton of the firmware and usually doesn't need any changes when new user-facing features are added. It provides the following services: The core framework forms the skeleton of the firmware and usually doesn't need any changes when new user-facing features are added. It provides the following services:
\begin{itemize} \begin{itemize}
\item Hardware resource allocation (\ref{sec:res-allocation}) \item Hardware resource allocation (\cref{sec:res-allocation})
\item Settings storage and loading (\ref{sec:settings-storage}) \item Settings storage and loading (\cref{sec:settings-storage})
\item Functional block (\textit{units}) initialization (\ref{sec:units-function}) \item Functional block (\textit{units}) initialization (\cref{sec:units-function})
\item The communication port with different back-ends: \gls{USB}, \gls{UART}, wireless (\ref{sec:com-ports}) \item The communication port with different back-ends: \gls{USB}, \gls{UART}, wireless (\cref{sec:com-ports})
\item Message sending and delivery (\ref{sec:message_passing}) \item Message sending and delivery (\cref{sec:message_passing})
\item Interrupt management and routing to functional blocks (\ref{sec:irq-routing}) \item Interrupt management and routing to functional blocks (\cref{sec:irq-routing})
\item Virtual mass storage for configuration file editing \item Virtual mass storage for configuration files (explained in \cref{sec:fat16})
\end{itemize} \end{itemize}
When the firmware needs to be ported to a different STM32 microcontroller, the core framework is relatively straightforward to adapt and the whole process can be accomplished in a few hours. The time consuming part is modifying the functional blocks to work correctly with the new device's hardware. When the firmware needs to be ported to a different STM32 microcontroller, the core framework is relatively straightforward to adapt and the whole process can be accomplished in a few hours. The time consuming part is modifying the functional blocks to work correctly with the new device's hardware.
@ -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. 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} (\cref{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. 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.
@ -177,7 +177,7 @@ At start-up, the firmware enables the \gls{USB} peripheral, configures the devic
\subsubsection{USB Connection} \subsubsection{USB Connection}
GEX uses vid:pid \verb|1209:4c60| and the wireless gateway \verb|1209:4c61|. The \gls{USB} interface uses the \gls{CDCACM} \gls{USB} class (\ref{sec:cdc-acm}) and consists of two bulk endpoints with a payload size of up to 64 bytes. GEX uses vid:pid \verb|1209:4c60| and the wireless gateway \verb|1209:4c61|. The \gls{USB} interface uses the \gls{CDCACM} \gls{USB} class (\cref{sec:cdc-acm}) and consists of two bulk endpoints with a payload size of up to 64 bytes.
\subsubsection{Communication UART} \subsubsection{Communication UART}
@ -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. 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 \cref{sec:wireless}.
\subsection{Message Passing} \label{sec:message_passing} \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 \cref{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 \cref{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. 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. 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 \cref{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. 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} \caption{\label{fig:pin-packing}Pin packing}
\end{figure} \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 \cref{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 % here are the unit sections, all following a common pattern
\input{ch.unit.do} \input{ch.unit.do}

@ -14,22 +14,22 @@ 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{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 \cref{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} \subsection{Examples of Devices Using UART}
\begin{itemize} \begin{itemize}
\item \textbf{MH-Z19B} - \gls{NDIR} CO$_2$ concentration sensor \item \textbf{MH-Z19B} -- \gls{NDIR} CO$_2$ concentration sensor
\item \textbf{NEO-M8} - uBlox \gls{GPS} module \item \textbf{NEO-M8} -- uBlox \gls{GPS} module
\item \textbf{ESP8266} with AT firmware - a WiFi module \item \textbf{ESP8266} with AT firmware -- a WiFi module
\item \textbf{MFRC522} - \gls{NFC} MIFARE reader/writer \gls{IC} (also supports other interfaces) \item \textbf{MFRC522} -- \gls{NFC} MIFARE reader/writer \gls{IC} (also supports other interfaces)
\end{itemize} \end{itemize}
\section{SPI} \label{sec:theory-spi} \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 \cref{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] \begin{figure}[h]
\centering \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} \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} \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 \cref{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). \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).
@ -51,15 +51,15 @@ Transmission and reception on the \gls{SPI} bus happen simultaneously. A bus mas
\subsection{Examples of Devices Using SPI} \subsection{Examples of Devices Using SPI}
\begin{itemize} \begin{itemize}
\item \textbf{SX1276} - LoRa transceiver \item \textbf{SX1276} -- LoRa transceiver
\item \textbf{nRF24L01+} - 2.4\,GHz ISM band radio module \item \textbf{nRF24L01+} -- 2.4\,GHz ISM band radio module
\item \textbf{L3GD20} - 3-axis gyroscope \item \textbf{L3GD20} -- 3-axis gyroscope
\item \textbf{BMP280} - pressure sensor \item \textbf{BMP280} -- pressure sensor
\item \textbf{BME680} - air quality sensor \item \textbf{BME680} -- air quality sensor
\item \textbf{ENC28J60} - Ethernet controller \item \textbf{ENC28J60} -- Ethernet controller
\item \textbf{L6470} - intelligent stepper motor driver \item \textbf{L6470} -- intelligent stepper motor driver
\item \textbf{AD9833} - waveform generator (\gls{MOSI} only) \item \textbf{AD9833} -- waveform generator (\gls{MOSI} only)
\item \textbf{ADE7912} - triple $\Sigma$-$\Delta$ \gls{ADC} for power metering applications \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 \item SPI-interfaced EEPROM and Flash memories
\end{itemize} \end{itemize}
@ -71,7 +71,7 @@ It uses two connections (plus \gls{GND}): \gls{SDA} and \gls{SCL}, both open-dra
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 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 \cref{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.
@ -86,10 +86,10 @@ The bus supports multi-master operation, which leads to the problem of collision
\subsection{Examples of Devices Using \IIC} \subsection{Examples of Devices Using \IIC}
\begin{itemize} \begin{itemize}
\item \textbf{APDS-9960} - ambient light, proximity and gesture sensor \item \textbf{APDS-9960} -- ambient light, proximity and gesture sensor
\item \textbf{L3GD20}, \textbf{BMP280}, \textbf{BME680} - listed as \gls{SPI} devices, those also support \gls{I2C} \item \textbf{L3GD20}, \textbf{BMP280}, \textbf{BME680} -- listed as \gls{SPI} devices, those also support \gls{I2C}
\item \textbf{DS1307} - \gls{RTC}; \gls{I2C} is not mentioned in the entire datasheet, presumably to avoid paying license fees, but it is fully compatible \item \textbf{DS1307} -- \gls{RTC}; \gls{I2C} is not mentioned in the entire datasheet, presumably to avoid paying license fees, but it is fully compatible
\item \textbf{IS31FL3730} - a \gls{LED} matrix driver \item \textbf{IS31FL3730} -- a \gls{LED} matrix driver
\item The \gls{SCCB} used to configure camera modules is derived from \gls{I2C} \item The \gls{SCCB} used to configure camera modules is derived from \gls{I2C}
\end{itemize} \end{itemize}
@ -112,8 +112,8 @@ Devices are addressed by their unique 64-bit ID numbers called ROM codes or ROMs
\subsection{Examples of Devices Using 1-Wire} \subsection{Examples of Devices Using 1-Wire}
\begin{itemize} \begin{itemize}
\item \textbf{DS1820}, \textbf{DS18S20}, \textbf{DS18B20} - digital thermometers \item \textbf{DS1820}, \textbf{DS18S20}, \textbf{DS18B20} -- digital thermometers
\item \textbf{iButton} - contact-read access tokens, temperature loggers, etc. \item \textbf{iButton} -- contact-read access tokens, temperature loggers, etc.
\end{itemize} \end{itemize}
Since 1-Wire is a proprietary protocol, there is a much smaller choice of available devices and they also tend to be more expensive. The DS18x20 thermometers are, however, popular enough to warrant the bus's inclusion in GEX. Since 1-Wire is a proprietary protocol, there is a much smaller choice of available devices and they also tend to be more expensive. The DS18x20 thermometers are, however, popular enough to warrant the bus's inclusion in GEX.
@ -132,7 +132,7 @@ Since 1-Wire is a proprietary protocol, there is a much smaller choice of availa
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 \cref{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. 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,6 +1,6 @@
\chapter{Non-communication Hardware Functions} \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 \cref{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} \section{Frequency Measurement} \label{sec:theory-fcap}
@ -10,13 +10,13 @@ Applications like motor speed measurement and the reading of a \gls{VCO} or \gls
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} \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} (\cref{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. 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} (\cref{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. 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} \caption{\label{fig:fcap-reci-dia}Reciprocal frequency measurement method}
\end{figure} \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 \cref{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] \begin{figure}[h]
\centering \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.} \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} \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 \cref{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. 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,7 +62,7 @@ A very common need in experiments involving the measurement of physical properti
\caption{\label{fig:adc-sar}A diagram of the SAR type ADC} \caption{\label{fig:adc-sar}A diagram of the SAR type ADC}
\end{figure} \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 \cref{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:
@ -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} \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 \cref{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] \begin{figure}[h]
\centering \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} \caption{\label{fig:wavegen-dds}A block diagram of a DDS-based waveform generator}
\end{figure} \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 \cref{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. 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 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 \cref{fig:disco-touch}.
\begin{figure}[h] \begin{figure}[h]
\centering \centering
@ -145,7 +145,7 @@ Capacitive sensing is a sequential process described in the following steps:
\end{enumerate} \end{enumerate}
\noindent \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 \cref{fig:tsc-wfm}.
\begin{figure} \begin{figure}
\centering \centering

@ -2,7 +2,7 @@
Prototyping, design evaluation, and the measurement of physical properties in experiments make a daily occurrence in the engineering praxis. Those tasks often involve the generation and sampling of electrical signals coming to and from sensors, actuators, and other circuitry. Prototyping, design evaluation, and the measurement of physical properties in experiments make a daily occurrence in the engineering praxis. Those tasks often involve the generation and sampling of electrical signals coming to and from sensors, actuators, and other circuitry.
In the recent years, a wide range of intelligent sensors became available thanks to the drive for miniaturization in the consumer electronics industry. Those devices often provide sufficient accuracy and precision while keeping the circuit complexity and cost low. In contrast to analog sensors, here the signal conditioning and processing circuits are built into the sensor itself, and we access it using a digital connection. Recently, a wide range of intelligent sensors became available thanks to the drive for miniaturization in the consumer electronics industry. Those devices often provide sufficient accuracy and precision while keeping the circuit complexity and cost low. In contrast to analog sensors, here the signal conditioning and processing circuits are built into the sensor itself, and we access it using a digital connection.
\begin{figure}[H] \begin{figure}[H]
\centering \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} \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 \cref{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 \iffalse
\begin{figure}[H] \begin{figure}[H]

@ -1,6 +1,6 @@
\chapter{Client Software} \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 \cref{sec:tinyframe,sec:units-overview}, respective \cref{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} \section{General Library Structure}
@ -19,9 +19,9 @@ The structure of a GEX support library is in all cases similar:
\item \textbf{Higher-level GEX logic} \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. The host side of the communication protocol described in \cref{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. Additional utilities may be defined on top of this basic protocol support for the command API of different GEX units, as described in \cref{sec:units-overview}. Those unit-specific ``drivers'' are available in the provided Python library.
\end{itemize} \end{itemize}
\section{Python Library} \section{Python Library}
@ -38,9 +38,9 @@ The library is composed of a \textit{transport}, the core class called \textit{c
\item \mono{TrxRawUSB} -- similar to \mono{TrxSerialThread}, but using a raw USB endpoint access \item \mono{TrxRawUSB} -- similar to \mono{TrxSerialThread}, but using a raw USB endpoint access
\end{itemize} \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 \cref{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 \cref{fig:pydemo}.
\todo[inline]{add left line next to this listing} \todo[inline]{add left line next to this listing}
\begin{minted}{python} \begin{minted}{python}

@ -28,13 +28,13 @@ Generating an analog signal is possible using a \gls{PWM} or by a dedicated digi
\subsection{Logic Level Input and Output} \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 \cref{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} \subsection{Pulse Generation and Measurement}
Some sensors have a variable frequency or a \gls{PWM} output. To capture those signals and convert them to a more useful digital value, we can use the external input functions of a timer/counter in the microcontroller. Those timers have many possible configurations and can also be used for pulse counting or a pulse train generation. Some sensors have a variable frequency or a \gls{PWM} output. To capture those signals and convert them to a more useful digital value, we can use the external input functions of a timer/counter in the microcontroller. Those timers have many possible configurations and can also be used for pulse counting or a pulse train generation.
\section{Host Computer Connection} \section{Connection to the Host Computer}
\subsection{Communication Interface} \subsection{Communication Interface}
@ -83,7 +83,7 @@ Let's now summarize the features we wish to support in the GEX firmware, based o
\section{Microcontroller Selection} \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 \cref{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. 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} \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 \cref{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 \cref{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] \begin{figure}[h]
\centering \centering

@ -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. 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. \Cref{fig:bulk-rw} shows a diagram of the bulk read and write data flow.
\begin{figure} \begin{figure}
\centering \centering

@ -1,6 +1,6 @@
\section{1-Wire Unit} \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 \cref{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. 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 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 \cref{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} \subsection{DAC Configuration}
@ -26,9 +26,9 @@ ch2_noise-level=3
Channels are specified in all commands as a bit map: Channels are specified in all commands as a bit map:
\begin{itemize}[nosep] \begin{itemize}[nosep]
\item 0x01 - channel 1 \item 0x01 -- channel 1
\item 0x02 - channel 2 \item 0x02 -- channel 2
\item 0x03 - both channels affected at once \item 0x03 -- both channels affected at once
\end{itemize} \end{itemize}
\begin{cmdlist} \begin{cmdlist}

@ -1,6 +1,6 @@
\section{Digital Output} \section{Digital Output}
The digital output unit provides a write access to one or more pins of a \gls{GPIO} port. This unit additionally supports pulse generation on any of its pins; this is implemented in software, with timing derived from the system timebase, in order to support pulses on all pins regardless of hardware \gls{PWM} support. Pins in commands are expressed in the packed format (\ref{sec:packedpins}). The digital output unit provides a write access to one or more pins of a \gls{GPIO} port. This unit additionally supports pulse generation on any of its pins; this is implemented in software, with timing derived from the system timebase, in order to support pulses on all pins regardless of hardware \gls{PWM} support. Pins in commands are expressed in the packed format (\cref{sec:packedpins}).
\subsection{Digital Output Configuration} \subsection{Digital Output Configuration}

@ -1,7 +1,7 @@
\section{Frequency Capture Unit} \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 \cref{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. 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} \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 \cref{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. 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} \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 \cref{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. 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} \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 \cref{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 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 \cref{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] \begin{figure}[h]
\centering \centering
@ -42,7 +42,7 @@ pins=0
\begin{cmdlist} \begin{cmdlist}
0 & \cname{QUERY} 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 \cref{fig:spi_query}
& \begin{cmdreq} & \begin{cmdreq}
\cfield{u8} slave number 0--16 \cfield{u8} slave number 0--16
\cfield{u16} response padding \cfield{u16} response padding
@ -55,7 +55,7 @@ pins=0
\end{cmdresp} \\ \end{cmdresp} \\
1 & \cname{MULTICAST} 1 & \cname{MULTICAST}
Send a message to multiple slaves at once. The ``addressed slaves'' word uses the packed pins format (\ref{sec:packedpins}). Send a message to multiple slaves at once. The ``addressed slaves'' word uses the packed pins format (\cref{sec:packedpins}).
& \begin{cmdreq} & \begin{cmdreq}
\cfield{u16} addressed slaves \cfield{u16} addressed slaves
\cfield{u8[]} bytes to write \cfield{u8[]} bytes to write

@ -1,6 +1,6 @@
\section{Touch Sense Unit} \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 \cref{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} \subsection{Touch Sense Configuration}

@ -1,6 +1,6 @@
\section{USART Unit} \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 \cref{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. 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.

@ -29,10 +29,10 @@ Endpoints can be either unidirectional or bidirectional; the direction from the
There are four types of data transfers defined in \gls{USB}: control, bulk, isochronous, and interrupt. Each endpoint is configured for a fixed transfer type: There are four types of data transfers defined in \gls{USB}: control, bulk, isochronous, and interrupt. Each endpoint is configured for a fixed transfer type:
\begin{itemize} \begin{itemize}
\item \textit{Control} - initial configuration after device plug-in; also used for other aplication-specific control messages that can affect other pipes. \item \textit{Control} -- initial configuration after device plug-in; also used for other aplication-specific control messages that can affect other pipes.
\item \textit{Bulk} - used for burst transfers of large messages, commonly e.g. for mass storage devices \item \textit{Bulk} -- used for burst transfers of large messages, commonly e.g. for mass storage devices
\item \textit{Isochronous} - streaming with guaranteed low latency; designed for audio or video streams where some data loss is preferred over stuttering \item \textit{Isochronous} -- streaming with guaranteed low latency; designed for audio or video streams where some data loss is preferred over stuttering
\item \textit{Interrupt} - low latency short messages, used for human interface devices like mice and keyboards \item \textit{Interrupt} -- low latency short messages, used for human interface devices like mice and keyboards
\end{itemize} \end{itemize}
\subsection{Interfaces and Classes} \subsection{Interfaces and Classes}
@ -51,7 +51,7 @@ 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 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 \cref{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 \newpage
\input{fig.gex-descriptors} \input{fig.gex-descriptors}
@ -62,7 +62,7 @@ The descriptor table used by GEX is captured in figure~\ref{fig:gex-descriptors}
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. 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 \cref{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] \begin{figure}[h]
\centering \centering
@ -96,7 +96,7 @@ Unfortunately, the \gls{SCSI} Transparent command set appears to have been delib
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. 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 \cref{sec:fat16}.
\subsection{CDC/ACM Class} \label{sec:cdc-acm} \subsection{CDC/ACM Class} \label{sec:cdc-acm}

@ -12,7 +12,7 @@ The Semtech SX1276~\cite{semtech-manual} and Nordic Semiconductor nRF24L01+ ~\ci
\section{Modulations Overview} \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 \cref{fig:nrf-sx-comparison} and the rest of the chapter.
\subsection{On-Off Keying (OOK)} \subsection{On-Off Keying (OOK)}
@ -40,7 +40,7 @@ LoRa is a patented proprietary modulation developed by Semtech. It uses a direct
\section{Comparing SX1276 and nRF24L01+} \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 \cref{fig:nrf-sx-comparison}. It is apparent that each of them has its strengths and weaknesses, which will be discussed below.
\begin{table}[h] \begin{table}[h]
\centering \centering
@ -90,7 +90,7 @@ A separate device, the \textit{GEX wireless gateway}, was developed to provide t
\caption{A block diagram of the wireless connection} \caption{A block diagram of the wireless connection}
\end{wrapfigure} \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 \cref{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. 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.

@ -70,6 +70,8 @@
urlcolor={blue!80!black} urlcolor={blue!80!black}
} }
\usepackage[nameinlink,capitalize,noabbrev]{cleveref}
%% ACRONYM CONFIG %% ACRONYM CONFIG
\usepackage[xindy,nonumberlist,nomain,acronym,nopostdot,toc=false]{glossaries} \usepackage[xindy,nonumberlist,nomain,acronym,nopostdot,toc=false]{glossaries}

@ -6,7 +6,7 @@
front-list-of-tables = true, front-list-of-tables = true,
mainlanguage = english, mainlanguage = english,
% %
author = {Ondřej Hruška}, author = {Bc. Ondřej Hruška},
supervisor = {doc. Ing. Radislav Šmíd, Ph.D.}, supervisor = {doc. Ing. Radislav Šmíd, Ph.D.},
% %
title-english = {Learning and automation GPIO platform}, title-english = {Learning and automation GPIO platform},

Binary file not shown.
Loading…
Cancel
Save