mirror of
https://github.com/nqrduck/ATM.git
synced 2024-11-25 11:32:28 +00:00
Change to PlatformIO
This commit is contained in:
commit
b3ffde53d1
33 changed files with 4067 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
5
include/Debug.h
Normal file
5
include/Debug.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#ifdef DEBUG
|
||||
#define DEBUG_PRINT(x) Serial.println (x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#endif
|
27
include/Pins.h
Normal file
27
include/Pins.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//SPI Pins
|
||||
#define SCLK_PIN 14
|
||||
#define MOSI_PIN 13
|
||||
#define MISO_PIN 12
|
||||
|
||||
//ADF Pins
|
||||
#define LE_PIN 27
|
||||
#define CE_PIN 25
|
||||
|
||||
// Pins M1
|
||||
#define EN_PIN_M1 25
|
||||
#define DIR_PIN_M1 33
|
||||
#define STEP_PIN_M1 32
|
||||
#define CS_PIN_M1 26
|
||||
|
||||
#define DIAG1_PIN_M1 2 // used for homing
|
||||
|
||||
// Pins M2
|
||||
#define EN_PIN_M2 17
|
||||
#define DIR_PIN_M2 19
|
||||
#define STEP_PIN_M2 5
|
||||
#define CS_PIN_M2 18
|
||||
|
||||
#define DIAG1_PIN_M2 4 // used for homing
|
||||
|
||||
//ADC Pin
|
||||
#define REFLECTION_PIN 15
|
14
include/Positions.h
Normal file
14
include/Positions.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Position @ 50, 75, 100, 125, 150, 175, 200 MHz
|
||||
struct FREQUENCY_POSITION {
|
||||
uint32_t FREQUENCY;
|
||||
uint32_t TUNING_POSITION;
|
||||
uint32_t MATCHING_POSITION;
|
||||
};
|
||||
|
||||
// Settings for 100MHz -18dB
|
||||
#define TUNING_STEPPER_HOME 34100U
|
||||
#define MATCHING_STEPPER_HOME 32000U
|
||||
|
||||
// Settings for 125MHz -30dB
|
||||
//#define TUNING_STEPPER_HOME 37550U
|
||||
//#define MATCHING_STEPPER_HOME 29500U
|
39
include/README
Normal file
39
include/README
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
12
include/Stepper.h
Normal file
12
include/Stepper.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Stepper Settings
|
||||
#define STEPS_PER_ROTATION 3200U // 200 * 16 -> Microstepping
|
||||
|
||||
// Stall Detection sensitivity
|
||||
#define STALL_VALUE 16 // [-64..63]
|
||||
|
||||
struct Stepper{
|
||||
AccelStepper STEPPER;
|
||||
TMC2130Stepper DRIVER;
|
||||
int STALL_PIN;
|
||||
int HOME_POSITION;
|
||||
};
|
336
lib/ADF4351/ADF4351.cpp
Normal file
336
lib/ADF4351/ADF4351.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
#include "ADF4351.h"
|
||||
|
||||
#define ADF_FREQ_MAX 4294967295UL ///< Maximum Generated Frequency = value of MAX Unsigned Long
|
||||
#define ADF_FREQ_MIN 34385000UL ///< Minimum Generated Frequency
|
||||
#define ADF_PFD_MAX 32000000.0 ///< Maximum Frequency for Phase Detector
|
||||
#define ADF_PFD_MIN 125000.0 ///< Minimum Frequency for Phase Detector
|
||||
#define ADF_REFIN_MAX 250000000UL ///< Maximum Reference Frequency
|
||||
#define REF_FREQ_DEFAULT 250000000UL ///< Default Reference Frequency
|
||||
|
||||
uint32_t steps[] = { 1000, 5000, 10000, 50000, 100000 , 500000, 1000000 }; ///< Array of Allowed Step Values (Hz)
|
||||
|
||||
|
||||
/*!
|
||||
single register constructor
|
||||
*/
|
||||
Reg::Reg()
|
||||
{
|
||||
whole = 0 ;
|
||||
}
|
||||
|
||||
uint32_t Reg::get()
|
||||
{
|
||||
return whole ;
|
||||
}
|
||||
|
||||
void Reg::set(uint32_t value)
|
||||
{
|
||||
whole = value ;
|
||||
}
|
||||
|
||||
void Reg::setbf(uint8_t start, uint8_t len, uint32_t value)
|
||||
{
|
||||
uint32_t bitmask = ((1UL << len) - 1UL) ;
|
||||
value &= bitmask ;
|
||||
bitmask <<= start ;
|
||||
whole = ( whole & ( ~bitmask)) | ( value << start ) ;
|
||||
}
|
||||
|
||||
uint32_t Reg::getbf(uint8_t start, uint8_t len)
|
||||
{
|
||||
uint32_t bitmask = ((1UL << len) - 1UL) << start ;
|
||||
uint32_t result = ( whole & bitmask) >> start ;
|
||||
return ( result ) ;
|
||||
}
|
||||
|
||||
// Constructor function; initializes communication pinouts
|
||||
ADF4351::ADF4351(int SCLK, int DATA, int LE, int CE){
|
||||
_sclk = SCLK;
|
||||
_data=DATA;
|
||||
_le=LE;
|
||||
_ce=CE;
|
||||
|
||||
SPIClass SPI1(HSPI);
|
||||
spi_settings = SPISettings(1000000UL, MSBFIRST, SPI_MODE0) ;
|
||||
|
||||
reffreq = REF_FREQ_DEFAULT ;
|
||||
cfreq = 0 ;
|
||||
ChanStep = steps[0] ;
|
||||
RD2refdouble = 0 ;
|
||||
RCounter = 25 ;
|
||||
RD1Rdiv2 = 0 ;
|
||||
BandSelClock = 80 ;
|
||||
ClkDiv = 150 ;
|
||||
Prescaler = 0 ;
|
||||
pwrlevel = 0 ;
|
||||
}
|
||||
|
||||
void ADF4351::begin(void){
|
||||
pinMode(_sclk, OUTPUT);
|
||||
pinMode(_data, OUTPUT);
|
||||
pinMode(_le, OUTPUT);
|
||||
pinMode(_ce, OUTPUT);
|
||||
|
||||
SPI1.begin();
|
||||
}
|
||||
|
||||
int ADF4351::setf(uint32_t freq)
|
||||
{
|
||||
// calculate settings from freq
|
||||
if ( freq > ADF_FREQ_MAX ) return 1 ;
|
||||
|
||||
if ( freq < ADF_FREQ_MIN ) return 1 ;
|
||||
|
||||
int localosc_ratio = 2200000000UL / freq ;
|
||||
outdiv = 1 ;
|
||||
int RfDivSel = 0 ;
|
||||
|
||||
// select the output divider
|
||||
while ( outdiv <= localosc_ratio && outdiv <= 64 ) {
|
||||
outdiv *= 2 ;
|
||||
RfDivSel++ ;
|
||||
}
|
||||
|
||||
if ( freq > 3600000000UL/outdiv )
|
||||
Prescaler = 1 ;
|
||||
else
|
||||
Prescaler = 0 ;
|
||||
|
||||
PFDFreq = (float) reffreq * ( (float) ( 1.0 + RD2refdouble) / (float) (RCounter * (1.0 + RD1Rdiv2))); // find the loop freq
|
||||
BigNumber::begin(10) ;
|
||||
char tmpstr[20] ;
|
||||
// kludge - BigNumber doesn't like leading spaces
|
||||
// so you need to make sure the string passed doesnt
|
||||
// have leading spaces.
|
||||
int cntdigits = 0 ;
|
||||
uint32_t num = (uint32_t) ( PFDFreq / 10000 ) ;
|
||||
|
||||
while ( num != 0 ) {
|
||||
cntdigits++ ;
|
||||
num /= 10 ;
|
||||
}
|
||||
|
||||
dtostrf(PFDFreq, cntdigits + 8 , 3, tmpstr) ;
|
||||
// end of kludge
|
||||
BigNumber BN_PFDFreq = BigNumber(tmpstr) ;
|
||||
BigNumber BN_N = ( BigNumber(freq) * BigNumber(outdiv) ) / BN_PFDFreq ;
|
||||
N_Int = (uint16_t) ( (uint32_t) BN_N ) ;
|
||||
BigNumber BN_Mod = BN_PFDFreq / BigNumber(ChanStep) ;
|
||||
Mod = BN_Mod ;
|
||||
BN_Mod = BigNumber(Mod) ;
|
||||
BigNumber BN_Frac = ((BN_N - BigNumber(N_Int)) * BN_Mod) + BigNumber("0.5") ;
|
||||
Frac = (int) ( (uint32_t) BN_Frac);
|
||||
BN_N = BigNumber(N_Int) ;
|
||||
|
||||
if ( Frac != 0 ) {
|
||||
uint32_t gcd = gcd_iter(Frac, Mod) ;
|
||||
|
||||
if ( gcd > 1 ) {
|
||||
Frac /= gcd ;
|
||||
BN_Frac = BigNumber(Frac) ;
|
||||
Mod /= gcd ;
|
||||
BN_Mod = BigNumber(Mod) ;
|
||||
}
|
||||
}
|
||||
|
||||
BigNumber BN_cfreq ;
|
||||
|
||||
if ( Frac == 0 ) {
|
||||
BN_cfreq = ( BN_PFDFreq * BN_N) / BigNumber(outdiv) ;
|
||||
|
||||
} else {
|
||||
BN_cfreq = ( BN_PFDFreq * ( BN_N + ( BN_Frac / BN_Mod) ) ) / BigNumber(outdiv) ;
|
||||
}
|
||||
|
||||
cfreq = BN_cfreq ;
|
||||
|
||||
if ( cfreq != freq ) Serial.println(F("output freq diff than requested")) ;
|
||||
|
||||
BigNumber::finish() ;
|
||||
|
||||
if ( Mod < 2 || Mod > 4095) {
|
||||
Serial.println(F("Mod out of range")) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
if ( (uint32_t) Frac > (Mod - 1) ) {
|
||||
Serial.println(F("Frac out of range")) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
if ( Prescaler == 0 && ( N_Int < 23 || N_Int > 65535)) {
|
||||
Serial.println(F("N_Int out of range")) ;
|
||||
return 1;
|
||||
|
||||
} else if ( Prescaler == 1 && ( N_Int < 75 || N_Int > 65535 )) {
|
||||
Serial.println(F("N_Int out of range")) ;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// setting the registers to default values
|
||||
// R0
|
||||
R[0].set(0UL) ;
|
||||
// (0,3,0) control bits
|
||||
R[0].setbf(3, 12, Frac) ; // fractonal
|
||||
R[0].setbf(15, 16, N_Int) ; // N integer
|
||||
// R1
|
||||
R[1].set(0UL) ;
|
||||
R[1].setbf(0, 3, 1) ; // control bits
|
||||
R[1].setbf(3, 12, Mod) ; // Mod
|
||||
R[1].setbf(15, 12, 1); // phase
|
||||
R[1].setbf(27, 1, Prescaler); // prescaler
|
||||
// (28,1,0) phase adjust
|
||||
// R2
|
||||
R[2].set(0UL) ;
|
||||
R[2].setbf(0, 3, 2) ; // control bits
|
||||
// (3,1,0) counter reset
|
||||
// (4,1,0) cp3 state
|
||||
// (5,1,0) power down
|
||||
R[2].setbf(6, 1, 1) ; // pd polarity
|
||||
|
||||
if ( Frac == 0 ) {
|
||||
R[2].setbf(7, 1, 1) ; // LDP, int-n mode
|
||||
R[2].setbf(8, 1, 1) ; // ldf, int-n mode
|
||||
|
||||
} else {
|
||||
R[2].setbf(7, 1, 0) ; // LDP, frac-n mode
|
||||
R[2].setbf(8, 1, 0) ; // ldf ,frac-n mode
|
||||
}
|
||||
|
||||
R[2].setbf(9, 4, 7) ; // charge pump
|
||||
// (13,1,0) dbl buf
|
||||
R[2].setbf(14, 10, RCounter) ; // r counter
|
||||
R[2].setbf(24, 1, RD1Rdiv2) ; // RD1_RDiv2
|
||||
R[2].setbf(25, 1, RD2refdouble) ; // RD2refdouble
|
||||
// R[2].setbf(26,3,0) ; // muxout, not used
|
||||
// (29,2,0) low noise and spurs mode
|
||||
// R3
|
||||
R[3].set(0UL) ;
|
||||
R[3].setbf(0, 3, 3) ; // control bits
|
||||
R[3].setbf(3, 12, ClkDiv) ; // clock divider
|
||||
|
||||
// (15,2,0) clk div mode
|
||||
// (17,1,0) reserved
|
||||
// (18,1,0) CSR
|
||||
// (19,2,0) reserved
|
||||
if ( Frac == 0 ) {
|
||||
R[3].setbf(21, 1, 1); // charge cancel, reduces pfd spurs
|
||||
R[3].setbf(22, 1, 1); // ABP, int-n
|
||||
|
||||
} else {
|
||||
R[3].setbf(21, 1, 0) ; // charge cancel
|
||||
R[3].setbf(22, 1, 0); // ABP, frac-n
|
||||
}
|
||||
|
||||
R[3].setbf(23, 1, 1) ; // Band Select Clock Mode
|
||||
// (24,8,0) reserved
|
||||
// R4
|
||||
R[4].set(0UL) ;
|
||||
R[4].setbf(0, 3, 4) ; // control bits
|
||||
R[4].setbf(3, 2, pwrlevel) ; // output power 0-3 (-4dbM to 5dbM, 3db steps)
|
||||
R[4].setbf(5, 1, 1) ; // rf output enable
|
||||
// (6,2,0) aux output power
|
||||
// (8,1,0) aux output enable
|
||||
// (9,1,0) aux output select
|
||||
// (10,1,0) mtld
|
||||
// (11,1,0) vco power down
|
||||
R[4].setbf(12, 8, BandSelClock) ; // band select clock divider
|
||||
R[4].setbf(20, 3, RfDivSel) ; // rf divider select
|
||||
R[4].setbf(23, 1, 1) ; // feedback select
|
||||
// (24,8,0) reserved
|
||||
// R5
|
||||
R[5].set(0UL) ;
|
||||
R[5].setbf(0, 3, 5) ; // control bits
|
||||
// (3,16,0) reserved
|
||||
R[5].setbf(19, 2, 3) ; // Reserved field,set to 11
|
||||
// (21,1,0) reserved
|
||||
R[5].setbf(22, 2, 1) ; // LD Pin Mode
|
||||
// (24,8,0) reserved
|
||||
int i ;
|
||||
|
||||
SPI1.beginTransaction(spi_settings);
|
||||
for (i = 5 ; i > -1 ; i--) {
|
||||
WriteRegister(getReg(i)) ;
|
||||
//delayMicroseconds(2500) ;
|
||||
}
|
||||
SPI1.endTransaction();
|
||||
|
||||
return 0 ; // ok
|
||||
}
|
||||
|
||||
int ADF4351::setrf(uint32_t f)
|
||||
{
|
||||
if ( f > ADF_REFIN_MAX ) return 1 ;
|
||||
|
||||
if ( f < 100000UL ) return 1 ;
|
||||
|
||||
float newfreq = (float) f * ( (float) ( 1.0 + RD2refdouble) / (float) (RCounter * (1.0 + RD1Rdiv2))); // check the loop freq
|
||||
|
||||
if ( newfreq > ADF_PFD_MAX ) return 1 ;
|
||||
|
||||
if ( newfreq < ADF_PFD_MIN ) return 1 ;
|
||||
|
||||
reffreq = f ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
// write data into register
|
||||
void ADF4351::WriteRegister(uint32_t regData){
|
||||
/*digitalWrite(_le, LOW);
|
||||
_regData = regData;
|
||||
|
||||
for(int i=0; i<32; i++)
|
||||
{
|
||||
if(((_regData<<i)&0x80000000)==0x80000000)
|
||||
{
|
||||
digitalWrite(_data,1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(_data,0) ;
|
||||
|
||||
}
|
||||
|
||||
digitalWrite(_sclk, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_sclk, LOW);
|
||||
}
|
||||
|
||||
// load data into register
|
||||
digitalWrite(_le, HIGH);
|
||||
delay(1);
|
||||
digitalWrite(_le, LOW);*/
|
||||
|
||||
byte txbyte ;
|
||||
digitalWrite(_le, LOW) ;
|
||||
|
||||
for (int i = 3 ; i > -1 ; i--) {
|
||||
txbyte = (byte) (regData >> (i * 8)) ;
|
||||
SPI1.transfer(txbyte) ;
|
||||
}
|
||||
|
||||
digitalWrite(_le, HIGH) ;
|
||||
delayMicroseconds(5) ;
|
||||
digitalWrite(_le, LOW) ;
|
||||
|
||||
}
|
||||
|
||||
uint32_t ADF4351::getReg(int n)
|
||||
{
|
||||
return R[n].whole ;
|
||||
}
|
||||
|
||||
uint32_t ADF4351::gcd_iter(uint32_t u, uint32_t v)
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
while (v) {
|
||||
t = u ;
|
||||
u = v ;
|
||||
v = t % v ;
|
||||
}
|
||||
|
||||
return u ;
|
||||
}
|
114
lib/ADF4351/ADF4351.h
Normal file
114
lib/ADF4351/ADF4351.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
#ifndef __ADF4351_H__
|
||||
#define __ADF4351_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
#include <BigNumber.h>
|
||||
|
||||
/*!
|
||||
@brief Stores a device register value
|
||||
|
||||
This class is used to store and manage a single ADF4351 register value
|
||||
and provide bit field manipulations.
|
||||
*/
|
||||
class Reg {
|
||||
public:
|
||||
/*!
|
||||
Constructor
|
||||
*/
|
||||
Reg();
|
||||
/*!
|
||||
get the current register value
|
||||
returns same value as getbf(0,32)
|
||||
@return unsigned long value of the register
|
||||
*/
|
||||
uint32_t get();
|
||||
/*!
|
||||
sets the register value
|
||||
@param value unsigned long
|
||||
*/
|
||||
void set(uint32_t value);
|
||||
/*!
|
||||
current register value
|
||||
|
||||
returns same value as getbf(0,32)
|
||||
*/
|
||||
uint32_t whole;
|
||||
/*!
|
||||
modifies the register value based on a value and bitfield (mask)
|
||||
@param start index of the bit to start the modification
|
||||
@param len length number of bits to modify
|
||||
@param value value to modify (value is truncated if larger than len bits)
|
||||
*/
|
||||
void setbf(uint8_t start, uint8_t len , uint32_t value);
|
||||
/*!
|
||||
gets the current register bitfield value, based on the start and length mask
|
||||
@param start index of the bit of where to start
|
||||
@param len length number of bits to get
|
||||
@return bitfield value
|
||||
*/
|
||||
uint32_t getbf(uint8_t start, uint8_t len);
|
||||
|
||||
};
|
||||
|
||||
class ADF4351{
|
||||
public:
|
||||
ADF4351(int SCLK, int DATA, int LE, int CE);
|
||||
void begin(void);
|
||||
|
||||
void setReferenceFrequency(uint32_t reffreq);
|
||||
|
||||
void WriteRegister(uint32_t regData);
|
||||
|
||||
int setf(uint32_t freq) ; // set freq
|
||||
|
||||
int setrf(uint32_t f) ; // set reference freq
|
||||
|
||||
uint32_t getReg(int n) ;
|
||||
|
||||
uint32_t gcd_iter(uint32_t u, uint32_t v) ;
|
||||
|
||||
Reg R[6] ;
|
||||
|
||||
SPISettings spi_settings;
|
||||
|
||||
SPIClass SPI1;
|
||||
|
||||
uint32_t reffreq;
|
||||
|
||||
uint32_t cfreq ;
|
||||
|
||||
uint16_t N_Int ;
|
||||
|
||||
int Frac ;
|
||||
|
||||
uint32_t Mod ;
|
||||
|
||||
float PFDFreq ;
|
||||
|
||||
uint32_t ChanStep;
|
||||
|
||||
int outdiv ;
|
||||
|
||||
uint8_t RD2refdouble ;
|
||||
|
||||
int RCounter ;
|
||||
|
||||
uint8_t RD1Rdiv2 ;
|
||||
|
||||
uint8_t BandSelClock ;
|
||||
|
||||
int ClkDiv ;
|
||||
|
||||
uint8_t Prescaler ;
|
||||
|
||||
byte pwrlevel ;
|
||||
|
||||
private:
|
||||
int _data, _sclk, _le, _ce;
|
||||
long _regData;
|
||||
};
|
||||
|
||||
#endif
|
21
lib/BigNumber/LICENSE
Normal file
21
lib/BigNumber/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2017-2018 S. Downey
|
||||
|
||||
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.
|
58
lib/BigNumber/README.md
Normal file
58
lib/BigNumber/README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
BigNumber
|
||||
=========
|
||||
|
||||
BigNumber library for Arduino devices.
|
||||
|
||||
Use 256-bit numbers on tiny platforms.
|
||||
|
||||
|
||||
ported from https://github.com/nickgammon/BigNumber
|
||||
|
||||
## Requirements
|
||||
|
||||
- Any Arduino Device: (recommended model) [Adafruit Feather HUZZAH with ESP8266 WiFi](https://www.adafruit.com/product/2821)
|
||||
- Arduino IDE: https://www.arduino.cc/en/Main/Software
|
||||
|
||||
## Usage
|
||||
|
||||
### Initialize the BigNumber library
|
||||
```cpp
|
||||
BigNumber.begin();
|
||||
```
|
||||
|
||||
### create your BigNumber
|
||||
|
||||
```cpp
|
||||
BigNumber bigNum;
|
||||
bigNum = "67411411944031530524562029520200239450929984281572279077458355238873731477537";
|
||||
```
|
||||
|
||||
```cpp
|
||||
BigNumber bigNum = "67411411944031530524562029520200239450929984281572279077458355238873731477537";
|
||||
```
|
||||
|
||||
### modify your BigNumber
|
||||
|
||||
|
||||
```cpp
|
||||
BigNumber bigNum = "67411411944031530524562029520200239450929984281572279077458355238873731477537";
|
||||
BigNumber base = 16;
|
||||
BigNumber multiplier = base.pow(8);
|
||||
bigNum *= multiplier;
|
||||
```
|
||||
|
||||
### Serial.print your BigNumber
|
||||
|
||||
```cpp
|
||||
BigNumber bigNum = "67411411944031530524562029520200239450929984281572279077458355238873731477537";
|
||||
Serial.println(bigNum);
|
||||
```
|
||||
> 67411411944031530524562029520200239450929984281572279077458355238873731477537
|
||||
|
||||
#
|
||||
|
||||
# More documentation and examples:
|
||||
|
||||
http://www.gammon.com.au/forum/?id=11519
|
||||
|
||||
|
32
lib/BigNumber/examples/Calculate_E/Calculate_E.pde
Normal file
32
lib/BigNumber/examples/Calculate_E/Calculate_E.pde
Normal file
|
@ -0,0 +1,32 @@
|
|||
// BigNumber test: calculate e
|
||||
#include "BigNumber.h"
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
|
||||
BigNumber::begin (50); // max around 160 on the Uno
|
||||
|
||||
// some big numbers
|
||||
BigNumber n = 1, e = 1, one = 1;
|
||||
|
||||
int i = 1;
|
||||
BigNumber E; // previous result
|
||||
|
||||
unsigned long start = millis ();
|
||||
do
|
||||
{
|
||||
E = e;
|
||||
n *= i++; // n is i factorial
|
||||
e += one / n;
|
||||
} while (e != E);
|
||||
unsigned long time = millis () - start;
|
||||
|
||||
Serial.println (e);
|
||||
Serial.print (time);
|
||||
Serial.println (" mS");
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
||||
|
25
lib/BigNumber/examples/Factorials/Factorials.pde
Normal file
25
lib/BigNumber/examples/Factorials/Factorials.pde
Normal file
|
@ -0,0 +1,25 @@
|
|||
// BigNumber test: factorials
|
||||
#include "BigNumber.h"
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
while (!Serial) ;
|
||||
delay(500);
|
||||
Serial.println ();
|
||||
BigNumber::begin (); // initialize library
|
||||
|
||||
//factorials
|
||||
BigNumber fact = 1;
|
||||
|
||||
for (int i = 2; i <= 200; i++)
|
||||
{
|
||||
Serial.print(i);
|
||||
Serial.print("! = ");
|
||||
fact *= i;
|
||||
Serial.println(fact);
|
||||
}
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
20
lib/BigNumber/examples/Multiplication/Multiplication.pde
Normal file
20
lib/BigNumber/examples/Multiplication/Multiplication.pde
Normal file
|
@ -0,0 +1,20 @@
|
|||
// BigNumber test: multiplication
|
||||
#include "BigNumber.h"
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
Serial.println ();
|
||||
BigNumber::begin (); // initialize library
|
||||
|
||||
// test multiplication
|
||||
BigNumber a = "564328376";
|
||||
BigNumber b = "18254546";
|
||||
BigNumber c = a * b;
|
||||
|
||||
Serial.println (c);
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
49
lib/BigNumber/examples/Natural_Log/Natural_Log.pde
Normal file
49
lib/BigNumber/examples/Natural_Log/Natural_Log.pde
Normal file
|
@ -0,0 +1,49 @@
|
|||
// BigNumber test: calculate natural logarithm
|
||||
#include "BigNumber.h"
|
||||
|
||||
BigNumber one (1);
|
||||
BigNumber two (2);
|
||||
BigNumber half ("0.5");
|
||||
|
||||
BigNumber ln (BigNumber x)
|
||||
{
|
||||
|
||||
// if x <= 0.5 or >= 2 take the square root and double the result
|
||||
if (x <= half || x >= two)
|
||||
{
|
||||
BigNumber e = ln (x.sqrt ());
|
||||
return e * two;
|
||||
} // end of x <= 0.5 or >= 2
|
||||
|
||||
// some big numbers
|
||||
BigNumber a = (x - one) / (x + one);
|
||||
BigNumber e;
|
||||
BigNumber t = a;
|
||||
|
||||
BigNumber i = one;
|
||||
BigNumber E;
|
||||
|
||||
do
|
||||
{
|
||||
E = e;
|
||||
e += t / i;
|
||||
t *= a * a;
|
||||
i += two;
|
||||
} while (e != E);
|
||||
|
||||
return e * two;
|
||||
} // end of function ln
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
Serial.println ();
|
||||
BigNumber::begin (45); // max around 45 on the Uno for ln (100)
|
||||
|
||||
Serial.println (ln (100));
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
||||
|
60
lib/BigNumber/examples/Pi/Pi.ino
Normal file
60
lib/BigNumber/examples/Pi/Pi.ino
Normal file
|
@ -0,0 +1,60 @@
|
|||
// BigNumber example: Calculate Pi using the Francois Viete formula
|
||||
|
||||
#include <BigNumber.h>
|
||||
|
||||
BigNumber PiViete ()
|
||||
{
|
||||
// Francois Viete formula
|
||||
BigNumber two (2); // used as a constant value of 2
|
||||
BigNumber s (0); // used in iteration
|
||||
BigNumber t (1); // used in iteration
|
||||
|
||||
for (int i = 0; i < 115; i++) // number of iterations: 10 to 115
|
||||
{
|
||||
BigNumber r = s + two; // temporary value
|
||||
s = r.sqrt ();
|
||||
t *= s / two;
|
||||
}
|
||||
|
||||
return two / t; // calculate pi
|
||||
} // end of function pi
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
|
||||
// Arduino Uno
|
||||
// -----------
|
||||
// The Arduino Uno has only 2k bytes of SRAM.
|
||||
// The maximum length of BigNumber is 74 for an Arduino Uno.
|
||||
// About 115 iterations in the Francois Viete formula is enough for an Arduino Uno.
|
||||
// That will take 34 seconds.
|
||||
//
|
||||
// Arduino Zero or Arduino MKR
|
||||
// ---------------------------
|
||||
// For an Arduino Zero, it is possible to set the length of BigNumber to a higher value.
|
||||
// For example, the length of BigNumber to 1000, and 1500 iterations.
|
||||
// That will take 8 hours.
|
||||
//
|
||||
BigNumber::begin (74); // Length of the BigNumber. 50 is fast, 74 is slow.
|
||||
|
||||
Serial.println (F("Please wait patiently (34 seconds with Arduino Uno)"));
|
||||
Serial.println (F("pi (as text) = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706"));
|
||||
|
||||
unsigned long start = millis();
|
||||
|
||||
BigNumber pi = PiViete ();
|
||||
|
||||
unsigned long finish = millis();
|
||||
|
||||
Serial.print (F("pi (Viete formula) = "));
|
||||
Serial.println (pi);
|
||||
Serial.print (F("It took "));
|
||||
Serial.print ((finish - start) / 1000UL);
|
||||
Serial.print (F(" seconds."));
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
||||
|
43
lib/BigNumber/examples/Power_of_E/Power_of_E.pde
Normal file
43
lib/BigNumber/examples/Power_of_E/Power_of_E.pde
Normal file
|
@ -0,0 +1,43 @@
|
|||
// BigNumber test: calculate power of E
|
||||
#include "BigNumber.h"
|
||||
|
||||
BigNumber ePower (BigNumber x)
|
||||
{
|
||||
|
||||
// if x > 1 halve it and square the result
|
||||
if (x > 1)
|
||||
{
|
||||
BigNumber e = ePower (x / BigNumber (2));
|
||||
return e * e;
|
||||
} // end of x > 1
|
||||
|
||||
// some big numbers
|
||||
BigNumber n = 1, e = 1, t = 1;
|
||||
|
||||
int i = 1;
|
||||
BigNumber E;
|
||||
|
||||
do
|
||||
{
|
||||
E = e;
|
||||
n *= i++; // n is i factorial
|
||||
t *= x; // t is x^i
|
||||
e += t / n;
|
||||
} while (e != E);
|
||||
|
||||
return e;
|
||||
} // end of function ePower
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
Serial.println ();
|
||||
BigNumber::begin (65); // max around 65 on the Uno for a power of 5
|
||||
|
||||
Serial.println (ePower (5)); // e ^ 5
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
||||
|
38
lib/BigNumber/examples/Powers/Powers.pde
Normal file
38
lib/BigNumber/examples/Powers/Powers.pde
Normal file
|
@ -0,0 +1,38 @@
|
|||
// BigNumber test: powers
|
||||
#include "BigNumber.h"
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
BigNumber::begin (); // initialize library
|
||||
|
||||
Serial.println ("--- powers of 2 ---");
|
||||
|
||||
BigNumber a = 2;
|
||||
|
||||
for (int i = 1; i <= 300; i++)
|
||||
{
|
||||
Serial.print ("2^");
|
||||
Serial.print (i);
|
||||
Serial.print (" = ");
|
||||
BigNumber p = a.pow (i);
|
||||
Serial.println (p);
|
||||
} // end of for loop
|
||||
|
||||
Serial.println ("--- powers of 3 ---");
|
||||
|
||||
a = 3;
|
||||
|
||||
for (int i = 1; i <= 300; i++)
|
||||
{
|
||||
Serial.print ("3^");
|
||||
Serial.print (i);
|
||||
Serial.print (" = ");
|
||||
BigNumber p = a.pow (i);
|
||||
Serial.println (p);
|
||||
} // end of for loop
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
43
lib/BigNumber/examples/Sine/Sine.pde
Normal file
43
lib/BigNumber/examples/Sine/Sine.pde
Normal file
|
@ -0,0 +1,43 @@
|
|||
// BigNumber test: calculate sines
|
||||
#include "BigNumber.h"
|
||||
|
||||
// calculate sine of x with 'precision' iterations
|
||||
BigNumber sine (const BigNumber x, BigNumber precision)
|
||||
{
|
||||
BigNumber val = 1;
|
||||
const BigNumber one = 1, two = 2;
|
||||
while (precision > 0)
|
||||
{
|
||||
val = one - val * x * x / (two * precision) / (two * precision + one);
|
||||
precision--;
|
||||
}
|
||||
val = x * val;
|
||||
return val;
|
||||
} // end of function sine
|
||||
|
||||
void setup ()
|
||||
{
|
||||
Serial.begin (115200);
|
||||
Serial.println ();
|
||||
Serial.println ();
|
||||
|
||||
BigNumber::begin (50);
|
||||
|
||||
BigNumber E ("2.7182818284590452353602874713526624977572470936999595749669676277240766303535");
|
||||
BigNumber pi ("3.1415926535897932384626433832795028841971693993751058209749445923078164062862");
|
||||
|
||||
for (int deg = 0; deg <= 90; deg++)
|
||||
{
|
||||
Serial.print ("sin(");
|
||||
Serial.print (deg);
|
||||
Serial.print (") = ");
|
||||
BigNumber rad (deg);
|
||||
rad *= pi / BigNumber (180);
|
||||
Serial.println (sine (rad, 30));
|
||||
} // end of for loop
|
||||
|
||||
} // end of setup
|
||||
|
||||
void loop () { }
|
||||
|
||||
|
339
lib/BigNumber/gpl.txt
Normal file
339
lib/BigNumber/gpl.txt
Normal file
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
11
lib/BigNumber/keywords.txt
Normal file
11
lib/BigNumber/keywords.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
BigNumber KEYWORD1
|
||||
begin KEYWORD2
|
||||
finish KEYWORD2
|
||||
setScale KEYWORD2
|
||||
toString KEYWORD2
|
||||
isNegative KEYWORD2
|
||||
isZero KEYWORD2
|
||||
isNearZero KEYWORD2
|
||||
sqrt KEYWORD2
|
||||
pow KEYWORD2
|
||||
divMod KEYWORD2
|
10
lib/BigNumber/library.properties
Normal file
10
lib/BigNumber/library.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
name=BigNumber
|
||||
version=3.5
|
||||
author=NickGammon
|
||||
maintainer=NickGammon
|
||||
sentence=BigNumber library for the Arduino
|
||||
category=Other
|
||||
url=https://github.com/nickgammon/BigNumber
|
||||
architectures=*
|
||||
paragraph=A library for handling "big" numbers, similar to the "bc" program under Unix. Numbers consisting of large numbers of digits, and large numbers of decimal places can be manipulated, subject to memory limitations.
|
||||
include=BigNumber.h
|
12
lib/BigNumber/src/BigNumber.h
Normal file
12
lib/BigNumber/src/BigNumber.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
//
|
||||
// BigNumber.h
|
||||
//
|
||||
// Author: Nick Gammon
|
||||
// Date: 7th January 2018.
|
||||
// Contributors: Paul Stoffregen, S. Downey
|
||||
// Version: 3.5
|
||||
// Released into the public domain.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BigNumber/BigNumber.h"
|
245
lib/BigNumber/src/BigNumber/BigNumber.cpp
Normal file
245
lib/BigNumber/src/BigNumber/BigNumber.cpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
//
|
||||
// BigNumber.cpp
|
||||
//
|
||||
// Author: Nick Gammon
|
||||
// Date: 22nd January 2013.
|
||||
// Contributors: Paul Stoffregen, S. Downey
|
||||
// Version: 3.5
|
||||
// Released into the public domain.
|
||||
// Added print function as suggested by Paul Stoffregen.
|
||||
// Changed printTo to return the length, as required.
|
||||
|
||||
#include "BigNumber.h"
|
||||
|
||||
int BigNumber::scale_ = 0;
|
||||
|
||||
// constructor
|
||||
BigNumber::BigNumber () : num_ (NULL)
|
||||
{
|
||||
bc_init_num (&num_); // default to zero
|
||||
} // end of constructor from string
|
||||
|
||||
// constructor
|
||||
BigNumber::BigNumber (const char * s) : num_ (NULL)
|
||||
{
|
||||
bc_str2num(&num_, s, scale_);
|
||||
} // end of constructor from string
|
||||
|
||||
BigNumber::BigNumber (const int n) : num_ (NULL) // constructor from int
|
||||
{
|
||||
bc_int2num (&num_, n);
|
||||
} // end of constructor from int
|
||||
|
||||
// copy constructor
|
||||
BigNumber::BigNumber (const BigNumber & rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
num_ = bc_copy_num (rhs.num_);
|
||||
} // end of BigNumber::BigNumber
|
||||
|
||||
//operator=
|
||||
BigNumber & BigNumber::operator= (const BigNumber & rhs)
|
||||
{
|
||||
// gracefully handle self-assignment (eg. a = a;)
|
||||
if (this == &rhs )
|
||||
return *this;
|
||||
|
||||
bc_free_num (&num_); // get rid of old one
|
||||
num_ = bc_copy_num (rhs.num_);
|
||||
return *this;
|
||||
} // end of BigNumber::BigNumber & operator=
|
||||
|
||||
// destructor - free memory used, if any
|
||||
BigNumber::~BigNumber ()
|
||||
{
|
||||
bc_free_num (&num_);
|
||||
} // end of destructor
|
||||
|
||||
// set scale factor (number of places after the decimal point)
|
||||
int BigNumber::setScale (const int scale)
|
||||
{
|
||||
int old_scale = scale_;
|
||||
if (scale >= 0)
|
||||
scale_ = scale;
|
||||
else
|
||||
scale_ = 0;
|
||||
return old_scale;
|
||||
} // end of BigNumber::setScale
|
||||
|
||||
// initialize package
|
||||
// supply scale (number of decimal places): default zero
|
||||
void BigNumber::begin (const int scale)
|
||||
{
|
||||
bc_init_numbers ();
|
||||
scale_ = scale;
|
||||
} // end of BigNumber::begin
|
||||
|
||||
// finished with package
|
||||
// free special numbers: zero, one, two
|
||||
void BigNumber::finish ()
|
||||
{
|
||||
bc_free_numbers ();
|
||||
} // end of BigNumber::finish
|
||||
|
||||
// return a pointer to a string containing the number
|
||||
// MUST FREE THIS after use!
|
||||
// eg: char * s = mynumber.toString ();
|
||||
// Serial.println (s);
|
||||
// free (s);
|
||||
char * BigNumber::toString () const
|
||||
{
|
||||
return bc_num2str(num_);
|
||||
} // end of BigNumber::toString
|
||||
|
||||
BigNumber::operator long () const
|
||||
{
|
||||
return bc_num2long (num_);
|
||||
} // end of BigNumber::operator long
|
||||
|
||||
// Allow Arduino's Serial.print() to print BigNumber objects!
|
||||
size_t BigNumber::printTo(Print& p) const
|
||||
{
|
||||
char *buf = bc_num2str(num_);
|
||||
size_t len = p.write(buf);
|
||||
free(buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
// add
|
||||
BigNumber & BigNumber::operator+= (const BigNumber & n)
|
||||
{
|
||||
bc_num result = NULL;
|
||||
bc_add (num_, n.num_, &result, scale_);
|
||||
bc_free_num (&num_);
|
||||
num_ = result;
|
||||
return *this;
|
||||
} // end of BigNumber::operator+=
|
||||
|
||||
// subtract
|
||||
BigNumber & BigNumber::operator-= (const BigNumber & n)
|
||||
{
|
||||
bc_num result = NULL;
|
||||
bc_sub (num_, n.num_, &result, scale_);
|
||||
bc_free_num (&num_);
|
||||
num_ = result;
|
||||
return *this;
|
||||
} // end of BigNumber::operator-=
|
||||
|
||||
// divide
|
||||
BigNumber & BigNumber::operator/= (const BigNumber & n)
|
||||
{
|
||||
bc_num result = NULL;
|
||||
bc_init_num (&result); // in case zero
|
||||
bc_divide (num_, n.num_, &result, scale_);
|
||||
bc_free_num (&num_);
|
||||
num_ = result;
|
||||
return *this;
|
||||
} // end of BigNumber::operator/=
|
||||
|
||||
// multiply
|
||||
BigNumber & BigNumber::operator*= (const BigNumber & n)
|
||||
{
|
||||
bc_num result = NULL;
|
||||
bc_multiply (num_, n.num_, &result, scale_);
|
||||
bc_free_num (&num_);
|
||||
num_ = result;
|
||||
return *this;
|
||||
} // end of BigNumber::operator*=
|
||||
|
||||
// modulo
|
||||
BigNumber & BigNumber::operator%= (const BigNumber & n)
|
||||
{
|
||||
bc_num result = NULL;
|
||||
bc_init_num (&result); // in case zero
|
||||
bc_modulo (num_, n.num_, &result, scale_);
|
||||
bc_free_num (&num_);
|
||||
num_ = result;
|
||||
return *this;
|
||||
} // end of BigNumber::operator%=
|
||||
|
||||
|
||||
// ----------------------------- COMPARISONS ------------------------------
|
||||
|
||||
// compare less with another BigNumber
|
||||
bool BigNumber::operator< (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) < 0;
|
||||
} // end of BigNumber::operator<
|
||||
|
||||
|
||||
// compare greater with another BigNumber
|
||||
bool BigNumber::operator> (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) > 0;
|
||||
} // end of BigNumber::operator>
|
||||
|
||||
// compare less-or-equal with another BigNumber
|
||||
bool BigNumber::operator<= (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) <= 0;
|
||||
} // end of BigNumber::operator<=
|
||||
|
||||
// compare greater-or-equal with another BigNumber
|
||||
bool BigNumber::operator>= (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) >= 0;
|
||||
} // end of BigNumber::operator>=
|
||||
|
||||
// compare not equal with another BigNumber
|
||||
bool BigNumber::operator!= (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) != 0;
|
||||
} // end of BigNumber::operator!=
|
||||
|
||||
// compare equal with another BigNumber
|
||||
bool BigNumber::operator== (const BigNumber & rhs) const
|
||||
{
|
||||
return bc_compare (num_, rhs.num_) == 0;
|
||||
} // end of BigNumber::operator==
|
||||
|
||||
// special comparisons
|
||||
bool BigNumber::isNegative () const
|
||||
{
|
||||
return bc_is_neg (num_) == true;
|
||||
} // end of BigNumber::isNegative
|
||||
|
||||
bool BigNumber::isZero () const
|
||||
{
|
||||
return bc_is_zero (num_) == true;
|
||||
} // end of BigNumber::isZero
|
||||
|
||||
bool BigNumber::isNearZero () const
|
||||
{
|
||||
return bc_is_near_zero (num_, scale_) == true;
|
||||
} // end of BigNumber::isNearZero
|
||||
|
||||
// ----------------------------- OTHER OPERATIONS ------------------------------
|
||||
|
||||
// square root
|
||||
BigNumber BigNumber::sqrt () const
|
||||
{
|
||||
BigNumber result (*this);
|
||||
bc_sqrt (&result.num_, scale_);
|
||||
return result;
|
||||
} // end of BigNumber::sqrt
|
||||
|
||||
// raise to power
|
||||
BigNumber BigNumber::pow (const BigNumber power) const
|
||||
{
|
||||
BigNumber result;
|
||||
bc_raise (num_, power.num_, &result.num_, scale_);
|
||||
return result;
|
||||
} // end of BigNumber::pow
|
||||
|
||||
void BigNumber::divMod (const BigNumber divisor, BigNumber & quotient, BigNumber & remainder) const
|
||||
{
|
||||
bc_divmod (num_, divisor.num_, "ient.num_, &remainder.num_, scale_);
|
||||
}
|
||||
|
||||
// raise number by power, modulus modulus
|
||||
BigNumber BigNumber::powMod (const BigNumber power, const BigNumber & modulus) const
|
||||
{
|
||||
BigNumber result;
|
||||
bc_raisemod (num_, power.num_, modulus.num_, &result.num_, scale_);
|
||||
return result;
|
||||
}
|
115
lib/BigNumber/src/BigNumber/BigNumber.h
Normal file
115
lib/BigNumber/src/BigNumber/BigNumber.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// BigNumber.h
|
||||
//
|
||||
// Author: Nick Gammon
|
||||
// Date: 22nd January 2013.
|
||||
// Contributors: Paul Stoffregen, S. Downey
|
||||
// Version: 3.5
|
||||
// Released into the public domain.
|
||||
// Added print function as suggested by Paul Stoffregen.
|
||||
|
||||
#ifndef _BigNumber_h
|
||||
#define _BigNumber_h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "number.h"
|
||||
}
|
||||
|
||||
class BigNumber : public Printable
|
||||
{
|
||||
|
||||
// the current scaling amount - shared amongst all BigNumbers
|
||||
static int scale_;
|
||||
|
||||
// member variable (the big number)
|
||||
bc_num num_;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
BigNumber (); // default constructor
|
||||
BigNumber (const char * s); // constructor from string
|
||||
BigNumber (const int n); // constructor from int
|
||||
// copy constructor
|
||||
BigNumber (const BigNumber & rhs);
|
||||
|
||||
// destructor
|
||||
~BigNumber ();
|
||||
|
||||
// static methods: initialize package, and set global scaling factor
|
||||
static void begin (const int scale = 0);
|
||||
static void finish (); // free memory used by 'begin' method
|
||||
static int setScale (const int scale = 0);
|
||||
|
||||
// for outputting purposes ...
|
||||
char * toString () const; // returns number as string, MUST FREE IT after use!
|
||||
operator long () const;
|
||||
virtual size_t printTo(Print& p) const; // for Arduino Serial.print()
|
||||
|
||||
// operators ... assignment
|
||||
BigNumber & operator= (const BigNumber & rhs);
|
||||
|
||||
// operations on the number which change it (eg. a += 5; )
|
||||
BigNumber & operator+= (const BigNumber & n);
|
||||
BigNumber & operator-= (const BigNumber & n);
|
||||
BigNumber & operator/= (const BigNumber & n);
|
||||
BigNumber & operator*= (const BigNumber & n);
|
||||
BigNumber & operator%= (const BigNumber & n); // modulo
|
||||
|
||||
// operations on the number which do not change it (eg. a = b + 5; )
|
||||
BigNumber operator+ (const BigNumber & n) const { BigNumber temp = *this; temp += n; return temp; };
|
||||
BigNumber operator- (const BigNumber & n) const { BigNumber temp = *this; temp -= n; return temp; };
|
||||
BigNumber operator/ (const BigNumber & n) const { BigNumber temp = *this; temp /= n; return temp; };
|
||||
BigNumber operator* (const BigNumber & n) const { BigNumber temp = *this; temp *= n; return temp; };
|
||||
BigNumber operator% (const BigNumber & n) const { BigNumber temp = *this; temp %= n; return temp; };
|
||||
|
||||
// prefix operations
|
||||
BigNumber & operator++ () { *this += 1; return *this; }
|
||||
BigNumber & operator-- () { *this -= 1; return *this; }
|
||||
|
||||
// postfix operations (cannot return by reference)
|
||||
// we make a temporary object, change our current object, return the temporary one
|
||||
// if we returned a reference it would cease to exist, so we have to return a copy
|
||||
BigNumber operator++ (int) { BigNumber temp = *this; *this += 1; return temp; }
|
||||
BigNumber operator-- (int) { BigNumber temp = *this; *this -= 1; return temp; }
|
||||
|
||||
// comparisons
|
||||
bool operator< (const BigNumber & rhs) const;
|
||||
bool operator< (const int rhs) const { return *this < BigNumber (rhs); }
|
||||
bool operator> (const BigNumber & rhs) const;
|
||||
bool operator> (const int rhs) const { return *this > BigNumber (rhs); }
|
||||
bool operator<= (const BigNumber & rhs) const;
|
||||
bool operator<= (const int rhs) const { return *this <= BigNumber (rhs); }
|
||||
bool operator>= (const BigNumber & rhs) const;
|
||||
bool operator>= (const int rhs) const { return *this >= BigNumber (rhs); }
|
||||
bool operator!= (const BigNumber & rhs) const;
|
||||
bool operator!= (const int rhs) const { return *this != BigNumber (rhs); }
|
||||
bool operator== (const BigNumber & rhs) const;
|
||||
bool operator== (const int rhs) const { return *this == BigNumber (rhs); }
|
||||
|
||||
// quick sign test
|
||||
bool isNegative () const;
|
||||
// quick zero test
|
||||
bool isZero () const;
|
||||
|
||||
// In some places we need to check if the number is almost zero.
|
||||
// Specifically, all but the last digit is 0 and the last digit is 1.
|
||||
// Last digit is defined by scale.
|
||||
bool isNearZero () const;
|
||||
|
||||
// other mathematical operations
|
||||
BigNumber sqrt () const;
|
||||
BigNumber pow (const BigNumber power) const;
|
||||
// divide number by divisor, give quotient and remainder
|
||||
void divMod (const BigNumber divisor, BigNumber & quotient, BigNumber & remainder) const;
|
||||
// raise number by power, modulus modulus
|
||||
BigNumber powMod (const BigNumber power, const BigNumber & modulus) const;
|
||||
|
||||
}; // end class declaration
|
||||
|
||||
|
||||
#endif
|
24
lib/BigNumber/src/BigNumber/bcconfig.h
Normal file
24
lib/BigNumber/src/BigNumber/bcconfig.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* config.h
|
||||
* number.c from GNU bc-1.06 exports some symbols without the bc_ prefix.
|
||||
* This header file fixes this without touching either number.c or number.h
|
||||
* (luckily, number.c already wants to include a config.h).
|
||||
* Clients of number.c should include config.h before number.h.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#define NDEBUG 1
|
||||
|
||||
#define _zero_ bc_zero
|
||||
#define _one_ bc_one
|
||||
#define _two_ bc_two
|
||||
#define num2str bc_num2str
|
||||
#define mul_base_digits bc_mul_base_digits
|
||||
|
||||
#define bc_rt_warn bc_error
|
||||
#define bc_rt_error bc_error
|
||||
#define bc_out_of_memory() bc_error(0)
|
||||
|
||||
void bc_error(const int mesg);
|
||||
|
1516
lib/BigNumber/src/BigNumber/number.c
Normal file
1516
lib/BigNumber/src/BigNumber/number.c
Normal file
File diff suppressed because it is too large
Load diff
161
lib/BigNumber/src/BigNumber/number.h
Normal file
161
lib/BigNumber/src/BigNumber/number.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* number.h: Arbitrary precision numbers header file. */
|
||||
/*
|
||||
Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License , or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to:
|
||||
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330
|
||||
Boston, MA 02111-1307 USA.
|
||||
|
||||
|
||||
You may contact the author by:
|
||||
e-mail: philnelson@acm.org
|
||||
us-mail: Philip A. Nelson
|
||||
Computer Science Department, 9062
|
||||
Western Washington University
|
||||
Bellingham, WA 98226-9062
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef _NUMBER_H_
|
||||
#define _NUMBER_H_
|
||||
|
||||
// errors, warnings
|
||||
|
||||
#define BC_ERROR_OUT_OF_MEMORY 0
|
||||
#define BC_ERROR_EXPONENT_TOO_LARGE_IN_RAISE 1
|
||||
#define BC_WARNING_NON_ZERO_SCALE_IN_EXPONENT -1
|
||||
#define BC_WARNING_NON_ZERO_SCALE_IN_BASE -2
|
||||
#define BC_WARNING_NON_ZERO_SCALE_IN_MODULUS -3
|
||||
|
||||
|
||||
typedef enum {PLUS, MINUS} sign;
|
||||
|
||||
typedef struct bc_struct *bc_num;
|
||||
|
||||
typedef struct bc_struct
|
||||
{
|
||||
sign n_sign;
|
||||
int n_len; /* The number of digits before the decimal point. */
|
||||
int n_scale; /* The number of digits after the decimal point. */
|
||||
int n_refs; /* The number of pointers to this number. */
|
||||
bc_num n_next; /* Linked list for available list. */
|
||||
char *n_ptr; /* The pointer to the actual storage.
|
||||
If NULL, n_value points to the inside of
|
||||
another number (bc_multiply...) and should
|
||||
not be "freed." */
|
||||
char *n_value; /* The number. Not zero char terminated.
|
||||
May not point to the same place as n_ptr as
|
||||
in the case of leading zeros generated. */
|
||||
} bc_struct;
|
||||
|
||||
|
||||
/* The base used in storing the numbers in n_value above.
|
||||
Currently this MUST be 10. */
|
||||
|
||||
#define BASE 10
|
||||
|
||||
/* Some useful macros and constants. */
|
||||
|
||||
#define CH_VAL(c) (c - '0')
|
||||
#define BCD_CHAR(d) (d + '0')
|
||||
|
||||
#ifdef MIN
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#endif
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a,b) ((a)>(b)?(b):(a))
|
||||
#define ODD(a) ((a)&1)
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef LONG_MAX
|
||||
#define LONG_MAX 0x7ffffff
|
||||
#endif
|
||||
|
||||
|
||||
/* Global numbers. */
|
||||
extern bc_num _zero_;
|
||||
extern bc_num _one_;
|
||||
extern bc_num _two_;
|
||||
|
||||
|
||||
/* Function Prototypes */
|
||||
|
||||
/* Define the _PROTOTYPE macro if it is needed. */
|
||||
|
||||
#ifndef _PROTOTYPE
|
||||
#define _PROTOTYPE(func, args) func args
|
||||
#endif
|
||||
|
||||
_PROTOTYPE(void bc_init_numbers, (void));
|
||||
|
||||
_PROTOTYPE(void bc_free_numbers, (void));
|
||||
|
||||
_PROTOTYPE(bc_num bc_new_num, (int length, int scale));
|
||||
|
||||
_PROTOTYPE(void bc_free_num, (bc_num *num));
|
||||
|
||||
_PROTOTYPE(bc_num bc_copy_num, (bc_num num));
|
||||
|
||||
_PROTOTYPE(void bc_init_num, (bc_num *num));
|
||||
|
||||
_PROTOTYPE(void bc_str2num, (bc_num *num, const char *str, int scale));
|
||||
|
||||
_PROTOTYPE(char *bc_num2str, (bc_num num));
|
||||
|
||||
_PROTOTYPE(void bc_int2num, (bc_num *num, int val));
|
||||
|
||||
_PROTOTYPE(long bc_num2long, (bc_num num));
|
||||
|
||||
_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
|
||||
|
||||
_PROTOTYPE(char bc_is_zero, (bc_num num));
|
||||
|
||||
_PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale));
|
||||
|
||||
_PROTOTYPE(char bc_is_neg, (bc_num num));
|
||||
|
||||
_PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
|
||||
|
||||
_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
|
||||
|
||||
_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale));
|
||||
|
||||
_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale));
|
||||
|
||||
_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result,
|
||||
int scale));
|
||||
|
||||
_PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot,
|
||||
bc_num *rem, int scale));
|
||||
|
||||
_PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod,
|
||||
bc_num *result, int scale));
|
||||
|
||||
_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result,
|
||||
int scale));
|
||||
|
||||
_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
|
||||
|
||||
_PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
|
||||
int leading_zero));
|
||||
|
||||
#endif
|
||||
|
46
lib/README
Normal file
46
lib/README
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
21
platformio.ini
Normal file
21
platformio.ini
Normal file
|
@ -0,0 +1,21 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
lib_extra_dirs = ~/Documents/Arduino/libraries
|
||||
lib_deps =
|
||||
teemuatlut/TMC2130Stepper@^2.5.1
|
||||
waspinator/AccelStepper@^1.61
|
||||
|
||||
; Custom Serial Monitor speed (baud rate)
|
||||
monitor_speed = 115200
|
6
src/.theia/launch.json
Normal file
6
src/.theia/launch.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
"version": "0.2.0",
|
||||
"configurations": []
|
||||
}
|
602
src/ATM.ino
Normal file
602
src/ATM.ino
Normal file
|
@ -0,0 +1,602 @@
|
|||
#include <TMC2130Stepper.h>
|
||||
#include <AccelStepper.h>
|
||||
#include <MultiStepper.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "ADF4351.h"
|
||||
#include "Pins.h" // Pins are defined here
|
||||
#include "Positions.h" // Calibrated frequency positions are defined her
|
||||
#include "Stepper.h" // Stepper specific values are defined here
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
|
||||
// Frequency Settings
|
||||
#define FREQUENCY_STEP 100000U // 100kHz frequency steps for initial frequency sweep
|
||||
#define START_FREQUENCY 35000000U // 80MHz
|
||||
#define STOP_FREQUENCY 200000000 // 120MHz
|
||||
|
||||
ADF4351 adf4351(SCLK_PIN, MOSI_PIN, LE_PIN, CE_PIN); // declares object PLL of type ADF4351
|
||||
|
||||
TMC2130Stepper tuning_driver = TMC2130Stepper(EN_PIN_M1, DIR_PIN_M1, STEP_PIN_M1, CS_PIN_M1, MOSI_PIN, MISO_PIN, SCLK_PIN);
|
||||
TMC2130Stepper matching_driver = TMC2130Stepper(EN_PIN_M2, DIR_PIN_M2, STEP_PIN_M2, CS_PIN_M2, MOSI_PIN, MISO_PIN, SCLK_PIN);
|
||||
|
||||
AccelStepper tuning_stepper = AccelStepper(tuning_stepper.DRIVER, STEP_PIN_M1, DIR_PIN_M1);
|
||||
AccelStepper matching_stepper = AccelStepper(matching_stepper.DRIVER, STEP_PIN_M2, DIR_PIN_M2);
|
||||
|
||||
Stepper tuner = {tuning_stepper, tuning_driver, DIAG1_PIN_M1, TUNING_STEPPER_HOME};
|
||||
|
||||
Stepper matcher = {matching_stepper, matching_driver, DIAG1_PIN_M2, MATCHING_STEPPER_HOME};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
pinMode(MISO_PIN, INPUT_PULLUP); // Seems to be necessary for SPI to work
|
||||
|
||||
tuner.DRIVER.begin(); // Initiate pins and registeries
|
||||
tuner.DRIVER.rms_current(400); // Set stepper current to 800mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
|
||||
tuner.DRIVER.microsteps(16);
|
||||
tuner.DRIVER.coolstep_min_speed(0xFFFFF); // 20bit max - needs to be set for stallguard
|
||||
tuner.DRIVER.diag1_stall(1);
|
||||
tuner.DRIVER.diag1_active_high(1);
|
||||
tuner.DRIVER.sg_stall_value(STALL_VALUE - 1);
|
||||
tuner.DRIVER.shaft_dir(0);
|
||||
tuner.DRIVER.stealthChop(1); // Enable extremely quiet stepping
|
||||
|
||||
pinMode(DIAG1_PIN_M1, INPUT);
|
||||
|
||||
Serial.print("DRV_STATUS=0b");
|
||||
Serial.println(tuning_driver.DRV_STATUS(), BIN);
|
||||
|
||||
matcher.DRIVER.begin(); // Initiate pins and registeries
|
||||
matcher.DRIVER.rms_current(200); // Set stepper current to 200mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
|
||||
matcher.DRIVER.microsteps(16);
|
||||
matcher.DRIVER.coolstep_min_speed(0xFFFFF); // 20bit max - needs to be set for stallguard
|
||||
matcher.DRIVER.diag1_stall(1);
|
||||
matcher.DRIVER.diag1_active_high(1);
|
||||
matcher.DRIVER.sg_stall_value(STALL_VALUE - 2);
|
||||
matcher.DRIVER.shaft_dir(0);
|
||||
matcher.DRIVER.stealthChop(1); // Enable extremely quiet stepping
|
||||
|
||||
digitalWrite(EN_PIN_M1, LOW);
|
||||
|
||||
digitalWrite(EN_PIN_M2, LOW);
|
||||
|
||||
tuner.STEPPER.setMaxSpeed(12000);
|
||||
tuner.STEPPER.setAcceleration(12000);
|
||||
tuner.STEPPER.setEnablePin(EN_PIN_M1);
|
||||
tuner.STEPPER.setPinsInverted(false, false, true);
|
||||
tuner.STEPPER.enableOutputs();
|
||||
|
||||
matcher.STEPPER.setMaxSpeed(12000);
|
||||
matcher.STEPPER.setAcceleration(12000);
|
||||
matcher.STEPPER.setEnablePin(EN_PIN_M2);
|
||||
matcher.STEPPER.setPinsInverted(false, false, true);
|
||||
matcher.STEPPER.enableOutputs();
|
||||
|
||||
tuner.STEPPER.setCurrentPosition(0);
|
||||
|
||||
matcher.STEPPER.setCurrentPosition(0);
|
||||
|
||||
adf4351.begin();
|
||||
|
||||
adf4351.setrf(25000000U);
|
||||
adf4351.pwrlevel = 3; // This equals -4dBm*/
|
||||
adf4351.setf(START_FREQUENCY);
|
||||
|
||||
}
|
||||
|
||||
// Implement Serial communication ...
|
||||
// This could probably cleaned up by using structs for the inputs, pointing to the different functions- > would reduce copy-paste code and make adding functions more intuitive
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
|
||||
String input_line = Serial.readStringUntil('\n'); // read string until newline character
|
||||
|
||||
char command = input_line.charAt(0); // gets first character of input
|
||||
|
||||
// approximate call
|
||||
// CAREFULL -> if the coil has no proper matching in the frequency range this will not work! Only use this for testing -> otherwise use the automated 'decide' call.
|
||||
if (command == 'a') {
|
||||
float target_frequency_MHz = input_line.substring(1).toFloat();
|
||||
uint32_t target_frequency = validateInput(target_frequency_MHz);
|
||||
if (target_frequency == 0) return;
|
||||
|
||||
Serial.println("Approximating matching to target frequency in MHz:");
|
||||
Serial.println(target_frequency_MHz);
|
||||
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
resonance_frequency = approximateResonance(target_frequency, resonance_frequency);
|
||||
Serial.println("Resonance after approximation is at:");
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
|
||||
// bruteforce call
|
||||
// CAREFULL -> if the current resonance frequency is not within +-5MHz of the target frequency this will not work. Only use this for testing -> otherwise use the automated 'decide' call.
|
||||
} else if (command == 'b') {
|
||||
float target_frequency_MHz = input_line.substring(1).toFloat();
|
||||
uint32_t target_frequency = validateInput(target_frequency_MHz);
|
||||
if (target_frequency == 0) return;
|
||||
|
||||
Serial.println("Bruteforce matching to target frequency in MHz:");
|
||||
Serial.println(target_frequency_MHz);
|
||||
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
|
||||
resonance_frequency = bruteforceResonance(target_frequency, resonance_frequency);
|
||||
Serial.println("Resonance after bruteforce is at:");
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
|
||||
|
||||
// decide call
|
||||
// this function decides what kind of t&m mode should be used based on the relationship between target frequency and current resonance
|
||||
// it also makes sure that there a homing routine performed in case there is currently no proper resonance in the frequency range
|
||||
} else if (command == 'd'){
|
||||
float target_frequency_MHz = input_line.substring(1).toFloat();
|
||||
uint32_t target_frequency = validateInput(target_frequency_MHz);
|
||||
if (target_frequency == 0) return;
|
||||
|
||||
Serial.println("Tuning and Matching to target frequency in MHz (automatic mode):");
|
||||
Serial.println(target_frequency_MHz);
|
||||
|
||||
uint32_t resonance_frequency = automaticTM(target_frequency);
|
||||
|
||||
Serial.println("Resonance after tuning and matching is at:");
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
// home call
|
||||
// Perform the homing routine by looking for the limit of the capacitors
|
||||
// it also places the steppers in a way so there is a resonance dip inside the frequency range
|
||||
// CAREFULL -> The values are hardcoded, these need to be changed if there is a different coil in use
|
||||
} else if (command == 'h'){
|
||||
Serial.println("Homing...");
|
||||
homeStepper(tuner);
|
||||
homeStepper(matcher);
|
||||
Serial.println("Resonance frequency after homing:");
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
// frequency sweep call
|
||||
// scans the frequency range for the current resonance frequency
|
||||
} else if (command == 'f'){
|
||||
Serial.println("Frequency sweep...");
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
Serial.println("Resonance is at:");
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
// calculates Reflection loss for a given frequency
|
||||
} else if (command == 'r'){
|
||||
float frequency_MHz = input_line.substring(1).toFloat();
|
||||
uint32_t frequency = validateInput(frequency_MHz);
|
||||
if (frequency == 0) return;
|
||||
|
||||
float reflection_loss = getReflectionRMS(frequency);
|
||||
Serial.println("For frequency:");
|
||||
Serial.println(frequency);
|
||||
Serial.println("RMS of the reflection is:");
|
||||
Serial.println(reflection_loss);
|
||||
|
||||
//optimize Matching
|
||||
} else if (command == 'm'){
|
||||
Serial.println("Optimize Matching around frequency:");
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
|
||||
Serial.println(resonance_frequency);
|
||||
|
||||
optimizeMatching(resonance_frequency);
|
||||
|
||||
//calculate sum
|
||||
} else if (command == 's'){
|
||||
|
||||
float frequency_MHz = input_line.substring(1).toFloat();
|
||||
uint32_t frequency = validateInput(frequency_MHz);
|
||||
if (frequency == 0) return;
|
||||
|
||||
int sum = sumReflectionAroundFrequency(frequency);
|
||||
Serial.println("For frequency:");
|
||||
Serial.println(frequency);
|
||||
Serial.println("Sum of the reflection is:");
|
||||
Serial.println(sum);
|
||||
|
||||
// Calibration Call
|
||||
} else if (command == 'c'){
|
||||
Serial.println("Calibrating ...");
|
||||
getCalibrationValues();
|
||||
} else {
|
||||
Serial.println("Invalid Input");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This helper function checks if the input frequency is plausible, if so it returns the value in Hz
|
||||
// otherwise it returns 0
|
||||
uint32_t validateInput(float frequency_MHz){
|
||||
uint32_t frequency_Hz = frequency_MHz * 1000000U;
|
||||
|
||||
if (frequency_Hz < START_FREQUENCY){
|
||||
Serial.println("Invalid input: frequency too low");
|
||||
return 0;
|
||||
} else if (frequency_Hz > STOP_FREQUENCY) {
|
||||
Serial.println("Invalid input: frequency too high");
|
||||
return 0;
|
||||
}else{
|
||||
return frequency_Hz;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int readReflection(int averages){
|
||||
int reflection = 0;
|
||||
for (int i = 0; i < averages; i ++) reflection += analogReadMilliVolts(REFLECTION_PIN);
|
||||
return reflection/averages;
|
||||
|
||||
}
|
||||
|
||||
void getCalibrationValues(){
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
|
||||
tuner.STEPPER.setCurrentPosition(0);
|
||||
matcher.STEPPER.setCurrentPosition(0);
|
||||
|
||||
int tuner_position = stallStepper(tuner);
|
||||
|
||||
int matcher_position = stallStepper(matcher);
|
||||
|
||||
Serial.println("For Resonance frequency:");
|
||||
Serial.println(resonance_frequency);
|
||||
Serial.println("Tuner Calibration is:");
|
||||
Serial.println(tuner_position);
|
||||
Serial.println("Matcher Position is:");
|
||||
Serial.println(matcher_position);
|
||||
}
|
||||
|
||||
//should put the stepper stuff into a struct
|
||||
void homeStepper(Stepper stepper){
|
||||
stallStepper(stepper);
|
||||
stepper.STEPPER.setCurrentPosition(0);
|
||||
stepper.STEPPER.moveTo(1000);
|
||||
stepper.STEPPER.runToPosition();
|
||||
|
||||
stepper.STEPPER.setMaxSpeed(3000);
|
||||
stepper.STEPPER.setAcceleration(3000);
|
||||
|
||||
stepper.DRIVER.sg_stall_value(-64); // Stall value needs to be lowered because of slower stepper
|
||||
stallStepper(stepper);
|
||||
stepper.DRIVER.sg_stall_value(STALL_VALUE);
|
||||
|
||||
stepper.STEPPER.setMaxSpeed(12000);
|
||||
stepper.STEPPER.setAcceleration(12000);
|
||||
|
||||
stepper.STEPPER.setCurrentPosition(0);
|
||||
stepper.STEPPER.moveTo(stepper.HOME_POSITION);
|
||||
stepper.STEPPER.runToPosition();
|
||||
|
||||
}
|
||||
|
||||
int stallStepper(Stepper stepper){
|
||||
stepper.STEPPER.moveTo(-9999999);
|
||||
|
||||
while (!digitalRead(stepper.STALL_PIN)){
|
||||
stepper.STEPPER.run();
|
||||
}
|
||||
|
||||
DEBUG_PRINT(stepper.STEPPER.currentPosition());
|
||||
|
||||
stepper.STEPPER.stop();
|
||||
|
||||
return stepper.STEPPER.currentPosition(); // returns value until limit is reached
|
||||
|
||||
}
|
||||
|
||||
uint32_t automaticTM(uint32_t target_frequency){
|
||||
uint32_t resonance_frequency = findCurrentResonanceFrequency(START_FREQUENCY, STOP_FREQUENCY, FREQUENCY_STEP);
|
||||
|
||||
int32_t delta_frequency = target_frequency - resonance_frequency; // needs to be int -> negative frequencies possible
|
||||
if (abs(delta_frequency) > 5000000U) resonance_frequency = approximateResonance(target_frequency, resonance_frequency);
|
||||
|
||||
resonance_frequency = bruteforceResonance(target_frequency, resonance_frequency);
|
||||
|
||||
optimizeMatching(resonance_frequency);
|
||||
|
||||
resonance_frequency = findCurrentResonanceFrequency(resonance_frequency - 1000000U, resonance_frequency + 1000000U, FREQUENCY_STEP / 2);
|
||||
|
||||
resonance_frequency = bruteforceResonance(target_frequency, resonance_frequency);
|
||||
|
||||
return resonance_frequency;
|
||||
}
|
||||
|
||||
// calculates the Reflection Loss at a specified frequency
|
||||
//24mV/dB slope
|
||||
//0dBV defined as 1V Sin RMS
|
||||
// Would expect 1.74V as output for unmatched coil -> but it's 1.65V => ~10mV at Logamp
|
||||
|
||||
// Measurments: with 40dB LNA @85MHz
|
||||
// Open: 1.6V RMS output
|
||||
// Coil matched to -30dB: 1.0V RmS Output
|
||||
float calculateRL(uint32_t frequency){
|
||||
float RMS_ADF = 13; // at -4dBm the ADF4351 generates sin with an RMS value of 131.5mV but due to to -10dB attenuation of the transcoupler and some additional reflections about 13mV are effectivly at the Logamp
|
||||
float reflection_rms = getReflectionRMS(frequency);
|
||||
|
||||
float reflection_loss = 20 * log10((reflection_rms)/ RMS_ADF);
|
||||
|
||||
return reflection_loss;
|
||||
|
||||
}
|
||||
|
||||
float getReflectionRMS(uint32_t frequency){
|
||||
float LOGAMP_SLOPE = 24; // Slope in mV/dB
|
||||
|
||||
adf4351.setf(frequency);
|
||||
delay(10);
|
||||
|
||||
int reflection_mv = readReflection(64); // Output of the logamp
|
||||
|
||||
int intercept_positioning = -108; // in dB
|
||||
|
||||
float reflection_dBV = (reflection_mv/LOGAMP_SLOPE) + intercept_positioning;
|
||||
|
||||
float reflection_rms = pow(10, reflection_dBV / 20) * 1000; // this step could be shortened but I still like to calculate it explicitly since there are multiple logarithmic operations going on here - > this value is in mV
|
||||
return reflection_rms;
|
||||
}
|
||||
|
||||
// Finds current Resonance Frequency of the coil. There should be a substential dip already present atm.
|
||||
// Add plausibility check to make sure there is one peak at at least -12dB
|
||||
// Following is for setup WITHOUT 20dB LNA:
|
||||
// -30dB aprox. 1.15V Oscilloscope -> normally 1.6V -> 1300 Points
|
||||
// -16dB aprox. 1.27V Oscilloscope - normally 1.6V
|
||||
// -18dB aprox 1.295V Oscilloscope -> use 1489 Points as decision line for sufficient Matching
|
||||
|
||||
// Values for setup WITH 20dB LNA: -> i don't know what happened here.
|
||||
// open 1.2V
|
||||
//-16dB 827mV Oscilloscope
|
||||
//-30dB 770mV Oscilloscope
|
||||
|
||||
|
||||
int32_t findCurrentResonanceFrequency(uint32_t start_frequency, uint32_t stop_frequency, uint32_t frequency_step){
|
||||
int minimum_reflection = 4096;
|
||||
int current_reflection = 0;
|
||||
uint32_t minimum_frequency = 0;
|
||||
float reflection_rms = 0;
|
||||
|
||||
adf4351.setf(start_frequency); // A frequency value needs to be set once -> there seems to be a bug with the first SPI call
|
||||
|
||||
for(uint32_t frequency = start_frequency; frequency <= stop_frequency; frequency += frequency_step){
|
||||
adf4351.setf(frequency);
|
||||
delay(5); // This delay is essential! There is a glitch with ADC2 that leads to wrong readings if GPIO27 is set to high for multiple microseconds.
|
||||
|
||||
current_reflection = readReflection(4);
|
||||
|
||||
if (current_reflection < minimum_reflection){
|
||||
minimum_frequency = frequency;
|
||||
minimum_reflection = current_reflection;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reflection_rms = getReflectionRMS(minimum_frequency);
|
||||
if (reflection_rms > 10){
|
||||
Serial.println("Resonance could not be found.");
|
||||
Serial.println(reflection_rms);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return minimum_frequency;
|
||||
}
|
||||
|
||||
|
||||
// Approximates the target frequency to about 3 MHZ with the tuning capacitor .... works so far
|
||||
int32_t approximateResonance(uint32_t target_frequency, uint32_t current_resonance_frequency){
|
||||
|
||||
int32_t delta_frequency = target_frequency - current_resonance_frequency;
|
||||
int rotation = 0; // rotation == 1 -> clockwise, rotation == -1 -> counterclockwise
|
||||
|
||||
if (delta_frequency < 0) rotation = -1; // negative delta means currentresonance is to high, hence anticlockwise movement is necessary
|
||||
else rotation = 1;
|
||||
|
||||
int start_position = tuner.STEPPER.currentPosition();
|
||||
|
||||
tuner.STEPPER.move(STEPS_PER_ROTATION * rotation); // This needs to be changed
|
||||
tuner.STEPPER.runToPosition();
|
||||
|
||||
// @ Optimization possibility: -> just scan plausible area, would reduce half the scan time
|
||||
int32_t one_revolution_resonance = findCurrentResonanceFrequency(current_resonance_frequency - 30000000U, current_resonance_frequency + 30000000U, FREQUENCY_STEP);
|
||||
|
||||
DEBUG_PRINT(one_revolution_resonance);
|
||||
|
||||
int32_t delta_one_revolution_frequency = one_revolution_resonance - current_resonance_frequency;
|
||||
|
||||
//Plausibility Check - prevents the stepper from turning forever.
|
||||
if ((one_revolution_resonance == -1) || (abs(delta_one_revolution_frequency) > 30000000U)){
|
||||
Serial.println("Tuning and matching not possible - homing needed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32_t steps_to_delta_frequency = ((float) delta_frequency / (float) delta_one_revolution_frequency) * STEPS_PER_ROTATION * rotation;
|
||||
|
||||
DEBUG_PRINT(delta_one_revolution_frequency);
|
||||
DEBUG_PRINT(delta_frequency);
|
||||
|
||||
DEBUG_PRINT(tuner.STEPPER.currentPosition());
|
||||
DEBUG_PRINT(steps_to_delta_frequency);
|
||||
|
||||
tuner.STEPPER.moveTo(start_position + steps_to_delta_frequency);
|
||||
tuner.STEPPER.runToPosition();
|
||||
|
||||
DEBUG_PRINT(tuner.STEPPER.currentPosition());
|
||||
|
||||
current_resonance_frequency = findCurrentResonanceFrequency(target_frequency - 5000000U, target_frequency + 5000000U, FREQUENCY_STEP);
|
||||
return(current_resonance_frequency);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Tries out different capacitor position until iteration depth is reached OR current_resonancy frequency matches the target_frequency
|
||||
int32_t bruteforceResonance(uint32_t target_frequency, uint32_t current_resonance_frequency){
|
||||
// Change Tuning Stepper -> Clockwise => Freq goes up
|
||||
// Dir = 0 => Anticlockwise movement
|
||||
int rotation = 0; // rotation == 1 -> clockwise, rotation == -1 -> counterclockwise
|
||||
|
||||
int ITERATIONS = 25; // Iteration depth
|
||||
int iteration_steps = 0;
|
||||
|
||||
int32_t delta_frequency = target_frequency - current_resonance_frequency;
|
||||
|
||||
if (delta_frequency < 0) rotation = -1; // negative delta means currentresonance is too high, hence anticlockwise movement is necessary
|
||||
else rotation = 1;
|
||||
|
||||
iteration_steps = rotation * (STEPS_PER_ROTATION / 50);
|
||||
|
||||
//'bruteforce' the stepper position to match the target frequency
|
||||
|
||||
for (int i = 0; i < ITERATIONS; i ++){
|
||||
tuner.STEPPER.move(iteration_steps);
|
||||
tuner.STEPPER.runToPosition();
|
||||
|
||||
// @ Optimization possibility: Reduce frequency range when close to target_frequency
|
||||
current_resonance_frequency = findCurrentResonanceFrequency(target_frequency - 5000000U, target_frequency + 5000000U, FREQUENCY_STEP / 2);
|
||||
|
||||
//Serial.println(current_resonance_frequency);
|
||||
//Serial.println(rotation);
|
||||
//Serial.println(iteration_steps);
|
||||
|
||||
// Stops the iteration if the minima matches the target frequency
|
||||
if (current_resonance_frequency == target_frequency) break;
|
||||
|
||||
// This means the bruteforce resolution was too high and the resonance frequency overshoot
|
||||
// therfore the turn direction gets inverted and the increment halfed
|
||||
if ((current_resonance_frequency > target_frequency) && (rotation == 1)) {
|
||||
rotation = -1;
|
||||
iteration_steps /= 2;
|
||||
iteration_steps *= rotation;
|
||||
}
|
||||
else if ((current_resonance_frequency < target_frequency) && (rotation == -1)){
|
||||
rotation = 1;
|
||||
iteration_steps /= 2;
|
||||
iteration_steps *= -rotation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return current_resonance_frequency;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Matcher clockwise lowers resonance frequency
|
||||
|
||||
int optimizeMatching(uint32_t current_resonance_frequency){
|
||||
int ITERATIONS = 20; // //100 equals one full rotation
|
||||
int iteration_steps = 0;
|
||||
|
||||
int minimum_reflection = 10e5;
|
||||
int current_reflection = 0;
|
||||
int minimum_matching_position = 0;
|
||||
int last_reflection = 10e5;
|
||||
int rotation = 1;
|
||||
|
||||
// Look which rotation direction improves matching.
|
||||
rotation = getMatchRotation(current_resonance_frequency);
|
||||
|
||||
DEBUG_PRINT(rotation);
|
||||
|
||||
|
||||
// This tries to find the minimum reflection while ignoring the change in resonance -> it always looks for minima within
|
||||
iteration_steps = rotation * (STEPS_PER_ROTATION / 10);
|
||||
|
||||
DEBUG_PRINT(iteration_steps);
|
||||
|
||||
adf4351.setf(current_resonance_frequency);
|
||||
for (int i = 0; i < ITERATIONS; i ++){
|
||||
//while(minimum_reflection > 270000){
|
||||
DEBUG_PRINT("Iteration");
|
||||
current_reflection = 0;
|
||||
|
||||
matcher.STEPPER.move(iteration_steps);
|
||||
matcher.STEPPER.runToPosition();
|
||||
|
||||
delay(250);
|
||||
|
||||
current_resonance_frequency = findCurrentResonanceFrequency(current_resonance_frequency - 1000000U, current_resonance_frequency + 1000000U, FREQUENCY_STEP);
|
||||
|
||||
current_reflection = sumReflectionAroundFrequency(current_resonance_frequency);
|
||||
|
||||
if (current_reflection < minimum_reflection){
|
||||
minimum_matching_position = matcher.STEPPER.currentPosition();
|
||||
minimum_reflection = current_reflection;
|
||||
DEBUG_PRINT("Minimum");
|
||||
DEBUG_PRINT(minimum_matching_position);
|
||||
}
|
||||
|
||||
|
||||
/*if (current_reflection > last_reflection) {
|
||||
rotation *= -1;
|
||||
//iteration_steps /= 2;
|
||||
iteration_steps *= rotation;
|
||||
}*/
|
||||
|
||||
DEBUG_PRINT(matcher.STEPPER.currentPosition());
|
||||
DEBUG_PRINT(current_resonance_frequency);
|
||||
DEBUG_PRINT(last_reflection);
|
||||
|
||||
last_reflection = current_reflection;
|
||||
|
||||
if(iteration_steps == 0) break;
|
||||
|
||||
|
||||
DEBUG_PRINT(current_reflection);
|
||||
|
||||
}
|
||||
|
||||
matcher.STEPPER.moveTo(minimum_matching_position);
|
||||
matcher.STEPPER.runToPosition();
|
||||
|
||||
DEBUG_PRINT(matcher.STEPPER.currentPosition());
|
||||
|
||||
return (minimum_reflection);
|
||||
}
|
||||
|
||||
// probably do this for multiple positions in each direction
|
||||
int getMatchRotation(uint32_t current_resonance_frequency){
|
||||
|
||||
|
||||
matcher.STEPPER.move(STEPS_PER_ROTATION / 2);
|
||||
matcher.STEPPER.runToPosition();
|
||||
|
||||
current_resonance_frequency = findCurrentResonanceFrequency(current_resonance_frequency - 1000000U, current_resonance_frequency + 1000000U, FREQUENCY_STEP / 10);
|
||||
int clockwise_match = sumReflectionAroundFrequency(current_resonance_frequency);
|
||||
|
||||
matcher.STEPPER.move(-2* (STEPS_PER_ROTATION / 2));
|
||||
matcher.STEPPER.runToPosition();
|
||||
|
||||
current_resonance_frequency = findCurrentResonanceFrequency(current_resonance_frequency - 1000000U, current_resonance_frequency + 1000000U, FREQUENCY_STEP / 10);
|
||||
int anticlockwise_match = sumReflectionAroundFrequency(current_resonance_frequency);
|
||||
|
||||
matcher.STEPPER.move(STEPS_PER_ROTATION / 2);
|
||||
matcher.STEPPER.runToPosition();
|
||||
|
||||
DEBUG_PRINT(clockwise_match);
|
||||
DEBUG_PRINT(anticlockwise_match);
|
||||
|
||||
if (clockwise_match < anticlockwise_match) return 1;
|
||||
else return -1;
|
||||
|
||||
}
|
||||
|
||||
int sumReflectionAroundFrequency(uint32_t center_frequency){
|
||||
int sum_reflection = 0;
|
||||
|
||||
// sum approach -> cummulates reflection around resonance -> reduce influence of wrong minimum and noise
|
||||
for (uint32_t frequency = center_frequency - 500000U; frequency < center_frequency + 500000U; frequency+= FREQUENCY_STEP / 10) {
|
||||
adf4351.setf(frequency);
|
||||
delay(10);
|
||||
sum_reflection += readReflection(16);
|
||||
}
|
||||
|
||||
return sum_reflection;
|
||||
}
|
11
test/README
Normal file
11
test/README
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
Loading…
Reference in a new issue