[New Feature] Added initial implementation of olivia for testing

geofence_dev
Richard Eoin Meadows 2014-11-18 10:49:04 +00:00
rodzic 21d5005d6b
commit 6dd5205691
5 zmienionych plików z 249 dodań i 11 usunięć

Wyświetl plik

@ -5,3 +5,23 @@ The density of FR4 is 1,850 kg/m^3. If we assume a PCB area of 12*50 =
For a 1.0mm PCB: 600 * 1.0 * 1.85 = 1.110g
For a 1.6mm PCB: 600 * 1.6 * 1.85 = 1.728g
## Contestia ##
There doesn't appear to be much documentation for contestia...
[Oh here's some](http://f1ult.free.fr/DIGIMODES/MULTIPSK/contestia_rttym_en.htm)
Really we're looking at Olivia MFSK - contestia is just a variant.
[Wikipedia](http://en.wikipedia.org/wiki/Olivia_MFSK)
[ARRL](http://www.arrl.org/olivia)
It's already implemented in dl-fldigi [here](https://github.com/jamescoxon/dl-fldigi/blob/master/src/include/jalocha/pj_mfsk.h)
(Inverse) Fast Hadamard Transform needed
## APRS ##
[some description..](http://dooce.de/dokuwiki/doku.php?id=projekte:utrak:aprs)

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,124 @@
/*
* Fast Hadamard Transform
* Copyright (C) 2014 Richard Meadows <richardeoin>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FHT_H
#define FHT_H
#ifdef FWHT_TEST
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#else
#include "samd20.h"
#endif
/**
* Resources:
*
*
*/
/**
* We might want to use this with different types in the future.
*/
#define T int8_t
/**
* Fast Walsh-Hadamard Transform
*
* `data` an array that is the input vector. Modifed in-place
* `len` is the number of elements in `data`
*
* The result is returned in "hadamard" order
*/
void fwht(T *Data, size_t Len)
{
size_t Step, Ptr, Ptr2; T Bit1, Bit2, NewBit1, NewBit2;
for(Step=1; Step<Len; Step*=2)
{ for(Ptr=0; Ptr<Len; Ptr+=2*Step)
{ for(Ptr2=Ptr; (Ptr2-Ptr)<Step; Ptr2+=1)
{ Bit1=Data[Ptr2]; Bit2=Data[Ptr2+Step];
NewBit1=Bit2; NewBit1+=Bit1;
NewBit2=Bit2; NewBit2-=Bit1;
Data[Ptr2]=NewBit1; Data[Ptr2+Step]=NewBit2;
}
}
}
}
/**
* Inverse Fast Hadamard Transform
*
* `data` an array that is the input vector. Modifed in-place
* `len` is the number of elements in `data`
*
* The result is returned in "hadamard" order
*/
void ifwht(T *Data, size_t len)
{
size_t step, Ptr, Ptr2; T Bit1, Bit2, NewBit1, NewBit2;
for(step=len/2; step; step/=2)
{ for(Ptr=0; Ptr<len; Ptr+=2*step)
{ for(Ptr2=Ptr; (Ptr2-Ptr)<step; Ptr2+=1)
{ Bit1=Data[Ptr2]; Bit2=Data[Ptr2+step];
NewBit1=Bit1; NewBit1-=Bit2;
NewBit2=Bit1; NewBit2+=Bit2;
Data[Ptr2]=NewBit1; Data[Ptr2+step]=NewBit2;
}
}
}
}
#ifdef FWHT_TEST
#include "string.h"
int main(void)
{
T fwht_test[] = {1,0,1,0,0,1,1,0};
const int fwht_test_len = 8;
fwht(fwht_test, fwht_test_len);
printf("Fast Walsh-Hadamard Transform: [");
for (int i; i < 8; i++) { printf("%d,", fwht_test[i]); }
printf("]\n");
T ifwht_test[] = {1,0,1,0,0,1,1,0};
const int ifwht_test_len = 8;
ifwht(ifwht_test, ifwht_test_len);
printf("Inverse Fast Walsh-Hadamard Transform: [");
for (int i; i < 8; i++) { printf("%d,", ifwht_test[i]); }
printf("]\n");
return 0;
}
#endif
#endif /* FHT_H */

Wyświetl plik

@ -27,6 +27,6 @@
#include "samd20.h"
void olivia_mfsk_encode_block(char* buffer, int8_t* tones);
void olivia_mfsk_encode_block(char* buffer, uint8_t* tones);
#endif /* MFSK_H */

Wyświetl plik

@ -25,7 +25,8 @@
#include <string.h>
#include "samd20.h"
#include "msfk.h"
#include "mfsk.h"
#include "math/fwht.h"
//#define OLIVIA_MFSK_ENCODE_TEST
#ifdef OLIVIA_MFSK_ENCODE_TEST
@ -53,27 +54,120 @@ static const uint64_t ScramblingCodeContestia = 0xEDB88320LL;
* https://github.com/jamescoxon/dl-fldigi/blob/master/src/include/jalocha/pj_mfsk.h
*/
size_t BitsPerSymbol = 5;
size_t Symbols = 32;
size_t BitsPerCharacter = 7;
size_t SymbolsPerBlock = 64;
uint8_t bContestia = 0;
int8_t FHT_Buffer[64]; /* SymbolsPerBlock */
uint8_t OutputBlock[64]; /* SymbolsPerBlock */
static const uint64_t ScramblingCode = 0xE257E6D0291574ECLL;
void EncodeCharacter(uint8_t Char) {
size_t TimeBit;
uint8_t Mask = (SymbolsPerBlock << 1) - 1;
if (bContestia) {
if (Char >= 'a' && Char <= 'z')
Char += 'A' - 'a';
if (Char == ' ')
Char = 59;
else if (Char == '\r')
Char = 60;
else if (Char == '\n')
Char = 0;
else if (Char >= 33 && Char <= 90)
Char -= 32;
else if (Char == 8)
Char = 61;
else if (Char == 0)
Char = 0;
else
Char = '?' - 32;
//} else if (bRTTYM) {
} else {
Char &= Mask;
}
for (TimeBit = 0; TimeBit < SymbolsPerBlock; TimeBit++)
FHT_Buffer[TimeBit] = 0;
if (Char<SymbolsPerBlock)
FHT_Buffer[Char] = 1;
else
FHT_Buffer[Char-SymbolsPerBlock] = (-1);
ifwht(FHT_Buffer, SymbolsPerBlock);
}
void ScrambleFHT(size_t CodeOffset)
{ size_t TimeBit;
size_t CodeWrap=(SymbolsPerBlock-1);
size_t CodeBit=CodeOffset&CodeWrap;
for (TimeBit=0; TimeBit<SymbolsPerBlock; TimeBit++)
{ uint64_t CodeMask=1; CodeMask<<=CodeBit;
if (ScramblingCode&CodeMask)
FHT_Buffer[TimeBit] = (-FHT_Buffer[TimeBit]);
CodeBit+=1; CodeBit&=CodeWrap; }
}
void EncodeBlock(uint8_t *InputBlock) {
size_t FreqBit;
size_t TimeBit;
size_t nShift;
nShift = (bContestia) ? 5 : 13; // Contestia/RTTYM or Olivia
for (TimeBit = 0; TimeBit < SymbolsPerBlock; TimeBit ++)
OutputBlock[TimeBit] = 0;
for (FreqBit = 0; FreqBit < BitsPerSymbol; FreqBit++) {
EncodeCharacter(InputBlock[FreqBit]);
ScrambleFHT(FreqBit * nShift);
size_t Rotate = 0;
for (TimeBit = 0; TimeBit < SymbolsPerBlock; TimeBit++) {
if (FHT_Buffer[TimeBit] < 0) {
size_t Bit = FreqBit+Rotate;
if (Bit >= BitsPerSymbol) Bit -= BitsPerSymbol;
uint8_t Mask = 1;
Mask <<= Bit;
OutputBlock[TimeBit] |= Mask;
}
Rotate += 1;
if (Rotate >= BitsPerSymbol)
Rotate -= BitsPerSymbol;
}
}
}
/**
* This function encodes a single block of Olivia MFSK
*
* It takes a buffer of ASCII-encoded text and returns an array of
* tones to transmit.
*/
void olivia_mfsk_encode_block(char* buffer, int8_t* tones)
void olivia_mfsk_encode_block(char* buffer, uint8_t* tones)
{
size_t bits_per_character = 7;
size_t bits_per_symbol = 5; /* That is, there are 2^5=32 tones */
size_t symbols_per_block = 64;
/* TODO! */
/* For the moment do this */
EncodeBlock((uint8_t*)buffer);
memcpy(tones, OutputBlock, symbols_per_block);
}
#ifdef OLIVIA_MFSK_ENCODE_TEST