initial commit

pull/2/head
Piotr Wilkon 2021-09-10 13:55:39 +02:00
parent effbb5b661
commit bc18307a97
5 changed files with 55 additions and 6 deletions

13
CHANGELOG.md 100644
View File

@ -0,0 +1,13 @@
# 1.2.0 (2021-09-10)
This is the very first open-source VP-Digi release.
## New features
* Viscous-delay and direct-only modes are enabled separately for each digipeater alias: ```digi <0-7> viscous [on/off]``` and ``` digi <0-7> direct [on/off] ```.
**When updating from version <1.2.0 please erase configuration or set new settings carefully.**
* Selectable signal input type: normal (filtered) audio or flat (unfiltered) audio: ```flat [on/off]``` - switches modem settings - before v. 1.2.0 was hardcoded for normal audio
* Erase all settings command: ```eraseall```
## Bug fixes
* none
## Other
* Code was partially rewritten (especially digipeater, modem and AX.25 layer)
## Known bugs
* none as far

View File

@ -1 +1,37 @@
# vp-digi
# VP-Digi
VP-Digi is a functional, cheap, easy to assemble and configure STM32-based APRS digipeater controller with built-in KISS modem.
## Description, schematic, instructions
If you are not interested in source code, this repository is not for you. You can find full project description, schematics, compiled firmware and instructions [on my website](https://sq8l.pzk.pl/index.php/vp-digi-cheap-and-functional-aprs-digipeater-controller-with-kiss-modem/).
## Source code usage
The firmware was written using System Workbench for STM32 (SW4STM32) and you should be able to import this repository directly to the IDE. The source code is publicly available since version 1.3.0.
## Technical description
The project was designed to be running on a Blue Pill board (STM32F103C8T6) with 8MHz crystal. The firmware was written using only register operations (with ST headers) and CMSIS libraries. The HAL is there only for USB. The code is (quite) extensively commented where needed, so it shouldn't be very hard to understand.
### Demodulator
There are two demodulators (and decoders) running in parallel to provide better efficiency. The signal is sampled at 38400Hz (32 samples per symbol) by DMA. The interrupt is generated after receiving 4 samples and the samples are decimated. Then they are pushed through a preemphasis/deemphasis filter (if enabled) which equalizes tone amplitudes. Filtered samples are multiplied by locally generated mark and space tones (their I and Q parts - cosine and sine). This gives a correlation factor between the input signal and each tone. In the meanwhile an unfiltered symbol is produced to drive the data carrier detection PLL. The difference of correlation factors is the new sample and is pushed through a low pass filter to eliminate noise. Filtered samples are compared to zero and the demodulated symbol is sent to bit recovery mechanism.
### Bit recovery (and NRZI decoder)
Bit recovery mechanism is based on a digital PLL. The PLL is nominally running at 1200Hz (=1200 Baud). The symbol change should occur near PLL counter zero, so that the counter overflows in the middle of the symbol and the symbol value is sampled. With every symbol change the counter is multiplied by a <1 factor to bring it closer to zero, keeping the PLL and incoming signal in phase. The DCD signal is multiplexed from both modems. Explained more in [modem.c](Src/drivers/modem.c). Sampled symbol is decoded by NRZI decoder and sent to AX.25 layer.
### AX.25 decoding
AX.25 decoder is quite standard. CRC, PID and Control Byte are checked and both modem paths are multiplexed to produce only one output frame.
### Data carrier detection
DCD uses an analog-digital approach: based on PLL, but working on a digital unfiltered symbol stream. The PLL works in the same way as bit recovery PLL, except that there is a special DCD pulse counting mechanism implemented, explained in [modem.c](Src/drivers/modem.c). This approach seems to be far more effective than a typical, digital, AX.25-based detection.
### AX.25 encoding
AX.25 encoder is also quite simple. It can handle multiple frames in a row (limited by buffer length). Every transmission starts with preamble flags, then header flags, actual data, CRC, footer/separating flags, actual data, CRC, footer/separating flags... and tail flags. Raw bits are requested by the modulator.
### Modulator (and NRZI encoder)
The NRZI encoder runs at exactly 1200Hz (=1200 Baud) and requests bits from the AX.25 encoder. Bits are encoded to symbols and the DAC sampling timer interval is set depending on symbol value. Because of that there is only one sine table used. For 1200Hz tone the timer interval is larger than for 2200 Hz tone - the sampling frequency is changed to change the output signal frequency. An array index is always kept so that the output signal phase is continuous.
## References
The project took a lot of time, but now it's probably the most effective, publicly available, STM32-based modem and the most customizable microcontroller-based APRS digipeater. I would like to mention some resources I found really useful or inspiring:
* [multimon-ng](https://github.com/EliasOenal/multimon-ng) - general demodulator idea (correlation)
* [BeRTOS](https://github.com/develersrl/bertos) - AX.25 decoder
* [Forum thread by SP8EBC](http://forum.aprs.pl/index.php?topic=2086.0) - inspiration
* [DireWolf](https://github.com/wb2osz/direwolf) - PLL bit recovery idea
* [A High-Performance Sound-Card AX.25 Modem](https://www.tau.ac.il/~stoledo/Bib/Pubs/QEX-JulAug-2012.pdf) - preemphasis and low pass filtering idea
* [UZ7HO Soundmodem](http://uz7.ho.ua/packetradio.htm) - PLL-based DCD idea
## Contributing
All contributions are appreciated, but please keep the code reasonably clean. Also, please make sure that the firmware is working well before creating a pull request.
## License
The project is licensed under the GNU GPL v3 license (see [LICENSE](LICENSE)).

View File

@ -25,7 +25,7 @@ uint8_t callSsid = 0;
const uint8_t dest[7] = {130, 160, 156, 172, 96, 98, 96}; //APNV01-0
const uint8_t *versionString = (const uint8_t*)"VP-Digi v. 1.3.0\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n";
const uint8_t *versionString = (const uint8_t*)"VP-Digi v. 1.2.0\r\nThe open-source standalone APRS digipeater controller and KISS TNC\r\n";
uint8_t autoReset = 0;
uint32_t autoResetTimer = 0;

View File

@ -271,7 +271,7 @@ void TIM1_UP_IRQHandler(void)
/**
* @brief ISR for baudrate generator timer
* @brief ISR for baudrate generator timer. NRZI encoding is done here.
*/
void TIM3_IRQHandler(void) __attribute__ ((interrupt));
void TIM3_IRQHandler(void)
@ -282,7 +282,7 @@ void TIM3_IRQHandler(void)
{
if(Ax25_getTxBit() == 0) //get next bit and check if it's 0
{
modState.currentSymbol = modState.currentSymbol ? 0 : 1; //change symbol
modState.currentSymbol = modState.currentSymbol ? 0 : 1; //change symbol - NRZI encoding
}
//if 1, no symbol change
}
@ -374,7 +374,7 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
//if tone changed inside this region, then we add something to the DCD pulse counter (and adjust counter phase for the counter to be closer to 0)
//if tone changes outside this region, then we subtract something from the DCD pulse counter
//if some DCD pulse threshold is reached, then we claim that the incoming signal is correct and set DCD flag
//when configured propoerly, it's generally immune to noise, as the detected tone changes much faster than 1200 baud
//when configured properly, it's generally immune to noise, as the detected tone changes much faster than 1200 baud
//it's also important to set some maximum value for DCD counter, otherwise the DCD is "sticky"
dem->dcdPll = (signed)((unsigned)(dem->dcdPll) + ((unsigned)PLLINC)); //keep PLL ticking at the frequency equal to baudrate
@ -385,7 +385,7 @@ static int32_t afsk_demod(int16_t sample, Demod *dem)
{
if(abs(dem->dcdPll) < PLLINC) //tone change occured near zero
dem->dcdCounter += DCD_INC; //increase DCD counter
else //tone change occured far from zero
else //tone change occurred far from zero
{
if(dem->dcdCounter >= DCD_DEC) //avoid overflow
dem->dcdCounter -= DCD_DEC; //decrease DCD counter

0
TODO 100644
View File