Archives par mot-clé : IW1QLH

Balise autonome WSPR avec MSP430

[GTranslate]

Ces derniers jours je me suis amusé un peu à programmer le LaunchPad de TI avec Energia. Le but étant de voir si du code Arduino (AVR ATMega) était facilement portable sur le MSP430.

Capture port série Balise WSPR MSP430 XV4Y (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/05/Capture-Balise-WSPR-MSP430 NULL.jpg)La réponse est oui, si le code est propre (pas toujours facile) et s’il n’utilise pas des librairies non encore portée sur Energia (ce qui va diminuer avec le temps). En pratique je suis parti d’un morceau de code de F4GKA/VA2GKA (http://www NULL.itsrainingelephants NULL.com/2012/04/29/wspr-30m-ready/#comments) et d’un autre de DH3JO (http://wsprnet NULL.org/drupal/node/1342) pour faire une balise WSPR autonome. Le code est fonctionnel mais n’a pas encore été testé sur l’air. Cerise sur le gâteau, il est “rétroportable” sur Arduino car il suffit de changer les numéros de broches.

J’ai encore un peu de travail autour de cela, mais pour les curieux voici les résultats de quelques heures de réflexion ce matin. Il me faut maintenant connecter cela sur la balise QRSS du kit de G0UPL / G0XAR et voir comment cela se comporte en particulier du point de vue dérive de la synchronisation dans le temps. Contrairement à mon Arduino Nano le LaunchPad n’est pas équipé d’origine d’un quartz mais j’ai ce qu’il faut sous la main.

Au passage la modification du kit balise QRSS peut se faire comme l’a fait IW1QLH avec une échelle R-2R (http://www NULL.iw1qlh NULL.net/index NULL.php/projects-hardware-mainmenu-66/99-qrp/115-qrss-beacon).

Le fichier pour Energia/Arduino est disponible au téléchargement (http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/05/WSPR_autonome_XV4Y NULL.txt). Attention, il faudra renommer le fichier en .ino au lieu du .txt (WordPress n’aime pas les .ino)

/* WSPR Static Generator for MSP430G2553
* Code for Energia 005a</code>

* By Yannick DEVOS - XV4Y - May 2012
* Free for HAM Radio usage

* Based on VA2GKA Guenael Jouchet code for sending
* Based on DH3JO Martin Nawrath for WSPR sequence encoding

*
* Internal clock of MSP430 could be not stable enough, try a Crystal
* Start the circuit on the second 0 of an odd minute

* Ouput on 2 bits PinA and PinB
* Mirror on LED1 and LED2 du LaunchPad for testing
* Output to Serial for testing
* Using an R-2R ladder it makes the G0UPL/G0XAR beacon frequency shift
*/

#include// Comment on Arduino, replace mySerial by Serial everywhere

#define wsprPinA 7
#define wsprPinB 6
#define LEDPinA 14
#define LEDPinB 2
#define StartBtn 5

const char SyncVec[162] = {
1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,
1,1,0,0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,
0,0,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1,0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,
0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,0,0
};

const char call[] = "XV4Y ";
const char locator[] = "OK20";
const byte power = 20;

int i;
char symbol;

int ii,bb;

byte c[11]; // encoded message

byte sym[170]; // symbol table 162
byte symt[170]; // symbol table temp
unsigned long n1; // encoded callsign
unsigned long m1; // encodes locator

TimerSerial mySerial; // Comment on Arduino

//******************************************************************
// Defining pins mode
// Encoding the WSPR sequence

void setup() {
mySerial.begin(); // Comment on Arduino
pinMode(wsprPinA, OUTPUT); // Change for Arduino/AVR
pinMode(wsprPinB, OUTPUT); // Change for Arduino/AVR
pinMode(LEDPinA, OUTPUT); // Change for Arduino/AVR
pinMode(LEDPinB, OUTPUT); // Change for Arduino/AVR
pinMode(StartBtn, INPUT_PULLUP); // INPUT for Arduino and put pin to HIGH
// digitalWrite(StartBtn, HIGH); // Don't use this on LaunchPad/MSP430

mySerial.print("\n\n\n*** MSP430 WPSR beacon \n");

encode_call();
mySerial.print("call: ");
mySerial.print(call);
mySerial.print(" ");
mySerial.print(n1,HEX);
mySerial.println(" ");

encode_locator();
mySerial.print("locator: ");
mySerial.print(locator);
mySerial.print(" ");
mySerial.print(m1 &lt;&lt; 2,HEX);
mySerial.println(" ");
for (bb=0;bb mySerial.print(c[bb],HEX);
mySerial.print(",");
}
mySerial.println("");
encode_conv();

mySerial.println("");

for (bb=0;bbmySerial.print(symt[bb],DEC);
mySerial.print(".");
if ( (bb+1) %32 == 0) mySerial.println("");
}
mySerial.println("");

interleave_sync();

mySerial.println("Channel symbols :");
for (bb=0;bb mySerial.print(sym[bb],DEC);
mySerial.print(".");
if ( (bb+1) %32 == 0) mySerial.println("");
}
mySerial.println("");

};

//******************************************************************
// Here starts the actual sequence sending

void loop() {
digitalWrite( wsprPinB, LOW );
digitalWrite( LEDPinB, LOW );

digitalWrite( wsprPinA, LOW );
digitalWrite( LEDPinA, LOW );
mySerial.println("*** Sequence sending delayed.");
mySerial.println("*** Press S2 to start now.");
i = 0;
while (i &lt; 9408) {
delay(1);
if (digitalRead(StartBtn)==LOW) {
i = 20000;
} else {
i++;
};

}

for (i = 0; i &lt; 170; i++) { symbol = sym[i]; mySerial.print(symbol%10, DEC); mySerial.print(" "); digitalWrite( wsprPinB, (symbol &gt;&gt; 1) );
digitalWrite( LEDPinB, (symbol &gt;&gt; 1) );

digitalWrite( wsprPinA, (symbol &amp; 1) );
digitalWrite( LEDPinA, (symbol &amp; 1) );
delay(682.667);
};
mySerial.println("\n *** End of sequence");
};

/* Functions declaration
* This code by DH3JO
* KHM 2009 / Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne
*/

//******************************************************************
void encode() {
encode_call();
encode_locator();
encode_conv();
interleave_sync();
};
//******************************************************************
// normalize characters 0..9 A..Z Space in order 0..36
char chr_normf(char bc ) {
char cc=36;
if (bc &gt;= '0' &amp;&amp; bc = 'A' &amp;&amp; bc &gt; 20;
t1=n1;
c[1]= t1 &gt;&gt; 12;
t1=n1;
c[2]= t1 &gt;&gt; 4;
t1=n1;
c[3]= t1 &lt;&lt; 4; } //****************************************************************** void encode_locator(){ unsigned long t1; // coding of locator m1=179-10*(chr_normf(locator[0])-10)-chr_normf(locator[2]); m1=m1*180+10*(chr_normf(locator[1])-10)+chr_normf(locator[3]); m1=m1*128+power+64; // merge coded locator and power into message array c[] t1=m1; c[3]= c[3] + ( 0x0f &amp; t1 &gt;&gt; 18);
t1=m1;
c[4]= t1 &gt;&gt; 10;
t1=m1;
c[5]= t1 &gt;&gt; 2;
t1=m1;
c[6]= t1 &lt;&lt; 6;

}
//******************************************************************
// convolutional encoding of message array c[] into a 162 bit stream
void encode_conv(){
int bc=0;
int cnt=0;
int cc;
unsigned long sh1=0;

cc=c[0];

for (int i=0; i &lt; 81;i++) {
if (i % 8 == 0 ) {
cc=c[bc];
bc++;
}
if (cc &amp; 0x80) sh1=sh1 | 1;

symt[cnt++]=parity(sh1 &amp; 0xF2D05351);
symt[cnt++]=parity(sh1 &amp; 0xE4613C47);

cc=cc &lt;&lt; 1;
sh1=sh1 &lt;&lt; 1;
}

}

//******************************************************************
byte parity(unsigned long li)
{
byte po = 0;
while(li != 0)
{
po++;
li&amp;= (li-1);
}
return (po &amp; 1);
}

//******************************************************************
// interleave reorder the 162 data bits and and merge table with the sync vector
void interleave_sync(){
int ii,ij,b2,bis,ip;
ip=0;

for (ii=0;iibis=1;
ij=0;
for (b2=0;b2 &lt; 8 ;b2++) { if (ii &amp; bis) ij= ij | (0x80 &gt;&gt; b2);
bis=bis &lt;&lt; 1;
}
if (ij &lt; 162 ) {
sym[ij]= SyncVec[ij] +2*symt[ip];
ip++;
}
}
}