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 - `TCA0-WO0-PB0`: generate the 32768kHz clock for the MS5534C
- `SPI0-PA1…3, 7`: communication with flash and FPGA - `SPI0-PA1…3`: communication with the MS5534C
- `USART0-RxD/TxD-PB0,2…3`: transmission of data, receive commands - `USART0-RxD/TxD-PB2…3`: transmission of data, receive commands
- `PORTB-PB1`: enable the RF power regulator - `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. - `PIT`: generate clock tick, to wake the µC once per second from deep sleep.
- `RTC`: clock
- `USERROW`: store persistent configuration - `USERROW`: store persistent configuration
- `EEPROM`: io configuration, `ADC` readings configuration - `EEPROM`: store `ADC` readings configuration, store sensor test data records.
- `RAM`: 64 byte TX buffer, 16 bytes RX buffer, ~128 bytes stack. - `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 ## Source files
- `thhor.c`: main program, interface to the MS5534C. - `bate.c`: main program, interface to the MS5534C
- `config.c`: io configuration, userrow config. - `calib.c`: calculate the calibrated the pressure sensor readings.
- `adc.c`: configure and run the ADC, calculate calibrated results - `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`. - `rtc.c`: configure the _periodic interrupt timer_ `PIT`.
- `spi.c`: configure the `SPI0` and run a 16-bit frame. - `spi.c`: configure the `SPI0` and run a 16-bit frame.
- `uart.c`: configure the USART0, provide Tx and Rx buffers for IO. - `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. - `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 The programm issues several types of output lines. Each type is
- a capital letter, prefixed with a unique capital letter.
- flags
- optionally one space and 16 base85 encoded `data` bytes
- a newline
When the first flags is a digit `0``4`, it selects a section of the - `V`: sent at boot, a greeting and version.
block buffer. When no section is selected, the command operates on - `B`: sent at boot, a single byte `RSTCTRL.RSTFR`, the reset reason.
the `data` buffer directly, where applicable. - `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 Config records are sent at boot, with test data, and when enabled via
previous command was the same letter, then the `data` of the previous `SEND_CONFIG` with a subset of sensor readings. The config byte `confp`
command is used again, possibly modified by the previous command is the number of readings sent in between without sending config records.
execution.
The µC answers with Debug data is only available when not disabled during compilation. Do
- a mesh `#`, `make DEBUG=-DNODEBUG` to disable all debugging code and data.
- the command letter and used flags,
- optionally one space and 16 base85 encoded `data` bytes,
- a newline.
In case of any error the answer is terminated with a what `?` and a newline, The `SEND` flags are stored in byte[3] of the `config` structure to
without encoded data bytes. 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 ## Configuration
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
- `B`: Block buffer ops, return valid sections. At boot, the configuration is copied from the `USERROW` to the
The block buffer is 80 bytes, in five sections. `config` structure in `RAM`, if the first byte in the `USERROW` is
One flash page is 8 blocks of 64 bytes, plus one section 4 for EDAC in the last block. the magic `0xba`, and the second byte matches the version of the
When no section is selected, the `data` is used in the cmd buffer. `config` structure, currently `0x08`. Else, the defaults are used.
* `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 operations _write_, _parity_, and _read_ can be combined in The config structure is
that order, as indicated by `…`. - `[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 ### Triggers
* `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`
- `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. - `TRIGGER_ONCE = 0x01`: one reading at boot.
* `F': return SPI status. - `TRIGGER_CONT = 0x02`: continuously read the sensor.
* `F data`: submit command - `TRIGGER_UART = 0x04`: read the sensor when the UART Rx input toggles.
* `F!`: Poll SPI. - `TRIGGER_CLOCK = 0x08`: read periodically, every `period`+1 _seconds_.
* `F<`: Return the answer. - `TRIGGER_BREAK = 0x10`: read continuously while the UART Rx input is low.
- `TRIGGER_IMMED = 0x20`: do any requested immediate readings.
- `M` peek/poke. _Seconds_ are define by the `PIT`. Those can be up to 8 real seconds
* `M data`: execute a peek of poke. long, or much shorter. _Immediate_ readings can be requested at boot
* `M=`: continue the just emitted peak/poke. or via the command `T`.
`data` is a `struct peek_poke`. Up to 12 bytes can be transfered by each call. ### Power
Writing to EEPROM requires a key for the CCP.
- `O`: Power/configure the FPGA, return FPGA status. The bits in the power byte\[4\] are
* `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.
- `P`: Pipe stream ops. - `POWER_DOWN = 0x01`: Enter `POWER_DOWN` sleep between readings.
* `P@`: Stop current stream (clear all destinations). - `POWER_DOWN_CLI = 0x02`: Disable interrupts before `POWER_DOWN`.
* `P data`: confiure ans start a stream. - `STOP_MCLK = 0x04`: Stop the `MCLK` after the reading.
* `P.`: Poll the flash stream. - `POWER_LED = 0x08`: Turn on the LED during a reading.
* `P,`: Poll the flashj stream with ACK. - `POWER_STDBY = 0x10`: Enter `STANDBY` sleep between readings.
* `P!`: Poll the pipe. - `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. `POWER_STDBY` is sufficient to reduce the power to a minimum.
Do `poke("magic+2", 0x01, s=1)` to set the pipe polling on hold. `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 ## 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-` - binutits: `./configure --target=avr --program-prefix=avr-`
- gcc: `../gcc/configure --program-prefix=avr- --with-avrlibc --target=avr --enable-languages=c --disable-nls` - gcc: `../gcc/configure --program-prefix=avr- --with-avrlibc --target=avr --enable-languages=c --disable-nls`
- avr-libc: `./configure --host=avr` - 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_VPORT VPORTB
#define UART_PORT PORTB #define UART_PORT PORTB
#define TxE_PIN 0 #define TxE_PIN 1
#define TxD_PIN 2 #define TxD_PIN 2
#define RxD_PIN 3 #define RxD_PIN 3
#define RxD_PINCTRL UART_PORT.PIN3CTRL #define RxD_PINCTRL UART_PORT.PIN3CTRL