Estimada comunidad estoy realizando con harto entusiasmo un proyecto para poder emitir señales PSK31 por radio ya que hay muchos programas en Windows y Android para decodificar. He googleado por un montón de partes y encontre uno que me pareció excelente porque no requiere de mucho hardware adicional, solo una adaptación de impedancias del Arduino Diecimilia al micrófono de una radio.
Lo principal es que el programa funciona con PWM con interrupciones propias del ATMega168 para poder mantener la cronometría de cada bit.
El problema con el que me topo es que genera una señal continua de una palabra (definida por mi), pero quiero hacer que se genere la cantidad de veces que yo desee. Esto es porque no domino bien el tema de las interrupciones vs los distintos comandos del código Arduino como delay(), while(),etc. Lo que quiereo conseguir es mantener un control en el loop() para que no sea continua sino algo como (int i=0; i <= 10; i++). Alguien sabe como poder controlar sin desestabilizar las interrupciones?
Desde ya agradecido por cualquier ayuda y por supuesto una vez que resuelva estos inconvenientes, mantendré actualizado el proyecto.

#include "avr/pgmspace.h"
// Tabla de 256 valores para construir una onda senoidal almacenada en memoriaflash
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
// Palabra "MAFARI" codificada en Varicode
PROGMEM prog_uchar msg[] = {1,0,1,1,1,0,1,1, 0,0, 1,1,1,1,1,0,1, 0,0, 1,1,0,1,1,0,1,1, 0,0, 1,1,1,1,1,0,1, 0,0, 1,0,1,0,1,1,1,1, 0,0, 1,1,1,1,1,1,1, 0,0, 0,0, 1, 0,0}; //Mauricio
byte ptr = 0;
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
double dfreq;
// const double refclk=31372.549; // =16MHz / 510
const double refclk=31335.6; // medido
// variables usadas dentro del servicio de interrupcion declaradas como volatile
volatile byte icnt; // variable dentro de interrupcion
volatile byte icnt1; // variable dentro de interrupcion
volatile byte c4ms; // countador incrementado todo 4ms
volatile unsigned long phaccu; // Acumulador de fase
volatile unsigned long tword_m; // dds tuning word m
volatile byte offset;
void setup()
{
pinMode(11, OUTPUT); // pin 11= Salida PWM / frequencia de salida
Setup_timer2();
// disabilita interrupciones para evitar distorsion por temporizacion
cbi (TIMSK0,TOIE0); // desabilita Timer0 !!! delay() no esta disponible
sbi (TIMSK2,TOIE2); // habilita interrupcione Timer2
dfreq=1000.0; // Frequencia Incial de Tx = 1000 Hz
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
}
void loop()
{
//Es aqui donde quiero poner un control para emitir mi mensaje la cant. de veces que yo desee y no en forma continua.
byte sig; // Byte para asignar el valor del bit de la letra que se esta enviando
if (c4ms >= 8) { // timer / wait for 32ms = 31.25 baud
c4ms=0;
sig = pgm_read_byte_near(msg + ptr); //Aqui se rescata el bit de la letra que esta enviando
ptr++;
if (ptr > 62) ptr=0;
if (sig == 0) { //Aqui se analiza si el valor del bit es cero o no
offset = offset + 128; //Si el valor del bit es cero entonces cambia de fase para producir el efecto PSK
}
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2() {
// Timer2 Clock Prescaler to : 1
TCCR2B = 0<<CS22 | 0<<CS21 | 1<<CS20;
// Timer2 PWM Mode set to Phase Correct PWM
TCCR2A = 1<<COM2A1 | 0<<COM2A0;
sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {
phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
icnt=phaccu >> 24; // use upper 8 bits for phase accu as frequency information
icnt = icnt + offset;
OCR2A=pgm_read_byte_near(sine256 + icnt); // read value from ROM sine table and send to PWM DAC
if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds (125)
c4ms++;
icnt1=0;
}
}