1

I'm writing software for a laser tag gun, which under the system we use needs the output waveform to be a carrier wave of 57600Hz with a signal wave of 1800HZ for about 50ms

Using the Tone library (https://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation) and a transistor AND gate, I've had this working using two timers, however I really want to shrink it down to one timer so that I can use the other for sound (using the TMRPCM library which only needs timer1).

I've modified the Tone library cut down to what I need, with the following methods:

void TagTone::beginPulse(uint8_t tonePin)
{
    _pin = tonePin;
    _timer = 2;

    // 8 bit timer
    TCCR2A = 0;
    TCCR2B = 0;
    bitWrite(TCCR2A, WGM21, 1);
    bitWrite(TCCR2B, CS20, 1);
    timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
    timer2_pin_mask = digitalPinToBitMask(_pin);

    int duration = 50; //50 milliseconds
    uint8_t prescalarbits = 0b001;
    int32_t signal_toggle_count = 0;


    // Note: may need prescaler reimplemented if using 16Mhz, fine on current 8Mhz
    ocr = F_CPU / (CARRIER_FREQUENCY * 2) - 1;
    prescalarbits = 0b001;  


    TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;

    toggle_count = 2 * CARRIER_FREQUENCY * duration / 1000; // how many times the carrier toggles before pulse ends

    // want to AND with 1800 Hz signal

    // as duration now set to 50: toggle_count for carrier = 5760
    // equivalent toggle count for signal = 180
    signal_toggle_count = 2* SIGNAL_FREQUENCY * duration / 1000;

    // want to flip signal state every 32 carrier pulses
    signal_cycle_count = 32; //toggle_count / signal_toggle_count;
}



// duration (in milliseconds).

void TagTone::playPulse()
{

    OCR2A = ocr;
    timer2_signal_toggle_count = signal_cycle_count;
    timer2_toggle_count = toggle_count;
    bitWrite(TIMSK2, OCIE2A, 1);

}


ISR(TIMER2_COMPA_vect)
{
    if(timer2_toggle_count  < 0)
    {
        *timer2_pin_port ^= timer2_pin_mask & signal_state; // flip

        if (timer2_signal_toggle_count > 0)
        {
          timer2_signal_toggle_count--;
        }
        else
        {
            signal_state ^= signal_state;
            timer2_toggle_count -= timer2_signal_toggle_count;
            timer2_signal_toggle_count = signal_cycle_count;
        }
    }
    else
    {
        TIMSK2 &= ~(1 << OCIE2A);                 // disable the interrupt
        *timer2_pin_port &= ~(timer2_pin_mask);   // keep pin low after stop
    }
}

What I hope this is doing is 32 toggles at the carrier speed (ie 16 full cycles of 57600Hz), followed by 32 'silent' toggles where nothing happens, followed by another 32 at carrier speed, etc. I should then be able to fire using:

digitalWrite(signalPin, HIGH);
carrierTone.playPulse();
delay(60);
digitalWrite(signalPin, LOW);

But that doesn't set off the sensor, whereas the simple code below works.

carrierTone.play(57600, 50);
signalTone.play(1800, 50);
0

Woo, solved it. My ISR code was completely wrong. Works using:

ISR(TIMER2_COMPA_vect)
{
  if (timer2_signal_toggle_count != 0)
  {
    // toggle the pin
    if(signal_state == 1)
        *timer2_pin_port ^= timer2_pin_mask;

    if (timer2_toggle_count > 0)
      timer2_toggle_count--; 
    else
    {
        TIMSK2 &= ~(1 << OCIE2A);                 // disable the interrupt
        *timer2_pin_port &= ~(timer2_pin_mask);   // keep pin low after stop
    }
     timer2_signal_toggle_count --; 
  }
  else
  {
    timer2_signal_toggle_count = signal_cycle_count;
    timer2_toggle_count --;
    if(signal_state == 1)
    {
        signal_state = 0;
        *timer2_pin_port &= ~(timer2_pin_mask);
        //*timer2_pin_port ^= timer2_pin_mask;
    }
    else 
    {
        signal_state = 1;
        *timer2_pin_port ^= timer2_pin_mask;
    }
  }
}

I was trying to just AND the signal state into the original pin state, which was completely the wrong thing to do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.