mirror of
https://github.com/cnlohr/lolra.git
synced 2026-06-15 07:19:25 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e79b88354 |
@@ -0,0 +1,8 @@
|
||||
all : genericgen
|
||||
|
||||
genericgen : genericgen.c
|
||||
gcc -g -o $@ $^
|
||||
|
||||
clean :
|
||||
rm -rf genericgen
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
/**
|
||||
|
||||
MIT-like-non-ai-license
|
||||
|
||||
Copyright (c) 2024 Charles Lohr "CNLohr"
|
||||
|
||||
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 two following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
In addition the following restrictions apply:
|
||||
|
||||
1. The Software and any modifications made to it may not be used for the
|
||||
purpose of training or improving machine learning algorithms, including but not
|
||||
limited to artificial intelligence, natural language processing, or data
|
||||
mining. This condition applies to any derivatives, modifications, or updates
|
||||
based on the Software code. Any usage of the Software in an AI-training dataset
|
||||
is considered a breach of this License.
|
||||
|
||||
2. The Software may not be included in any dataset used for training or
|
||||
improving machine learning algorithms, including but not limited to artificial
|
||||
intelligence, natural language processing, or data mining.
|
||||
|
||||
3. Any person or organization found to be in violation of these restrictions
|
||||
will be subject to legal action and may be held liable for any damages
|
||||
resulting from such use.
|
||||
|
||||
If any term is unenforcable, other terms remain in-force.
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
// Designed for generating chirp buffer to mimic hackaday badge... The idea is
|
||||
// you can feed this data you want to send... and it feeds you a generic
|
||||
// language of quarter chirps telling you when to up or down chirp.
|
||||
//
|
||||
// If the output value is negative, you need to emit a down-chirp. If it is
|
||||
// positive, you output an up-chirp.
|
||||
//
|
||||
// Down chirps are represented in one's compliment.
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../lib/LoRa-SDR-Code.h"
|
||||
|
||||
// Optionally send LoRaWAN messages. Be sure to copy your keys from the things network.
|
||||
//#define LORAWAN
|
||||
#define HACKADAY
|
||||
|
||||
|
||||
#ifdef LORAWAN
|
||||
#include "lorawan_simple.h"
|
||||
static const uint8_t payload_key[AES_BLOCKLEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // AppSKey Big Endian
|
||||
static const uint8_t network_skey[AES_BLOCKLEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // NwkSKey Big Endian
|
||||
static const uint8_t devaddress[4] = { 0x00, 0x00, 0x00, 0x00 }; // Device address Little Endian LSB (Written backwards from Device address default view)
|
||||
#endif
|
||||
|
||||
#ifdef HACKADAY
|
||||
#define SF_NUMBER 7
|
||||
#define CHIRPLENGTH_WORDS 128
|
||||
#endif
|
||||
|
||||
#if !defined( LORAWAN ) && !defined( HACKADAY )
|
||||
#error Need to define LORWAN or HACKADAY
|
||||
#endif
|
||||
|
||||
// Bits are shifted out MSBit first, then to LSBit
|
||||
|
||||
|
||||
#define MAX_BYTES 160
|
||||
#define MAX_SYMBOLS (MAX_BYTES*2+16)
|
||||
|
||||
// Our table is bespoke for the specific SF.
|
||||
#define CHIPSSPREAD CHIRPLENGTH_WORDS // QUARTER_CHIRP_LENGTH_WORDS (TODO: Use the quater value elsewhere in the code)
|
||||
#define MARK_FROM_SF0 (1<<SF_NUMBER) // SF7
|
||||
|
||||
#define PREAMBLE_CHIRPS 16
|
||||
#define CODEWORD_LENGTH 2
|
||||
|
||||
uint32_t quadsetcount;
|
||||
int16_t quadsets[MAX_SYMBOLS*4+PREAMBLE_CHIRPS*4+9+CODEWORD_LENGTH*4];
|
||||
int runningcount_bits = 0;
|
||||
volatile int fxcycle;
|
||||
volatile int quadsetplace = -1;
|
||||
|
||||
|
||||
|
||||
|
||||
int16_t * AddChirp( int16_t * qso, int offset, int verneer )
|
||||
{
|
||||
offset = offset * CHIPSSPREAD / (MARK_FROM_SF0);
|
||||
offset += verneer;
|
||||
*(qso++) = (CHIPSSPREAD * 0 / 4 + offset + CHIPSSPREAD ) % CHIPSSPREAD;
|
||||
*(qso++) = (CHIPSSPREAD * 1 / 4 + offset + CHIPSSPREAD ) % CHIPSSPREAD;
|
||||
*(qso++) = (CHIPSSPREAD * 2 / 4 + offset + CHIPSSPREAD ) % CHIPSSPREAD;
|
||||
*(qso++) = (CHIPSSPREAD * 3 / 4 + offset + CHIPSSPREAD ) % CHIPSSPREAD;
|
||||
return qso;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
#if 0
|
||||
SystemInit();
|
||||
|
||||
funGpioInitAll();
|
||||
|
||||
// Force HCLK to be nodiv. ch32vfun sets it to be a reasonbly high div.
|
||||
RCC->CFGR0 &= ~RCC_PPRE1_DIV16;
|
||||
|
||||
// MCO for testing.
|
||||
// funPinMode( PA8, GPIO_CFGLR_OUT_50Mhz_AF_PP ); RCC->CFGR0 |= RCC_CFGR0_MCO_PLL;
|
||||
|
||||
printf( "Switching to HSE\n" );
|
||||
Delay_Ms( 100 );
|
||||
|
||||
// Disable clock security system.
|
||||
RCC->CTLR &= ~RCC_CSSON;
|
||||
|
||||
#ifdef USE_EXTERNAL_CLOCK
|
||||
// No crystal - use clock.
|
||||
RCC->CTLR |= RCC_HSEBYP;
|
||||
#endif
|
||||
|
||||
// Enable external crystal
|
||||
RCC->CTLR |= RCC_HSEON;
|
||||
|
||||
// Set System Clock Source to be 0.
|
||||
RCC->CFGR0 = (RCC->CFGR0 & ~RCC_SW) | 0;
|
||||
|
||||
// Disable PLL
|
||||
RCC->CTLR &= ~RCC_PLLON;
|
||||
|
||||
|
||||
#ifdef USE_EXTERNAL_CLOCK
|
||||
// Set PLL to 9x not 18x
|
||||
RCC->CFGR0 = ( RCC->CFGR0 & ~RCC_PLLMULL18 ) | RCC_PLLMULL9;
|
||||
#endif
|
||||
|
||||
// Switch to HSE
|
||||
RCC->CFGR0 |= RCC_PLLSRC;
|
||||
|
||||
// Enable PLL
|
||||
RCC->CTLR |= RCC_PLLON;
|
||||
|
||||
// Wait for HSE to become ready.
|
||||
while( !( RCC->CTLR & RCC_HSERDY) );
|
||||
while( !( RCC->CTLR & RCC_PLLRDY) );
|
||||
RCC->CFGR0 |= RCC_SW_1; // Switch system clock to PLL
|
||||
printf( "HSE Switched\n" );
|
||||
Delay_Ms( 10 );
|
||||
RCC->CTLR &= ~RCC_HSION;
|
||||
Delay_Ms( 10 );
|
||||
printf( "HSI Off [%08lx %08lx]\n", RCC->CTLR, RCC->CFGR0 );
|
||||
|
||||
// funPinMode( PB12, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // NSS
|
||||
// funPinMode( PB13, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // SCK
|
||||
// funPinMode( PB14, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // MISO
|
||||
funPinMode( PB15, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // MOSI
|
||||
|
||||
RCC->APB1PRSTR = RCC_SPI2RST;
|
||||
RCC->APB1PRSTR = 0;
|
||||
RCC->APB1PCENR |= RCC_APB1Periph_SPI2;
|
||||
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
||||
|
||||
// Configure SPI
|
||||
SPI2->CTLR1 =
|
||||
SPI_NSS_Soft | SPI_CPHA_1Edge | SPI_CPOL_Low | SPI_DataSize_16b |
|
||||
SPI_Mode_Master | SPI_Direction_1Line_Tx |
|
||||
0 |
|
||||
0<<3; // Divisior = 0
|
||||
|
||||
// If using DMA may need this.
|
||||
SPI2->CTLR2 = SPI_CTLR2_TXDMAEN;
|
||||
|
||||
|
||||
SPI2->HSCR = 1; // High-speed enable.
|
||||
|
||||
SPI2->CTLR1 |= CTLR1_SPE_Set;
|
||||
//SPI2->DATAR = 0x55aa; // Set SPI line Low.
|
||||
|
||||
//DMA1_Channel5 is for SPI2TX
|
||||
DMA1_Channel5->PADDR = (uint32_t)&SPI2->DATAR;
|
||||
DMA1_Channel5->MADDR = (uint32_t)sendbuff;
|
||||
DMA1_Channel5->CNTR = 0;// sizeof( bufferset )/2; // Number of unique copies. (Don't start, yet!)
|
||||
DMA1_Channel5->CFGR =
|
||||
DMA_M2M_Disable |
|
||||
DMA_Priority_VeryHigh |
|
||||
DMA_MemoryDataSize_HalfWord |
|
||||
DMA_PeripheralDataSize_HalfWord |
|
||||
DMA_MemoryInc_Enable |
|
||||
DMA_Mode_Normal | // OR DMA_Mode_Circular or DMA_Mode_Normal
|
||||
DMA_DIR_PeripheralDST |
|
||||
DMA_IT_TC | DMA_IT_HT; // Transmission Complete + Half Empty Interrupts.
|
||||
|
||||
NVIC_EnableIRQ( DMA1_Channel5_IRQn );
|
||||
DMA1_Channel5->CFGR |= DMA_CFGR1_EN;
|
||||
|
||||
|
||||
memset( sendbuff, 0x00, sizeof( sendbuff ) );
|
||||
|
||||
// Enter critical section.
|
||||
DMA1_Channel5->CNTR = 0;
|
||||
DMA1_Channel5->MADDR = (uint32_t)sendbuff;
|
||||
DMA1_Channel5->CNTR = SENDBUFF_WORDS; // Number of unique uint16_t entries.
|
||||
DMA1_Channel5->CFGR |= DMA_Mode_Circular;
|
||||
#endif
|
||||
|
||||
uint16_t lora_symbols[MAX_SYMBOLS];
|
||||
int lora_symbols_count;
|
||||
|
||||
//while(1)
|
||||
{
|
||||
|
||||
//Delay_Ms( 1000 );
|
||||
|
||||
|
||||
#ifdef LORAWAN
|
||||
//Delay_Ms( 1000 );
|
||||
static uint32_t frame = 0;
|
||||
|
||||
// Send a message with LoraWan. Formatted specifically for thethings.network.
|
||||
uint8_t inner_payload_raw[24];
|
||||
int inner_payload_len = snprintf( (char*)inner_payload_raw, 24, "meow%lu ", frame%10 );
|
||||
inner_payload_len = 5;
|
||||
|
||||
// Just some random data.
|
||||
uint8_t raw_payload_with_b0[259+8] = { };
|
||||
uint8_t * payload_in = raw_payload_with_b0 + 16;
|
||||
uint8_t * pl = payload_in;
|
||||
int payload_in_size = 0;
|
||||
|
||||
pl += GenerateLoRaWANPacket( raw_payload_with_b0, inner_payload_raw, inner_payload_len, payload_key, network_skey, devaddress, frame++);
|
||||
|
||||
payload_in_size = pl - payload_in;
|
||||
|
||||
lora_symbols_count = 0;
|
||||
#else
|
||||
|
||||
// Just some random data.
|
||||
|
||||
uint8_t payload_in[128] = {
|
||||
0x07, 0xe9, 0x23, 0xee, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x16, 0xca,
|
||||
0x51, 0xd0, 0x06, 0x00, 0x02, 0x59, 0x6c, 0x6f, 0x6c, 0x72, 0x61, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x61, 0x61, 0x61, 0x61, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
int payload_in_size = sizeof(payload_in);
|
||||
|
||||
static int msgno = 0;
|
||||
payload_in[4] = msgno++;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
lora_symbols_count = 0;
|
||||
// int r = CreateMessageFromPayload( lora_symbols, &lora_symbols_count, MAX_SYMBOLS, SF_NUMBER, 4, payload_in, payload_in_size );
|
||||
|
||||
// I think the Hackaday swadge uses 5/4, not 8/4
|
||||
int r = CreateMessageFromPayload( lora_symbols, &lora_symbols_count, MAX_SYMBOLS, SF_NUMBER, 1, payload_in, payload_in_size );
|
||||
|
||||
if( r < 0 )
|
||||
{
|
||||
printf( "Failed to generate message (%d)\n", r );
|
||||
// Failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
int j;
|
||||
|
||||
quadsetcount = 0;
|
||||
int16_t * qso = quadsets;
|
||||
for( j = 0; j < PREAMBLE_CHIRPS; j++ )
|
||||
{
|
||||
qso = AddChirp( qso, 0, 0 );
|
||||
}
|
||||
|
||||
// Hackaday Syncword.
|
||||
uint8_t syncword = 0x21;
|
||||
|
||||
#define CODEWORD_SHIFT 3
|
||||
|
||||
if( CODEWORD_LENGTH > 0 )
|
||||
qso = AddChirp( qso, ( ( syncword & 0xf ) << CODEWORD_SHIFT ), 0 );
|
||||
if( CODEWORD_LENGTH > 1 )
|
||||
qso = AddChirp( qso, ( ( ( syncword & 0xf0 ) >> 4 ) << CODEWORD_SHIFT ), 0);
|
||||
|
||||
*(qso++) = -(CHIPSSPREAD * 0 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 1 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 2 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 3 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 0 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 1 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 2 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 3 / 4 )-1;
|
||||
*(qso++) = -(CHIPSSPREAD * 0 / 4 )-1;
|
||||
|
||||
if( SF_NUMBER <= 6 )
|
||||
{
|
||||
// Two additional upchirps with SF6 https://github.com/tapparelj/gr-lora_sdr/issues/74#issuecomment-1891569580
|
||||
for( j = 0; j < 2; j++ )
|
||||
qso = AddChirp( qso, 0, 0 );
|
||||
}
|
||||
|
||||
for( j = 0; j < lora_symbols_count; j++ )
|
||||
{
|
||||
int ofs = lora_symbols[j];
|
||||
//ofs = ofs ^ ((MARK_FROM_SF6<<6) -1);
|
||||
//ofs &= (MARK_FROM_SF6<<6) -1;
|
||||
qso = AddChirp( qso, ofs, 0 );
|
||||
//printf( "0x%03x, ", ofs );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
printf( "const int16_t quadstarts[%ld] = {", qso - quadsets );
|
||||
for (j = 0; j < qso - quadsets; j++ )
|
||||
{
|
||||
if( ( j & 0xf ) == 0 ) printf( "\n\t" );
|
||||
printf( "%4d, ", quadsets[j] );
|
||||
}
|
||||
printf( "};\n" );
|
||||
//int16_t * qso = quadsets
|
||||
|
||||
|
||||
runningcount_bits = 0;
|
||||
|
||||
// This tells the interrupt we have data.
|
||||
quadsetcount = qso - quadsets + 0;
|
||||
printf( "--- %d [%d] %d\n", (int)lora_symbols_count, (int)quadsetcount, CHIPSSPREAD/4 );
|
||||
|
||||
quadsetplace = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user