prettifying of the tinyframe payload boxes etc

master
Ondřej Hruška 6 years ago
parent 73129df46e
commit 5c6b34f949
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 22
      ch.fat16.tex
  2. 9
      ch.gex_units.tex
  3. 2
      ch.hw_functions.tex
  4. 6
      ch.requirements.tex
  5. 128
      ch.tinyframe.tex
  6. 2
      ch.unit.1wire.tex
  7. 2
      ch.unit.adc.tex
  8. 2
      ch.unit.di.tex
  9. 6
      ch.unit.i2c.tex
  10. 12
      ch.usb.tex
  11. 110
      ch.wireless.tex
  12. 2
      document_config.tex
  13. 37
      pre.gex_command_tables.tex
  14. 2
      pre.utils.tex
  15. 4
      thesis.acronyms.tex
  16. BIN
      thesis.pdf
  17. 1
      thesis.tex

@ -17,11 +17,11 @@ The storage medium is organized into \textit{sectors} (or \textit{blocks}), usua
\textbf{Disk area} & \textbf{Size / Notes} \\
\midrule
Boot sector & 1 sector \\
Reserved sectors & optional \\
FAT 1 & 1 or more sectors, depends on disk size \\
FAT 2 & optional, a back-up copy of FAT 1 \\
Root directory & 1 or more sectors \\
Data area & Organized in \textit{clusters} \\
Reserved sectors & optional \\
FAT 1 & 1 or more sectors, depends on disk size \\
FAT 2 & optional, a back-up copy of FAT 1 \\
Root directory & 1 or more sectors \\
Data area & Organized in \textit{clusters} \\
\bottomrule
\end{tabular}
\caption{\label{tab:fat16-disk-areas}Areas of a FAT-formatted disk}
@ -35,7 +35,7 @@ This is a 1-sector structure which holds the \gls{OS} bootstrap code for bootabl
The data area of the disk is organized in clusters, logical allocation units composed of groups of sectors. The use of a larger allocation unit allows the system to use shorter addresses and thus support a larger disk capacity.
The \gls{FAT} acts as a look-up table combined with linked lists. In FAT16, it is organized in 16-bit fields, each corresponding to one cluster. The first two entries in the allocation table are reserved and hold special values set by the disk formatter and the host \gls{OS}: a "media descriptor" 0xFFF8 and a "clean/dirty flag" 0xFFFF/0x3FFF.
The \gls{FAT} acts as a look-up table combined with linked lists. In FAT16, it is organized in 16-bit fields, each corresponding to one cluster. The first two entries in the allocation table are reserved and hold special values set by the disk formatter and the host \gls{OS}: a "media descriptor" 0xFFF8 and a "clean/dirty flag" 0xFFFF/0x3FFF.
Files can span multiple clusters; each \gls{FAT} entry either holds the address of the following file cluster, or a value with a special meaning:
@ -72,7 +72,7 @@ The root directory has the same structure as any other directories, which reside
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. Longer file names are encoded using a \gls{LFN} scheme as special hidden entries stored in the directory table alongside the regular 8.3 entries, ensuring backward compatibility.
The name and extension fields form together the well-known 8.3 filename format. Longer file names are encoded using a \gls{LFN} scheme as special hidden entries stored in the directory table alongside the regular 8.3 entries, ensuring backward compatibility.
The first byte of the file name has a special meaning:
@ -112,7 +112,7 @@ Now, just one problem remains: how to tell which sectors contain which part of o
\subsection{Handling a Write Access}
A file write access is more challenging to emulate than a read access, as the host OS tends to be somewhat unpredictable. In GEX's case we're interested only in the action of overwriting an already existing file, but it's interesting to also analyze other actions the host may perform.
A file write access is more challenging to emulate than a read access, as the host OS tends to be somewhat unpredictable. In GEX's case we're interested only in the action of overwriting an already existing file, but it's interesting to also analyze other actions the host may perform.
It must be noted that due to the nonexistence of a physical storage medium, it's not possible to read back a file the host has written. The \gls{OS} may show the written file on the disk, but when the user tried to read it, it either fails, or shows a cached copy. In the DAPLink emulator this is worked around by temporarily reporting that the storage medium has been removed, forcing the host to re-load its contents. In GEX, the loaded INI file will be a newly generated copy, embedding possible error messages as comments.
@ -123,7 +123,7 @@ A file is deleted by:
\begin{enumerate}
\item Marking all sectors used by it as free in the \gls{FAT}
\item Replacing the first character of its name in the directory table by 0xE5 to indicate the slot is free
\end{enumerate}
\end{enumerate}
From the perspective of emulation, we can ignore the \gls{FAT} access and only detect writes to the directory sectors. This is slightly more complicated when one considers that all disk access is performed in sectors: the emulator must compare the written data with the original bytes to detect what change has been performed. Alternatively, we could parse the written sector as a directory table and compare it with our knowledge of its original contents.
@ -143,7 +143,7 @@ A new file is created in three steps:
It can be expected the host \gls{OS} first finds the free sectors and a free file entry before performing any write operations, to prevent a potential disk corruption.
To properly handle such a file by the emulator, we could, in theory, find its name from the directory table, which has been updated, and then collect the data written to the corresponding clusters. In practice, confirmed by experiments with a real Linux host, those three steps may happen in any order, and often the content is written before the directory table is updated.
To properly handle such a file by the emulator, we could, in theory, find its name from the directory table, which has been updated, and then collect the data written to the corresponding clusters. In practice, confirmed by experiments with a real Linux host, those three steps may happen in any order, and often the content is written before the directory table is updated.
The uncertain order of the written disk areas poses a problem when the file name has any significance, as we can't store the received file data while waiting for the name to be written. The DAPLink mbed flashing firmware solves this by analyzing the content of the first written sector of the file, which may contain the binary \gls{NVIC} table, or a character pattern typical for Intel hex files.
@ -151,7 +151,7 @@ The uncertain order of the written disk areas poses a problem when the file name
A change to a file's content is performed in a similar way to the creation of a new file, except instead of creating a new entry in the directory table, an existing one is updated with the new file size. The name of the file may be, again, unknown until the content is written, but we could detect the file by comparing the starting sector with those of all files known to the virtual file system.
In the case of GEX, the detection of a file name is not important; We expect only INI files to be written, and the particular file may be detected by its first section marker, such as \verb|[UNITS]| or \verb|[SYSTEM]|. Should a non-INI file be written by accident, the INI parser will likely detect a syntax error and discard it.
In the case of GEX, the detection of a file name is not important; we expect only INI files to be written, and the particular file may be detected by its first section marker, such as \verb|[UNITS]| or \verb|[SYSTEM]|. Should a non-INI file be written by accident, the INI parser will likely detect a syntax error and discard it.
It should be noted that a file could be updated only partially, skipping the clusters which remain unchanged, and there's also no guarantee regarding the order in which the file's sectors are written. This is hard to detect and handle and the current firmware is not able to interpret it correctly, thus such a write operation will fail. Fortunately, this host behavior has not been conclusively observed in practice, but a write operation rarely fails for still unknown reasons and this could be a possible cause.

@ -1,17 +1,16 @@
\chapter{Units Overview, Commands and Events Description}
This chapter describes all functional blocks (units) implemented in GEX at the time of publication of this work. Each unit supports a different set of binary commands and events. The term ``unit'' will be used 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.
\todo[inline]{link to the chapter about tinyframe as it's important for context here}
\todo[inline]{also some diagram here}
Each unit's description will be accompanied by a corresponding snippet from the configuration file, and a list of supported commands and events. The commands and events described here form the payload of TinyFrame messages 0x10 (Unit Request) and 0x11 (Unit Report), as described in section \ref{sec:unit_requests_reports}. The number in the first column of the command (or event) tables, marked as ``Code'', is the command number (or report type) used in the payload to identify how the message data should be treated.
Each unit's description will be accompanied by a corresponding snippet from the configuration file, and a list of supported commands and events. When the command's request payload is empty, it's 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 if the command succeeds.
When the request or response payload is empty, it's 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.
\section{Naming Conventions and Common Principles}
\subsection{Unit Naming}
Unit types are named in uppercase (e.g. SPI, 1WIRE, NPX) in the INI file and in the list of units. Unit instances can be named in any way the user desires; Using lowercase makes it easier to distinguish them from unit types. It is advisable to use descriptive names, e.g. not ``pin1'' but rather ``button''.
Unit types are named in uppercase (e.g. SPI, 1WIRE, NPX) in the INI file and in the list of units. Unit instances can be named in any way the user desires; using lowercase makes it easier to distinguish them from unit types. It is advisable to use descriptive names, e.g. not ``pin1'' but rather ``button''.
\subsection{Packed Pin Access}

@ -53,7 +53,7 @@ The system clock's frequency, which we use to measure pulse lengths and to gate
A very common need in experiments involving the measurement of physical properties is the acquisition of analog signals, respective voltages. Those can be roughly divided into \gls{DC} and \gls{AC} or time-changing signals. Analog signals are converted to digital values using \glspl{ADC}. Several principles of analog signal measurement exist with different cost, speed, resolution, and many other factors which determine their suitability for a particular application.
\gls{DC} signals can be measured by taking several samples and calculating their average value; In the presence of a 50\,Hz or 60\,Hz mains interference, its advisable to spread those samples over the 20\,ms (resp. 16.7\,ms) time of one period so that the interfering waveform cancels out. Time-changing signals can be captured by taking isochronous samples at a frequency conforming to the Nyquist theorem, that is, at least twice that of the measured signal. In practice, a frequency several times higher is preferred for a more accurate capture.
\gls{DC} signals can be measured by taking several samples and calculating their average value; in the presence of a 50\,Hz or 60\,Hz mains interference, its advisable to spread those samples over the 20\,ms (resp. 16.7\,ms) time of one period so that the interfering waveform cancels out. Time-changing signals can be captured by taking isochronous samples at a frequency conforming to the Nyquist theorem, that is, at least twice that of the measured signal. In practice, a frequency several times higher is preferred for a more accurate capture.
\begin{figure}
\centering

@ -44,7 +44,7 @@ A common characteristic of those buses is that they require precise timing and h
Microcontrollers typically include a 10-12 bit ADC (\textit{Analog to Digital Converter}), often accompanied by a DAC (\textit{Digital to Analog Converter}), its output counterpart. In the lack of a real DAC, the analog output, albeit with worse dynamic parameters, can be realized using a PWM signal (\textit{Pulse Width Modulation}, pulse train) followed by a low-pass filter.
While we mainly focused on digital interfaces thus far, providing means of generating and capturing analog signals is also valuable. This capability makes it possible to read sensors with voltage output and it can substitute a simple oscilloscope when sampled periodically at a sufficient speed.
While we mainly focused on digital interfaces thus far, providing means of generating and capturing analog signals is also valuable. This capability makes it possible to read sensors with voltage output and it can substitute a simple oscilloscope when sampled periodically at a sufficient speed.
The analog output and input together can be used for automated characterization of electronic components, or for analog feedback regulation. Should the analog output be modulated, we could further use them to measure frequency-dependent characteristics, such as the frequency response of analog filters.
@ -66,7 +66,7 @@ We could load those settings into GEX using the serial interface, and indeed thi
It has been established that the designed device should be small and easily portable. It should support USB and wireless connection to a PC. Further, a plain UART interface should be offered in place of USB; this makes it easier to integrate GEX into other systems or use development kits fitted with a USB-UART converter.
The following protocols and features should be implemented as a minimum; Other functions may be added based on input from prototype testing in model situations.
The following protocols and features should be implemented as a minimum; other functions may be added based on input from prototype testing in model situations.
\begin{itemize}
\item Low level hardware functions
@ -93,7 +93,7 @@ The following protocols and features should be implemented as a minimum; Other f
\end{itemize}
\end{itemize}
Considering the requirements, availability, and cost, the STM32F072 microcontroller will be used for the first prototypes, with the expectation of later porting the project to more powerful or power-efficient devices, like the STM32L072, STM32F103, STM32F303, or other STM32 microcontrollers.
Considering the requirements, availability, and cost, the STM32F072 microcontroller will be used for the first prototypes, with the expectation of later porting the project to more powerful or power-efficient devices, like the STM32L072, STM32F103, STM32F303, or other STM32 microcontrollers.
The STM32F072 is a Cortex M0 device with 128\,KiB of flash memory, 16\,KiB of RAM and running at up to of 48\,MHz. It is equipped with a USB Full Speed peripheral block, a 12-bit ADC and DAC, a number of general purpose timers/counters, SPI, I$^2$C, and USART peripherals. It further supports a crystal-less USB operation, using the USB SOF packet for synchronization.

@ -8,8 +8,19 @@ GEX uses a framing library \textit{TinyFrame}, developed likewise by the author
\section{Frame Structure}
Message frames have the following structure:
Message frames have the following structure (all little-endian):
\begin{boxedpayload}[``TinyFrame'' frame structure, as used in GEX]
\cfield{u8} start-of-frame marker (0x01)
\cfield{u16} frame ID
\cfield{u16} payload length
\cfield{u8} frame type
\cfield{u8} header checksum
\cfield{u8[]} payload
\cfield{u8} payload checksum (omitted for empty payloads)
\end{boxedpayload}
\iffalse
\begin{table}[h]
\centering
%\hspace{-1.5em}
@ -42,8 +53,7 @@ Message frames have the following structure:
\bottomrule
\end{tabular}
\end{table}
The field widths shown here are those used in GEX; TinyFrame is flexible and the data type of all fields can be customized, as well as the checksum type. The SOF byte is always 0x01.
\fi
\textit{Frame ID}, which could be better described as \textit{Transaction ID}, uniquely identifies each transaction. The most significant bit is set to a different value in each peer to avoid ID conflicts, and the rest of the ID field is incremented with each initiated transaction.
@ -73,7 +83,7 @@ The following table lists all frame types used by GEX. It is divided into four l
0x04 & Bulk Read Poll & \textit{Requesting to read a block of data} \\
0x05 & Bulk Write Offer & \textit{An offer to receive a bulk write transaction} \\
0x06 & Bulk Data & \textit{Used for both reading and writing} \\
0x07 & Bulk End & \textit{Marks the last "Bulk Data" frame} \\
0x07 & Bulk End & \textit{Marks the last ``Bulk Data'' frame} \\
0x08 & Bulk Abort & \textit{} \\
\midrule
0x10 & Unit Request & \textit{Request to a unit} \\
@ -108,52 +118,50 @@ Figure \ref{fig:bulk-rw} shows a diagram of the bulk read and write data flow.
To read an INI file, we first send a frame 0x21 (INI Read), specifying the target file in the payload:
\begin{minted}{c}
struct Payload_INI_Read {
uint8_t filenum; // 0 - UNITS.INI, 1 - SYSTEM.INI
};
\end{minted}
\begin{boxedpayload}[INI Read frame structure]
\cfield{u8} which file to write
\begin{pldlist}
\item 0 \dots UNITS.INI
\item 1 \dots SYSTEM.INI
\end{pldlist}
\end{boxedpayload}
What follows is a standard bulk read transaction with the requested file.
GEX offers the file for reading with a frame 0x03 (Bulk Read Offer):
\begin{minted}{c}
struct Payload_BulkReadOffer {
uint32_t total_length; // full size of the file in bytes
uint32_t max_chunk_size; // largest chunk that can be read at once
};
\end{minted}
\begin{boxedpayload}[Bulk Read frame structure]
\cfield{u32} full size of the file in bytes
\cfield{u32} largest chunk that can be read at once
\end{boxedpayload}
Now we can proceed to read the file using 0x04 (Bulk Read Poll), which is always responded to with 0x06 (Bulk Data), or 0x07 (Bulk End) if this was the last frame. Data frames have only the useful data as their payload.
The 0x04 (Bulk Read Poll) payload specifies how many bytes we want to read:
\begin{minted}{c}
struct Payload_BulkReadPoll {
uint32_t max_chunk_size; // how many bytes to read
};
\end{minted}
\begin{boxedpayload}[Bulk Read Poll frame structure]
\cfield{u32} how many bytes to read (at most)
\end{boxedpayload}
\subsection{Bulk Write}
To overwrite an INI file, we first send a frame 0x22 (INI Write), specifying its size in the payload. Which file is written is detected automatically from the first INI section.
To overwrite an INI file, we first send a frame 0x22 (INI Write) with the file size as its payload. The name of the file is irrelevant, as it's detected automatically by inspecting the content.
\begin{minted}{c}
struct Payload_INI_Write {
uint32_t total_length; // file size in bytes
};
\end{minted}
\begin{boxedpayload}[INI Write frame structure]
\cfield{u32} size of the written file, in bytes
\end{boxedpayload}
The write request is confirmed by a frame 0x05 (Bulk Write Offer):
The write request is confirmed by a frame 0x05 (Bulk Write Offer) sent back:
\begin{minted}{c}
struct Payload_BulkWriteOffer {
uint32_t total_length; // the expected file size in bytes
uint32_t max_chunk_size; // largest chunk that can be written at once
};
\end{minted}
\begin{boxedpayload}[Bulk Write Offer frame structure]
\cfield{u32} total bytes to write (here copied from the request frame)
\cfield{u32} how many bytes may be written per message
\end{boxedpayload}
We can now send the file as a series of frames 0x06 (Bulk Data), or 0x07 (Bulk End) in the last frame. Each written chunk is confirmed by 0x00 (Success).
We can now send the file as a series of frames 0x06 (Bulk Data), or 0x07 (Bulk End) in the last frame, with chunks of the data as their payload. Each frame is confirmed by 0x00 (Success).
\begin{boxedpayload}[Bulk Data or Bulk End frame structure]
\cfield{u8[]} a chunk of the written file
\end{boxedpayload}
\subsection{Persisting the Changed Configuration to Flash}
@ -166,21 +174,20 @@ It should be noted that after flashing a firmware, the Flash control registers m
\section{Reading a List of Units}
The frame 0x20 (List Units) requests a list of all available units in the GEX module. The list includes all units' callsigns, names and types. The response payload has the following format (in pseudocode, as it can't be expressed as a C struct like the previous examples):
The frame 0x20 (List Units) requests a list of all available units in the GEX module. The list includes all units' callsigns, names and types. The response payload has the following format (in pseudocode):
\begin{minted}{c}
struct {
uint8_t count;
for all units {
uint8_t callsign;
cstring unit_name; // 0-terminated char array
cstring driver_name;
}
}
\end{minted}
\begin{boxedpayload}[List Units response structure (frame type Success)]
\cfield{u8} the number of available units
\item For each unit:
\begin{pldlist}
\cfield{u8} unit callsign
\cfield{char[]} unit name (zero-terminated string)
\cfield{char[]} unit type (zero-terminated string)
\end{pldlist}
\end{boxedpayload}
\section{Unit Requests and Reports}
\section{Unit Requests and Reports} \label{sec:unit_requests_reports}
Frame types 0x10 (Unit Request) and 0x11 (Unit Report) are dedicated to messages sent to and by unit instances. Each has a fixed header (\textit{inside the payload}) followed by unit-specific data.
@ -188,13 +195,11 @@ Frame types 0x10 (Unit Request) and 0x11 (Unit Report) are dedicated to messages
Unit requests deliver a message from the host to a unit instance. Unit drivers implements different commands, each with its own payload structure. The frame 0x10 (Unit Request) has the following structure:
\begin{minted}{c}
struct Payload_UnitRequest {
uint8_t callsign;
uint8_t command; // handled by the unit driver
uint8_t payload[]; // size and content depend on the command
};
\end{minted}
\begin{boxedpayload}[Unit Request frame structure]
\cfield{u8} unit callsign
\cfield{u8} command number, handled by the unit driver
\cfield{u8[]} command payload, handled by the unit driver; its size and content depend on the unit driver and the particular command number
\end{boxedpayload}
The most significant bit of the command byte (0x80) has a special meaning: when set, the message delivering routine responds with 0x00 (Success) after the command completes, unless an error occurred. That is used to get a confirmation that the message was delivered and the module operates correctly (as opposed to e.g. a lock-up resulting in a watchdog reset). Requests which normally generate a response (e.g. reading a value from the unit) should not be sent with this bit set. As a result of this special treatment of the highest bit, there can be only 127 different commands per unit.
@ -202,15 +207,12 @@ The most significant bit of the command byte (0x80) has a special meaning: when
Several unit types can produce asynchronous events, such as reporting a pin change or a triggering condition. The event is timestamped and sent with a frame type 0x11 (Unit Report):
\begin{minted}{c}
struct Payload_UnitRequest {
uint8_t callsign;
uint8_t report_type; // defines the payload structure
uint64_t timestamp; // microseconds since power-on
uint8_t payload[]; // size and content depend on the report type
};
\end{minted}
\begin{boxedpayload}[Unit Report (event) frame structure]
\cfield{u8} unit callsign
\cfield{u8} report type, defined by the unit driver
\cfield{u64} event time (microseconds since power-on)
\cfield{u8[]} report payload; its size and content depend on the unit driver and the particular report type
\end{boxedpayload}

@ -2,7 +2,7 @@
The 1-Wire unit implements the Dallas Semiconductor's 1-Wire protocol, most commonly used to interface smart thermometers (DS18x20). The protocol is explained in section \ref{sec:theory-1wire}.
This unit implements the ROM Search algorithm that is used to find the ROM codes of all 1-Wire devices connected to the bus. The algorithm can find up to 32 devices in one run; More devices can be found by issuing the SEARCH\_CONTINUE command.
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.
Devices are addressed using their ROM codes, unique 64-bit (8-byte) identifiers that work as addresses. When only one device is connected, the value 0 may be used instead and the addressing will be skipped. Its ROM code may be recovered using the READ\_ADDR command or by the search algorithm.

@ -1,6 +1,6 @@
\section{ADC Unit}
The analog/digital converter unit is one of the most complicated units implemented in the project. The unit can measure the voltage on an input pin, either as its immediate value, or averaged with exponential forgetting. Isochronous sampling is available as well: It's possible to capture a fixed-length block of data on demand, or as a response to a triggering condition on any of the enabled input pins. The \gls{ADC} must continuously sample the inputs to make the averaging and level based triggering possible; As a consequence, a pre-trigger buffer is available that can be read together with the block of samples following a trigger. The \gls{ADC} unit can also be switched to a continuous streaming mode.
The analog/digital converter unit is one of the most complicated units implemented in the project. The unit can measure the voltage on an input pin, either as its immediate value, or averaged with exponential forgetting. Isochronous sampling is available as well: It's possible to capture a fixed-length block of data on demand, or as a response to a triggering condition on any of the enabled input pins. The \gls{ADC} must continuously sample the inputs to make the averaging and level based triggering possible; as a consequence, a pre-trigger buffer is available that can be read together with the block of samples following a trigger. The \gls{ADC} unit can also be switched to a continuous streaming mode.
It's possible to activate any number of the 16 analog inputs of the \gls{ADC} peripheral simultaneously. The maximum continuous sampling frequency, which reaches 70\,ksps with one channel, lowers with an increasing number of enabled channels as the amount of data to transfer to the host increases.

@ -4,7 +4,7 @@ The digital input unit is the input counterpart of the digital output unit.
In addition to reading the immediate digital levels of the selected pins, this unit can generate asynchronous events on a pin change. The state of the entire input port, together with a microsecond timestamp (as is the case for all asynchronous events), is reported to the host either on a rising, falling, or any pin change.
The pin change event can be configured independently for each pin. In order to receive a pin change event, it must be armed first; The pin can be armed for a single event, or it may be re-armed automatically with a hold-off time. It's further possible to automatically arm selected pin triggers on start-up.
The pin change event can be configured independently for each pin. In order to receive a pin change event, we must arme the pin first; it can be armed for a single event, or it may be re-armed automatically with a hold-off time. It's further possible to automatically arm selected pin triggers on start-up.
\subsection{Digital Input Configuration}

@ -1,8 +1,8 @@
\section{I\textsuperscript{2}C Unit}
\section{\IIC Unit}
The \gls{I2C} unit provides access to one of the microcontroller's \gls{I2C} peripherals. It can be configured to use either of the three 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.
\subsection{I2C Configuration}
\subsection{\IIC Configuration}
\begin{inicode}
[I2C:d@4]
@ -21,7 +21,7 @@ analog-filter=Y
digital-filter=0
\end{inicode}
\subsection{I\textsuperscript{2}C Commands}
\subsection{\IIC Commands}
\begin{cmdlist}

@ -5,7 +5,7 @@ This chapter presents an overview of the \gls{USB} Full Speed interface, with fo
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth] {img/usb-hierarchy.png}
\caption[USB hierarchical structure]{\label{fig:usb-hierarchy}A diagram from the USB specification rev. 1.1 showing the hierarchical structure of the USB bus; The PC (Host) controls the bus and initiates all transactions.}
\caption[USB hierarchical structure]{\label{fig:usb-hierarchy}A diagram from the USB specification rev. 1.1 showing the hierarchical structure of the USB bus; the PC (Host) controls the bus and initiates all transactions.}
\end{figure}
\section{Basic Principles and Terminology}
@ -22,7 +22,7 @@ This chapter presents an overview of the \gls{USB} Full Speed interface, with fo
Endpoints can be either unidirectional or bidirectional; the direction from the host to a function is called OUT, the other direction (function the host) is called IN. A bidirectional endpoint is technically composed of a IN and OUT endpoint with the same number. All transactions (both IN and OUT) are initiated by the host; functions have to wait for their turn. Endpoint 0 is bidirectional, always enabled, and serves as a \textit{control endpoint}. The host uses the control endpoint to read information about the device and configure it as needed.
There are four types of transfers: control, bulk, isochronous, and interrupt. Each endpoint is configured for a fixed transfer type.
There are four types of transfers: control, bulk, isochronous, and interrupt. Each endpoint is configured for a fixed transfer type.
\begin{itemize}
\item \textit{Control} - initial configuration after device plug-in; also used for other aplication-specific control messages that can affect other pipes.
@ -71,7 +71,7 @@ The data lines, D+ and D--, are also commonly labeled DP and DM. This differenti
\caption[USB pull-ups]{\label{fig:usb-pullup-fs}Pull-up and pull-down resistors of a Full Speed function, as prescribed by the USB specification rev. 2.0}
\end{figure}
When a function wants to be re-enumerated by the host, which is needed to reload the descriptors and re-attach the correct drivers, it can momentarily remove the pull-up resistor, which the host will interpret as if the device was plugged out. With an internal pull-up this can be done by flipping a bit in a control register. An external resistor can be connected through a transistor controlled by a \gls{GPIO} pin.
When a function wants to be re-enumerated by the host, which is needed to reload the descriptors and re-attach the correct drivers, it can momentarily remove the pull-up resistor, which the host will interpret as if the device was plugged out. With an internal pull-up this can be done by flipping a bit in a control register. An external resistor can be connected through a transistor controlled by a \gls{GPIO} pin.
\todo[inline]{https://www.eevblog.com/forum/projects/driving-the-1k5-usb-pull-up-resistor-on-d/}
\todo[inline]{http://www.beyondlogic.org/usbnutshell/usb2.shtml}
@ -90,7 +90,7 @@ The \gls{MSC} is supported by all modern operating systems (MS Windows, MacOS, G
%http://www.usb.org/developers/docs/devclass_docs/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf
%http://www.usb.org/developers/docs/devclass_docs/usbmassbulk_10.pdf
The \gls{MSC} specification defines multiple \textit{transport protocols} that can be selected using the descriptors. For it's simplicity, the \gls{BOT} will be used. \gls{BOT} uses two bulk endpoints for reading and writing blocks of data and for the exchange of control commands and status messages. For the device to be recognized by the operating system, it must also implement a \textit{command set}. Most mass storage devices use the \textit{\gls{SCSI} Transparent command set}
The \gls{MSC} specification defines multiple \textit{transport protocols} that can be selected using the descriptors. For it's simplicity, the \gls{BOT} will be used. \gls{BOT} uses two bulk endpoints for reading and writing blocks of data and for the exchange of control commands and status messages. For the device to be recognized by the operating system, it must also implement a \textit{command set}. Most mass storage devices use the \textit{\gls{SCSI} Transparent command set}
\footnote{To confirm this assertion, the descriptors of five thumb drives and an external hard disk were analyzed using \verb|lsusb|. All but one device used the SCSI command set, one (the oldest thumb drive) used \textit{SFF-8070i}. A list of possible command sets can be found in TODO (usb spec overview)}.
The command set's commands let 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 checks that all internal buffers have been written to Flash.
@ -112,7 +112,7 @@ In order to emulate a mass storage device without having a physical storage medi
%https://www.keil.com/pack/doc/mw/USB/html/group__usbd__cdc_functions__acm.html
Historically meant for modem communication, this class is now the de facto standard way of making \gls{USB} devices appear as serial ports on the host \gls{OS}. The \gls{CDC} uses three endpoints: bulk IN and OUT, and an interrupt endpoint.
Historically meant for modem communication, this class is now the de facto standard way of making \gls{USB} devices appear as serial ports on the host \gls{OS}. The \gls{CDC} uses three endpoints: bulk IN and OUT, and an interrupt endpoint.
\todo{verify this vvv}
The interrupt endpoint is used for control commands and notifications while the bulk endpoints are used for useful data. \gls{ACM} stands for \textit{Abstract Control Model} and it's a \gls{CDC}'s subclass that defines the control messages format. Since we don't use a physical UART and the line is virtual both on the PC and in the end device, the control commands can be ignored.
@ -123,7 +123,7 @@ An interesting property of this class is that the bulk endpoints transport raw d
Since it's creation, the \gls{USB} specification expected that each function will have only one interface enabled at a time. After it became apparent that there is a need for having multiple unrelated interfaces work in parallel, a workaround called the \gls{IAD} was introduced. \gls{IAD} is an entry in the descriptor table that defines which interfaces belong together and should be handled by the same software driver.
To use the \gls{IAD}, the function's class must be set to 239 (0xEF), subclass 2 and protocol 1, so the \gls{OS} knows to look for the presence of \glspl{IAD} before binding drivers to any interfaces.
To use the \gls{IAD}, the function's class must be set to 239 (0xEF), subclass 2 and protocol 1, so the \gls{OS} knows to look for the presence of \glspl{IAD} before binding drivers to any interfaces.
% TODO link to some references..

@ -2,7 +2,7 @@
Four methods of a wireless connection have been considered: Bluetooth (e.g. with CC2541), WiFi with ESP8266, a 868\,MHz long range link with SX1276, and a 2.4\,GHz link with nRF24L01+. Bluetooth was dismissed early for its complexity, and ESP8266 for its high consumption in continuous reception mode, although both solutions might be viable for certain applications and with more development time.
The Semtech SX1276 and Nordic Semiconductor nRF24L01+ transceivers have both been tested using the first GEX prototype, confirming its usefulness as a hardware development tool, and it's been confirmed they could fulfill the requirements of the application.
The Semtech SX1276 and Nordic Semiconductor nRF24L01+ transceivers have both been tested using the first GEX prototype, proving its usefulness as a hardware development tool, and it has been confirmed they could fulfill the requirements of our application.
\begin{figure}[h]
\centering
@ -32,15 +32,15 @@ In \gls{OOK}, the carrier generator is switched on and off to transmit ones and
\subsection{Gaussian Minimum-Shift Keying (GMSK)}
\Gls{GMSK} is a variant of \gls{MSK} which uses a gaussian filter to shape the digital signal before sending it to the oscillator. The principle is similar to \gls{GFSK}, and it is yet another way to further reduce side-band interference and increase spectral efficiency. GMSK is used in the \gls{GSM}.
\Gls{GMSK} is a variant of \gls{MSK} which uses a Gaussian filter to shape the digital signal before sending it to the oscillator. The principle is similar to \gls{GFSK}, and it is a yet another way to reduce side-band interference and increase spectral efficiency. \gls{GMSK} is used in the \gls{GSM}.
\subsection{LoRa Modulation}
LoRa is a patented proprietary modulation developed by Semtech. It uses a direct sequence frequency hopping spread spectrum modulation and can achieve very long range transmission (over 10\,km is not uncommon). LoRa is available only with transceiver \glspl{IC} produced by Semtech and for this reason it is rather expensive.
\section{Comparing SX1276 vs. nRF24L01+}
\section{Comparing SX1276 and nRF24L01+}
The two transceivers are compared in table \ref{fig:nrf-sx-comparison}. It's apparent that each has its strengths and weaknesses.
The two transceivers are compared in table \ref{fig:nrf-sx-comparison}. It's apparent that each has its strengths and weaknesses, discussed below.
\begin{table}[h]
\centering
@ -53,7 +53,7 @@ The two transceivers are compared in table \ref{fig:nrf-sx-comparison}. It's app
\textbf{Data rate} & up to 300\,kbps & 250--2000\,kbps \\
\textbf{Modulation} & (G)FSK, (G)MSK, OOK, LoRa & GFSK \\
% \textbf{Bandwidth} & 7--500\,kHz per channel & 0.7--2\,MHz per channel \\
\textbf{Range (est.)} & 2\,km to 20\,km LOS & up to 1\,km LOS \\
\textbf{Range (est.)} & over 10\,km & up to 1\,km \\
\textbf{Consumption Rx} & 10.8--12\,mA & 12.6--13.5\,mA \\
\textbf{Consumption Tx} & 20--120\,mA & 7--11.3\,mA \\
\textbf{Idle power (max)} & 1\,$\mu$A sleep, 2\,mA stand-by & 0.9\,$\mu$A sleep, 320\,$\mu$A stand-by \\
@ -88,32 +88,80 @@ A separate device, the \textit{GEX wireless gateway}, was developed to provide t
\caption{A block diagram of the wireless connection}
\end{wrapfigure}
The gateway presents itself to the host as a \gls{CDCACM} device, much like the GEX modules themselves (here called \textit{nodes}) when connected over \gls{USB}. It implements a simple protocol which encapsulates the binary data sent to or from a connected node. The wrapped GEX protocol (chapter \ref{sec:tinyframe}) remains unchanged.
The gateway has a 4-byte network ID, a number derived from the microcontroller's unique ID. The network ID must be entered into all nodes that wish to communicate with it. Additionally, each module must be assigned a unique 1-byte number, which, together with the four network ID bytes, uniquely identifies the node. The gateway can connect to up to 6 nodes at once.
All messages sent to or from the gateway are a multiple of 64 bytes long, padded with zeros if shorter. The message starts with a control byte, determining the message type (table \ref{fig:rf-dongle-commands}).
\begin{table}[h]
\centering
\begin{tabulary}{\textwidth}{lL}
\toprule
\textbf{Function} & \textbf{Message structure} \\
\midrule
Send a message & `m' (\verb|u8|)address (\verb|u16|)length (\verb|u8[]|)payload \\
Restart \& remove nodes & `r' \\
Add nodes & `n' (\verb|u8|)count (\verb|u8[]|)addresses \\
Get the network ID & `i' \\
Response to `i' & 0x01 (\verb|u8[4]|)net\_id \\
Received message & 0x02 (\verb|u8|)address (\verb|u8|)length (\verb|u8[]|)data \\
\bottomrule
\end{tabulary}
\caption[Wireless gateway commands and messages]{\label{fig:rf-dongle-commands}Wireless gateway commands and messages; control characters in the printable range are shown as ASCII}
\end{table}
The gateway may be restarted using the `r' command when the \gls{PC} application starts. Then it adds all node addresses with the `n' command and can begin communication. The `i' command, reading the network ID, can additionally be used as a ping command to verify the \gls{USB} connection.
\todo[inline]{Add additional commands. Also remove magic bytes form the real messages, they're useless}
The gateway presents itself to the host as a \gls{CDCACM} device, much like the GEX modules themselves (here called \textit{nodes}) when connected over \gls{USB}. It implements a simple protocol which encapsulates the binary data sent to or from a connected node. The wrapped GEX protocol, which is described in chapter \ref{sec:tinyframe}, remains unchanged.
The gateway has a 4-byte network ID, a number derived from the \gls{MCU}'s unique ID by calculating its 32-bit \gls{CRC}. The network ID must be entered into all nodes that wish to communicate with the gateway. Additionally, each module is assigned a 1-byte number which serves as its address in the network. The gateway can receive messages from up to 6 nodes.
All messages sent to or from the gateway are a multiple of 64 bytes long, padded with zeros if shorter. The message starts with a control byte determining its type, as summarized in the following table:
{
\tabulinesep=5pt
\begin{longtabu} to \textwidth {P{5em} X[5] X[4,l]}
\toprule
\textbf{First byte} & \textbf{Function} & \textbf{Structure} \\
\midrule
\endhead
\bottomrule
\endfoot
`r' (114) &
\cname{RESTART}
Restart the gateway, disconnecting all nodes. This is functionally equivalent to re-plugging it to the USB port.
& \\
`i' (105) &
\cname{GET\_NET\_ID}
Read the unique 4-byte network ID. This command has no side effects and may be used as ``ping'' to verify the USB connection. &
\begin{cmdresp}
\cfield{0x01}
\cfield{u8[4]} network ID
\end{cmdresp}
\\
`n' (110) &
\cname{ADD\_NODES}
Configure the gateway to listen for messages from the given nodes.
Nodes may be removed using the RESTART command.
&
\begin{cmdreq}
\cfield{u8} count
\cfield{u8[]} node addresses
\end{cmdreq}
\\
`m' (109)&
\cname{SEND\_MSG}
Send a binary message to one of the connected nodes. The message may span multiple 64-byte frames; the subsequent frames will contain only the payload bytes, or zero padding at the end of the last one.
& \begin{cmdreq}
\cfield{u8} node address
\cfield{u16} length
\cfield{u8} checksum (inverted XOR of all payload bytes)
\cfield{u8[]} payload
\end{cmdreq} \\
0x02 &
\cname{INCOMING\_MSG}
A message was received from one of the configured nodes. This is an event frame sent by the gateway to the host.
& \begin{cmdpld}
\cfield{u8} node address
\cfield{u8} message length
\cfield{u8[]} payload
\end{cmdpld} \\
\end{longtabu}
}
\subsection{Gateway Initialization Procedure}
A host program connecting to a node or nodes through the gateway should follow the following procedure to initialize and configure the gateway:
\begin{enumerate}
\item Send the `GET\_NET\_ID' command to test if the gateway is connected (and obtain its network ID as a side effect)
\item Restart the gateway using the `RESTART' command to clean any possible previous configuration.
\item Add the node address(es) using `ADD\_NODES'
\item Ping the connected node(s) via TinyFrame (passed through `SEND\_MSG' and `INCOMING\_MSG') to test if the connection works.
\end{enumerate}

@ -1,5 +1,7 @@
% extra balíky a jejich nastavení
\usepackage{morewrites}
\usepackage{calc}
\usepackage{todonotes} % todos
\usepackage{blindtext} % lorem
\usepackage{csquotes} % quotes

@ -34,6 +34,7 @@
{
\begin{itemize}[
leftmargin=.7cm,
rightmargin=1mm,
nosep
]
}
@ -89,3 +90,39 @@
\end{cmditemlistenv}
}
%% hack from https://tex.stackexchange.com/questions/145812/using-fbox-in-a-newenvironment
% to allow using fbox inside a environment
\newsavebox{\mybox}
% a list of payload fields, with a caption
\newenvironment{boxedpayload}[1][]
{
\begingroup\setlength{\fboxsep}{0pt}
\indent
\begin{lrbox}{\mybox}
\begin{minipage}{\textwidth - \parindent*2}\null
\ifthenelse{\equal{#1}{}}{
\vspace{3pt} % no title
}{
% with title
\hspace{6pt}\textit{#1}
\vspace{-6pt}\newline
\noindent\rule{\textwidth}{.4pt}
\vspace{-\baselineskip}
\vspace{-4pt}
}
\begin{itemize}[
itemsep=0pt, % this is not actually 0, for some reason. that's okay
leftmargin=24pt,
rightmargin=1mm
]
}
{
\end{itemize}
\vspace{-\baselineskip}
\vspace{14pt}
\end{minipage}
\end{lrbox}\fbox{\usebox{\mybox}}
\endgroup
}

@ -22,3 +22,5 @@
\newcommand{\cm}{\centi\metre}
\newcommand{\VperA}{\V/\A}
\newcommand{\IIC}{I\textsuperscript{2}C\xspace}
\newcommand{\IIS}{I\textsuperscript{2}S\xspace}

@ -5,8 +5,8 @@
\newacronym{SPI}{SPI}{Serial Peripheral Interconnect}
\newacronym{USART}{USART}{Universal Synchronous/Asynchronous Receiver/Transmitter}
\newacronym{UART}{UART}{Universal Asynchronous Receiver/Transmitter}
\newacronym{I2C}{I\textsuperscript{2}C}{Inter-Integrated Circuit}
\newacronym{I2S}{I\textsuperscript{2}S}{Inter-IC Sound}
\newacronym[sort=I2C]{I2C}{I\textsuperscript{2}C}{Inter-Integrated Circuit}
\newacronym[sort=I2S]{I2S}{I\textsuperscript{2}S}{Inter-IC Sound}
\newacronym{USB}{USB}{Universal Serial Bus}
\newacronym{CAN}{CAN}{Controller Area Network}
\newacronym{HART}{HART}{Highway Addressable Remote Transducer}

Binary file not shown.

@ -1,6 +1,5 @@
\documentclass[twoside]{ctuthesis}
\usepackage{morewrites}
\input{document_config} % import balíků a nastavení ctuthesis
% --- obsah zvláštních oddílů ---

Loading…
Cancel
Save