Compare commits

..

No commits in common. "4920c5b8e12f3235164fda419f677fe5d632a8e3" and "55f5008540c1d603707673f898037fc7c567aac2" have entirely different histories.

2 changed files with 174 additions and 109 deletions

View file

@ -1,129 +1,194 @@
# THHOR Cosmic Ray Sensor
# Turbo Weather
## ATtiny3224 resources
## ATtiny424SS resources
- `TCA0`: ADC trigger clock
- `SPI0-PA1…3, 7`: communication with flash and FPGA
- `USART0-RxD/TxD-PB0,2…3`: transmission of data, receive commands
- `TCA0-WO0-PB0`: generate the 32768kHz clock for the MS5534C
- `SPI0-PA1…3`: communication with the MS5534C
- `USART0-RxD/TxD-PB2…3`: transmission of data, receive commands
- `PORTB-PB1`: enable the RF power regulator
- `ADC`: internal sources.
- `PORTA-PA5`: light up the LED
- `ADC0-PA4,6,7`: read Batterie, NTC, and RF power voltage, and internal sources.
- `PIT`: generate clock tick, to wake the µC once per second from deep sleep.
- `RTC`: clock
- `USERROW`: store persistent configuration
- `EEPROM`: io configuration, `ADC` readings configuration
- `RAM`: 64 byte TX buffer, 16 bytes RX buffer, ~128 bytes stack.
- `EEPROM`: store `ADC` readings configuration, store sensor test data records.
- `RAM`: 256 byte TX buffer, 16 bytes RX buffer, ~128 bytes stack.
- `FLASH`: pretty full. With lots of assembly, -O2 fits with -DDEBUG.
## Source files
- `thhor.c`: main program, interface to the MS5534C.
- `config.c`: io configuration, userrow config.
- `bate.c`: main program, interface to the MS5534C
- `calib.c`: calculate the calibrated the pressure sensor readings.
- `adc.c`: configure and run the ADC, calculate calibrated results
- `mul.c`: handcraft 16-bit multiplication and decimal printing.
- `rtc.c`: configure the _periodic interrupt timer_ `PIT`.
- `spi.c`: configure the `SPI0` and run a 16-bit frame.
- `uart.c`: configure the USART0, provide Tx and Rx buffers for IO.
- `uart_tx.S`: assembly implemention for uart.
- `base85.c`: Base85 encode/decode 16-bytes `cmd_buffer` on UART.
- `base85a.S` assembly implemention for bch4369.
- `cmd.c`: parse and run simple commands received from the UART.
- `flash.c`: talk to the external flash via SPI
- `bch4369.c`: EDAC on flash pages
- `flga.c`: talk to the FPGA via SPI
- `pipe.c`: move data streams
## UART protocol
## Output records
The host sends commands consisting of
- a capital letter,
- flags
- optionally one space and 16 base85 encoded `data` bytes
- a newline
The programm issues several types of output lines. Each type is
prefixed with a unique capital letter.
When the first flags is a digit `0``4`, it selects a section of the
block buffer. When no section is selected, the command operates on
the `data` buffer directly, where applicable.
- `V`: sent at boot, a greeting and version.
- `B`: sent at boot, a single byte `RSTCTRL.RSTFR`, the reset reason.
- `S`: config record (`SEND_CONFIG`): hex dump of the `SIGROW`.
- `F`: config record (`SEND_CONFIG`): hex dump of the `FUSES`.
- `U`: config record (`SEND_CONFIG`): hex dump of the `USERROW`.
- `C`: config record (`SEND_CONFIG`): hex dump of the `config` structure in `RAM`.
- `E`: config record (`SEND_CONFIG`): hex dump of the ADC configuration in `EEPROM`.
- `W`: calibration record (`SEND_BATEW`): sensor calibration data (hex) read from the sensor.
- `D`: sensor record (`SEND_BATED`): sensor reading data (hex) acquired from the sensor.
- `P`: pressure record (`SEND_CALIB`): sensor readings in natural units.
- `A`: ADC readings (`SEND_ADC_HEX`): hex words, 16-bit range.
- `V`: ADC readings (`SEND_ADC_VOLT`): calibrated, natural units.
- `X`: Debug (`SEND_DEBUG`): hex dump of the `debug_data` structure.
- `R`: command reception.
When the last flag is a haf-mesh `=` and there is no `data`, and the
previous command was the same letter, then the `data` of the previous
command is used again, possibly modified by the previous command
execution.
Config records are sent at boot, with test data, and when enabled via
`SEND_CONFIG` with a subset of sensor readings. The config byte `confp`
is the number of readings sent in between without sending config records.
The µC answers with
- a mesh `#`,
- the command letter and used flags,
- optionally one space and 16 base85 encoded `data` bytes,
- a newline.
Debug data is only available when not disabled during compilation. Do
`make DEBUG=-DNODEBUG` to disable all debugging code and data.
In case of any error the answer is terminated with a what `?` and a newline,
without encoded data bytes.
The `SEND` flags are stored in byte[3] of the `config` structure to
enable the respective output records, with the bit positions
### Commands
- `SEND_CONFIG = 0x01`
- `SEND_BATED = 0x02`
- `SEND_BATEW = 0x04`
- `SEND_CLOCK = 0x08`
- `SEND_CALIB = 0x10`
- `SEND_ADC_HEX = 0x20`
- `SEND_ADC_VOLT = 0x40`
- `SEND_DEBUG = 0x80`
- `A`: ADC
All variants return number of completed channels.
There are two configued channels, T and Vcc.
* `A`: return status
* `A!`: start conversions
* `A<`: return ADC readings
## Configuration
- `B`: Block buffer ops, return valid sections.
The block buffer is 80 bytes, in five sections.
One flash page is 8 blocks of 64 bytes, plus one section 4 for EDAC in the last block.
When no section is selected, the `data` is used in the cmd buffer.
* `B0``B4`: select section.
* `B@`: mark all sections invalid.
* `B0 data`: fill the invalid selected section with the data and mark is valid..
* `B0! data`: fill the selected section with the data even is it is valid.
* `B…%@`: reset the BCH4369 parity.
* `B…%`: add the selected section/data to the parity.
* `B…%!`: Complete the parity and copy to section 4 in the block buffer.
* `B…<`: Return valid data from the selected section and mark it invalid.
* `B…<!`: Return data from the selected section, evcen when invalid, and do not mark is invalid.
At boot, the configuration is copied from the `USERROW` to the
`config` structure in `RAM`, if the first byte in the `USERROW` is
the magic `0xba`, and the second byte matches the version of the
`config` structure, currently `0x08`. Else, the defaults are used.
The operations _write_, _parity_, and _read_ can be combined in
that order, as indicated by `…`.
The config structure is
- `[0]`: `magic = 0xba`.
- `[1]`: `version = 0x08`.
- `[2]`: `triggers`: trigger enables.
- `[3]`: `send`: output data configuration.
- `[4]`: `power`: power management.
- `[5]`: `calib_test`: number of test records to send after a reset.
- `[6]`: `spi_div`: `SPI0.CTRLA.SPI_PRESC` \[÷64\]
- `[7]`: `mclk_delay`: number of `MCLK` ticks to wait before a reading.
- `[8]`: `period`: number of seconds-1 between readings.
- `[9]`: `confp`: number of readings without config records.
- `[10]`: `cpu_clk`: `CLKCTRL.MCLKCTRLB` \[÷2\]
- `[11]`: `mclk_period`: `TCA0.SINGLE.CMP0` \[÷76\]
- `[12]`: `baud_div`: two bytes little endian \[÷16667\]
- `[14]`: `uart_mode`: `USART0.CTRLB`
- `[15]`: `pit_period`: `RTC.CLKSEL` \[÷1024\]
- `[16]`: `immediate`: number of immediate readings at boot.
- 'C': FPGA command
* `C@`: reset the FPGA to unconfigured state.
* `C data`: send a command to the FPGA, up to 14 bytes that came back.
The command format is defined by `struct fpga_cmd`
### Triggers
- `D`: Find the first free page in the flash telemetry area.
The `triggers` byte\[2\] enables various reasons to do a sensor reading.
- `F`: Command to the flash chip via SPI.
* `F': return SPI status.
* `F data`: submit command
* `F!`: Poll SPI.
* `F<`: Return the answer.
- `TRIGGER_ONCE = 0x01`: one reading at boot.
- `TRIGGER_CONT = 0x02`: continuously read the sensor.
- `TRIGGER_UART = 0x04`: read the sensor when the UART Rx input toggles.
- `TRIGGER_CLOCK = 0x08`: read periodically, every `period`+1 _seconds_.
- `TRIGGER_BREAK = 0x10`: read continuously while the UART Rx input is low.
- `TRIGGER_IMMED = 0x20`: do any requested immediate readings.
- `M` peek/poke.
* `M data`: execute a peek of poke.
* `M=`: continue the just emitted peak/poke.
_Seconds_ are define by the `PIT`. Those can be up to 8 real seconds
long, or much shorter. _Immediate_ readings can be requested at boot
or via the command `T`.
`data` is a `struct peek_poke`. Up to 12 bytes can be transfered by each call.
Writing to EEPROM requires a key for the CCP.
### Power
- `O`: Power/configure the FPGA, return FPGA status.
* `O0`: Turn power off.
* `O1`: Turn power on.
* `O2`: Configure from flash, if powered and unconfigured.
* `O3`: Power off if unconfigured.
* `O4`: Configure from flash, unconditionally.
The bits in the power byte\[4\] are
- `P`: Pipe stream ops.
* `P@`: Stop current stream (clear all destinations).
* `P data`: confiure ans start a stream.
* `P.`: Poll the flash stream.
* `P,`: Poll the flashj stream with ACK.
* `P!`: Poll the pipe.
- `POWER_DOWN = 0x01`: Enter `POWER_DOWN` sleep between readings.
- `POWER_DOWN_CLI = 0x02`: Disable interrupts before `POWER_DOWN`.
- `STOP_MCLK = 0x04`: Stop the `MCLK` after the reading.
- `POWER_LED = 0x08`: Turn on the LED during a reading.
- `POWER_STDBY = 0x10`: Enter `STANDBY` sleep between readings.
- `POWER_RX = 0x20`: Do not `POWER_DOWN` when the `UART` Rx is active
- `POWER_RF = 0x40`: Turn on the RF transmitter power.
- `POWER_LINE = 0x80`: Send a preamble after rfen()
The poll options are usefull for debugging, when mainloop polling is on hold.
Do `poke("magic+2", 0x01, s=1)` to set the pipe polling on hold.
`POWER_STDBY` is sufficient to reduce the power to a minimum.
`POWER_RX` does not seem to work. From `POWER_DOWN_CLI` we shall
never wake up, unless the `WDT` is enabled in the fuses. When the
`MCLK` is stopped after a reading, it will be truned on and
`mclk_delay` ticks must pass before communication with the sensor
resumes. That delay is probably not necessary. `POWER_RF` is
necessary to bias the NTC measured by ADC readings. The `POWER_LINE`
preamble charges the AC-coupled output of the RF receiver to
properly receive subsequent characters.
## Commands
Commandlines received via the UART must be in the format
- `«C» {[«space»]+ «hex»}+ [«space»]+ «linefeed»`
A command letter, uppercase, and up to seven (optionally space
separated) hex bytes, optionally followed by more space characters and
a linefeed. A hex character is one or two hex digits, letters `a``f`
_must_ be lowercase. Obviously, a single hex digit must be separated
with space characters from any following byte. No spaces are required
at all when all bytes are written with two digits. The Rx buffer can
accomodate commandlines up to 15 bytes long, including the newline
char.
The parser echos the received line, preceeded with the string `R>`.
When the command is valid, the answer bytes are sent prefixed with
`R!`. Invalid commands are answered with `R?`.
Most commands require a specific number of hex bytes as arguments. As
currently implemented, all commands echo all their arguments and one
additional byte.
### List of commands:
- `R «ccp»`: Reboot the µC. The argument byte must be `d8`, the
`CCP[IOREG]` key, to validate the reset.
- `C «key» «bytes»…`: write to the `config` structure in `RAM`
- `U «key» «bytes»…`: write to persistent config in the `USERROW`
- `E «key» «bytes»…`: write to `EEPROM`
Up to six «bytes» are written. The «key» must be `9d`, the
`CCP[SPM]` key, for the persistent stores, and `ba` for the `RAM`.
These commands return the old value of the first byte that was
written.
- `T «n»`: trigger «n» more immediate sensor readings.
- `M «aaaa»`: reads any memory address «aaaa» (two bytes, big endian)
and prints the byte.
- `W «aaaa» «bb»`: write a byte «bb» into any address «aaaa», return
the old value of that memory location.
- `K «bb» «bb» «bb» «bb»`: set the clock. The 32-bit time value must
be sent little endian.
- `D «n»`: process and send calibrated readings for «n» test data
records. The `EEPROM` has space for up to five data records.
## Toolchain
The ATtiny3224 µC requires an up-to-date toolchain
The ATtiny424 µC requires an up-to-date toolchain
- binutits: `./configure --target=avr --program-prefix=avr-`
- gcc: `../gcc/configure --program-prefix=avr- --with-avrlibc --target=avr --enable-languages=c --disable-nls`
- avr-libc: `./configure --host=avr`
## TODO (all done)
- √ Use the SPI hardware to talk to the sensor.
- √ Send results via UART hardware.
- × Setup the watchdog. √ Use PIT instead
- √ Control power to the RF transmitter
- √ Light the LED.
- √ Readout the ADCs, thermistors.
- √ Readout the internal temperature sensor.

View file

@ -70,7 +70,7 @@ extern struct io_config ee9_start[], ee9_end[];
#define UART_VPORT VPORTB
#define UART_PORT PORTB
#define TxE_PIN 0
#define TxE_PIN 1
#define TxD_PIN 2
#define RxD_PIN 3
#define RxD_PINCTRL UART_PORT.PIN3CTRL