/* ///////////////////////////////////////////////////////////////////// Sparkfun Pro Micro Sketch for LNC-Si564-1C https://www.changpuak.ch/electronics/LNC-1.php Software Version 1.0, 09.09.2019 by Alexander Sse Frank Updated for remote operation via USB, 2019-09-12, Christian Monstein HELFUL : https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/all //////////////////////////////////////////////////////////////////////*/ #include #include "LowPower.h" // SI564 VARIABLES / CONSTANTS unsigned long long F_VCO_MIN = 10800000000 ; unsigned long long F_VCO_MAX = 13122222022 ; unsigned long long F_OUT_MIN = 19999999 ; unsigned long long F_OUT_MAX = 2500000001 ; unsigned long long F_OUT = 500000000 ; const byte Si564_Address = 0x55 ; const int PullUpC = 4 ; const int PullUpD = 8 ; // Buffers and constants for remote programming via serial port String buffer; // keeps the command until executed char tempbuf[20]; // keeps the command temporary until CRLF char Version[]="Converter based on LNC-Si564-1C, 2019-09-16/af/cm"; // Version char Help[]="Commands via RS-232/USB port with 9600N81:"; // Help info //----------------------------------------------------------------------------------------- void setup() { pinMode( PullUpC, OUTPUT ) ; pinMode( PullUpD, OUTPUT ) ; digitalWrite( PullUpC, HIGH ); digitalWrite( PullUpD, HIGH ); delay(1999) ; Wire.begin() ; Serial.begin(9600) ; UpdateFreq(F_OUT) ; delay(999) ; UpdateFreq(F_OUT) ; } //----------------------------------------------------------------------------------------- void remote(void) { while (Serial.available() > 0) { int tmp; char st[20]; char rx = Serial.read(); // read a single charecter buffer += rx; //add character to the string buffer //Serial.print(rx); // echo if ((rx == '\n') || (rx == '\r')) { buffer.toCharArray(tempbuf, 40); if (buffer.startsWith("F")) { sscanf(tempbuf,"F%s",&st); // extract frequency as floating point number F_OUT = strtod(st,NULL); //Serial.print("Frequency: "); //Serial.println(F_OUT); UpdateFreq(F_OUT); } else if (buffer.startsWith("-v")) // Check version of SparkFunPro software { Serial.println(Version); } else if (buffer.startsWith("-x")) // Send uP into cerebral coma { LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF); // allerdings brennen noch die LEDs } else if (buffer.startsWith("-h")) // Check version of Arduino software { Serial.println(Help); Serial.println("-h send help info (this list)"); Serial.println("-v send software version"); Serial.println("-x execute power down"); Serial.println("Fx set frequency in Hz, x=19999999 ... 2500000000"); } else { Serial.println("Unknown command!"); } buffer = ""; // erase buffer for next command } } } //----------------------------------------------------------------------------------------- void loop() { // GO SLEEP remote(); } //----------------------------------------------------------------------------------------- void UpdateFreq( unsigned long long F_OUT) { // NOTE: SIMPLIFIED CALCULATIONS, AS F_MIN > 6.4 MHz, // LSDIV IS ALWAYS 1, 0x00 if (F_OUT < F_OUT_MIN) F_OUT = F_OUT_MIN ; if (F_OUT > F_OUT_MAX) F_OUT = F_OUT_MAX ; byte Aux = 0x00 ; unsigned long HSDIV ; unsigned long XTAL = 152600000 ; // Hz double FBDIV ; unsigned long INTEGER ; unsigned long long FRACTION ; unsigned long long F_VCO ; FBDIV = (double)(F_VCO_MIN * 1.0 / F_OUT ); HSDIV = (int)(FBDIV + 0.5) ; if ((HSDIV > 32) && (HSDIV % 2)) HSDIV += 1 ; // MIN MAX VALUE if (HSDIV < 4) HSDIV = 4 ; if (HSDIV > 2046) HSDIV = 2046 ; F_VCO = HSDIV * F_OUT ; FBDIV = (double)(F_VCO * 1.0 / XTAL) ; INTEGER = FBDIV ; // FLOOR FRACTION = 4294967295.0 * (double)(FBDIV - INTEGER) ; // Get Device Ready for Update // Set page register to point to page 0 Si564_Write_Byte( 255, 0x00) ; // Disable FCAL override Si564_Write_Byte( 69, 0x00) ; // Synchronously disable output Si564_Write_Byte( 17, 0x00) ; // HSDIV [7:0] Aux = HSDIV & 0xFF ; Si564_Write_Byte( 23, Aux) ; // LSDIV[2:0]; HSDIV[10:8] Aux = (HSDIV >> 8) & 0x07 ; Si564_Write_Byte( 24, Aux) ; // FBDIV [7:0] Aux = FRACTION & 0xFF ; Si564_Write_Byte( 26, Aux) ; // FBDIV [15:8] Aux = (FRACTION >> 8 ) & 0xFF ; Si564_Write_Byte( 27, Aux) ; // FBDIV [23:16] Aux = (FRACTION >> 16 ) & 0xFF ; Si564_Write_Byte( 28, Aux) ; // FBDIV [31:24] Aux = (FRACTION >> 24 ) & 0xFF ; Si564_Write_Byte( 29, Aux) ; // FBDIV [39:32] Aux = INTEGER & 0xFF ; Si564_Write_Byte( 30, Aux) ; // FBDIV [42:40] Aux = (INTEGER >> 8 ) & 0x07 ; Si564_Write_Byte( 31, Aux) ; // Start FCAL using new divider values Si564_Write_Byte( 7, 0x08) ; // Synchronously enable output Si564_Write_Byte( 17, 0x01) ; } //----------------------------------------------------------------------------------------- void Si564_Write_Byte( byte Register, byte Value) { byte Error = 0x00 ; Wire.beginTransmission(Si564_Address); Wire.write(Register); Wire.write(Value); Error = Wire.endTransmission(); SerialHexOutput(Value) ; /* switch (Error) { case 0 : Serial.println("0:success"); break; case 1 : Serial.println("1:data too long to fit in transmit buffer"); break; case 2 : Serial.println("2:received NACK on transmit of address"); break; case 3 : Serial.println("3:received NACK on transmit of data"); break; case 4 : Serial.println("4:other error"); break; } */ } //----------------------------------------------------------------------------------------- void SerialHexOutput(byte value) { //Serial.print("0x"); //if (value < 0x10) Serial.print("0"); //Serial.println(value,HEX); } //----------------------------------------------------------------------------------------- // ///////////////////////////////////////////////////////////////////// // END OF FILE // /////////////////////////////////////////////////////////////////////