kopia lustrzana https://github.com/kamocat/uSDX
Made driver for si5351
Also included some of Guido's trig approximations (magn, arctan3)chibios
rodzic
a1298df605
commit
776d4224ac
|
@ -67,9 +67,7 @@
|
|||
|
||||
<sourceEntries>
|
||||
|
||||
<entry excluding="radio" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="radio"/>
|
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
|
||||
</sourceEntries>
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ LDSCRIPT= $(STARTUPLD)/STM32F051x8.ld
|
|||
# setting.
|
||||
CSRC = $(ALLCSRC) \
|
||||
$(TESTSRC) \
|
||||
main.c radio/rx.c
|
||||
main.c radio/rx.c drivers/si5351.c trig.c
|
||||
|
||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* si5351.c
|
||||
*
|
||||
* Created on: Jul 7, 2020
|
||||
* Author: marshal
|
||||
*/
|
||||
#include "si5351.h"
|
||||
#include "../trig.h"
|
||||
|
||||
void synth_en(struct synth * cfg){
|
||||
uint8_t buf[2];
|
||||
buf[0]=cfg->channel+16;
|
||||
buf[1]=cfg->PLLx ? 0x2F : 0x1F;
|
||||
const uint8_t si5351 = 0x60;
|
||||
i2cMasterTransmitTimeout(&I2CD1, si5351, buf, 2,
|
||||
NULL, 0, TIME_MS2I(100));
|
||||
}
|
||||
|
||||
void synth_write_params(uint8_t reg, uint64_t val, uint8_t div){
|
||||
uint8_t buf[9];
|
||||
buf[0]=reg*8+26;
|
||||
buf[1]=0xFF; // denominator is always 0xFFFFF
|
||||
buf[2]=0xFF;
|
||||
buf[3]=val>>36 & 0x03;
|
||||
buf[3]|=div<<4;
|
||||
buf[4]=val>>28;
|
||||
buf[5]=val>>20;
|
||||
buf[6]=val>>16 | 0xF0;
|
||||
buf[7]=val>>8;
|
||||
buf[8]=val;
|
||||
|
||||
const uint8_t si5351 = 0x60;
|
||||
i2cMasterTransmitTimeout(&I2CD1, si5351, buf, 9, NULL, 0, TIME_MS2I(100));
|
||||
}
|
||||
|
||||
void synth_set_carrier(struct synth * cfg, float carrier){
|
||||
// Calculate PLL and Multisynth values
|
||||
const double xtal = 27e6;
|
||||
double pll = 27; // Good starting value to put vxco at 750MHz
|
||||
double div = xtal * pll / carrier;
|
||||
double delta = div - (xtal*pll)/(carrier+1); // Linearized change per Hz
|
||||
int8_t delta_shift = round(log2(delta)); // round to nearest power of 2
|
||||
double delta2 = (0x40000000>>delta_shift)*(1.0/0x40000000U); // (Computing a negative power of 2)
|
||||
div *= delta2/delta;
|
||||
div = round(div/2)*2+1; // Minimize chance of rollover
|
||||
pll = carrier * div / xtal; // Adjust pll to match
|
||||
|
||||
// If desired frequency is very low, we need to use the additional divider register
|
||||
uint8_t div2;
|
||||
for(div2=0; div>2048; ++div2){
|
||||
div *= 0.5;
|
||||
--delta_shift;
|
||||
}
|
||||
|
||||
// Store values into config
|
||||
const uint32_t fixed_shift = 1<<27; //For shifting values to fixed-point
|
||||
cfg->reg.pll = pll * fixed_shift;
|
||||
cfg->reg.synth = div * fixed_shift;
|
||||
cfg->reg.shift = delta_shift;
|
||||
cfg->reg.divide = div2;
|
||||
|
||||
// Write changes to chip
|
||||
synth_write_params(cfg->PLLx, cfg->reg.pll, 0);
|
||||
synth_write_params(cfg->channel+2, cfg->reg.synth, cfg->reg.divide);
|
||||
synth_en(cfg);
|
||||
}
|
||||
|
||||
void synth_set_baseband(struct synth * cfg, int32_t baseband){
|
||||
int32_t diff = baseband - cfg->baseband;
|
||||
diff >>= cfg->reg.shift;
|
||||
cfg->reg.synth -= diff;
|
||||
uint32_t val = cfg->reg.synth;
|
||||
uint8_t buf[5];
|
||||
/* This could potentially be sped up by dropping the last byte */
|
||||
buf[0]=8*(cfg->channel)+46;
|
||||
buf[1]=val>>20;
|
||||
buf[2]=(val>>16) | 0xF0;
|
||||
buf[3]=val>>8;
|
||||
buf[4]=val;
|
||||
const uint8_t si5351 = 0x60;
|
||||
i2cMasterTransmitTimeout(&I2CD1, si5351, buf, 5,NULL, 0, TIME_MS2I(100));
|
||||
}
|
||||
|
||||
void synth_init(struct synth * cfg, uint8_t channel, uint8_t pll){
|
||||
cfg->channel = channel;
|
||||
cfg->PLLx = pll;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* si5351.h
|
||||
*
|
||||
* Created on: Jul 8, 2020
|
||||
* Author: marshal
|
||||
*/
|
||||
|
||||
#ifndef SI5351_H_
|
||||
#define SI5351_H_
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
struct synth{
|
||||
float carrier; //< in Hz
|
||||
int32_t baseband; //< 15.16 fixed-point, in Hz
|
||||
struct { //< Calculated values for setting registers
|
||||
uint64_t pll:38; //< 11.27 fixed-point for PLL multipler
|
||||
uint64_t synth:38; //< 11.27 fixed-point for Synth Divider
|
||||
uint8_t divide:2; //< 4-bit field for extra divider settings
|
||||
int8_t shift; //< Shift value for scaling the baseband frequency
|
||||
}reg;
|
||||
uint8_t channel:2; //Supports four channels - increase bit width if more are desired
|
||||
uint8_t PLLx:1; //< 0 is PLLA, 1 is PLLB
|
||||
};
|
||||
|
||||
void synth_init(struct synth * cfg, uint8_t channel, uint8_t pll);
|
||||
void synth_en(struct synth * cfg);
|
||||
void synth_set_carrier(struct synth * cfg, float carrier);
|
||||
void synth_set_baseband(struct synth * cfg, int32_t baseband);
|
||||
void synth_write_params(uint8_t reg, uint64_t val, uint8_t div);
|
||||
|
||||
|
||||
#endif /* SI5351_H_ */
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* trig.c
|
||||
*
|
||||
* Created on: Jul 6, 2020
|
||||
* Author: marshal
|
||||
*/
|
||||
#include "trig.h"
|
||||
|
||||
inline int16_t arctan3(int16_t q, int16_t i) // error ~ 0.8 degree
|
||||
{ // source: [1] http://www-labs.iro.umontreal.ca/~mignotte/IFT2425/Documents/EfficientApproximationArctgFunction.pdf
|
||||
#define _atan2(z) (_UA/8 - _UA/22 * z + _UA/22) * z //derived from (5) [1]
|
||||
//#define _atan2(z) (_UA/8 - _UA/24 * z + _UA/24) * z //derived from (7) [1]
|
||||
int16_t r;
|
||||
if(abs(q) > abs(i))
|
||||
r = _UA / 4 - _atan2(abs(i) / abs(q)); // arctan(z) = 90-arctan(1/z)
|
||||
else
|
||||
r = (i == 0) ? 0 : _atan2(abs(q) / abs(i)); // arctan(z)
|
||||
r = (i < 0) ? _UA / 2 - r : r; // arctan(-z) = -arctan(z)
|
||||
return (q < 0) ? -r : r; // arctan(-z) = -arctan(z)
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* trig.h
|
||||
*
|
||||
* Created on: Jul 8, 2020
|
||||
* Author: marshal
|
||||
*/
|
||||
|
||||
#ifndef TRIG_H_
|
||||
#define TRIG_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define F_SAMP_TX 4810 //4810 // ADC sample-rate; is best a multiple of _UA and fits exactly in OCR0A = ((F_CPU / 64) / F_SAMP_TX) - 1 , should not exceed CPU utilization
|
||||
#define _UA (F_SAMP_TX) //360 // unit angle; integer representation of one full circle turn or 2pi radials or 360 degrees, should be a integer divider of F_SAMP_TX and maximized to have higest precision
|
||||
|
||||
// Stdlib includes abs, but I'm not sure we want it. This works for all numerical types.
|
||||
#define abs(x) (x>=0?x:-x)
|
||||
|
||||
int16_t arctan3(int16_t q, int16_t i);
|
||||
|
||||
#define magn(i, q) (abs(i) > abs(q) ? abs(i) + abs(q) / 4 : abs(q) + abs(i) / 4) // approximation of: magnitude = sqrt(i*i + q*q); error 0.95dB
|
||||
|
||||
|
||||
#endif /* TRIG_H_ */
|
Ładowanie…
Reference in New Issue