Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
4920c5b8e1 src/README, THHOR version 2026-04-08 23:21:26 +02:00
Stephan I. Böttcher
9723c5b3d6 TxE_PIN fix 2026-04-08 23:17:49 +02:00
2 changed files with 109 additions and 174 deletions

View file

@ -1,194 +1,129 @@
# Turbo Weather
# THHOR Cosmic Ray Sensor
## ATtiny424SS resources
## ATtiny3224 resources
- `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
- `TCA0`: ADC trigger clock
- `SPI0-PA1…3, 7`: communication with flash and FPGA
- `USART0-RxD/TxD-PB0,2…3`: transmission of data, receive commands
- `PORTB-PB1`: enable the RF power regulator
- `PORTA-PA5`: light up the LED
- `ADC0-PA4,6,7`: read Batterie, NTC, and RF power voltage, and internal sources.
- `ADC`: internal sources.
- `PIT`: generate clock tick, to wake the µC once per second from deep sleep.
- `RTC`: clock
- `USERROW`: store persistent configuration
- `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.
- `EEPROM`: io configuration, `ADC` readings configuration
- `RAM`: 64 byte TX buffer, 16 bytes RX buffer, ~128 bytes stack.
## Source files
- `bate.c`: main program, interface to the MS5534C
- `calib.c`: calculate the calibrated the pressure sensor readings.
- `thhor.c`: main program, interface to the MS5534C.
- `config.c`: io configuration, userrow config.
- `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
## Output records
## UART protocol
The programm issues several types of output lines. Each type is
prefixed with a unique capital letter.
The host sends commands consisting of
- a capital letter,
- flags
- optionally one space and 16 base85 encoded `data` bytes
- a newline
- `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 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.
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.
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.
Debug data is only available when not disabled during compilation. Do
`make DEBUG=-DNODEBUG` to disable all debugging code and data.
The µC answers with
- a mesh `#`,
- the command letter and used flags,
- optionally one space and 16 base85 encoded `data` bytes,
- a newline.
The `SEND` flags are stored in byte[3] of the `config` structure to
enable the respective output records, with the bit positions
In case of any error the answer is terminated with a what `?` and a newline,
without encoded data bytes.
- `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`
### Commands
## Configuration
- `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
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.
- `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.
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.
The operations _write_, _parity_, and _read_ can be combined in
that order, as indicated by `…`.
### Triggers
- '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`
The `triggers` byte\[2\] enables various reasons to do a sensor reading.
- `D`: Find the first free page in the flash telemetry area.
- `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.
- `F`: Command to the flash chip via SPI.
* `F': return SPI status.
* `F data`: submit command
* `F!`: Poll SPI.
* `F<`: Return the answer.
_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`.
- `M` peek/poke.
* `M data`: execute a peek of poke.
* `M=`: continue the just emitted peak/poke.
### Power
`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.
The bits in the power byte\[4\] are
- `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.
- `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()
- `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_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.
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.
## 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 ATtiny424 µC requires an up-to-date toolchain
The ATtiny3224 µ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 1
#define TxE_PIN 0
#define TxD_PIN 2
#define RxD_PIN 3
#define RxD_PINCTRL UART_PORT.PIN3CTRL