On an Arduino Mega (or an Uno with the ATmega328P replaced with an ATmega328PB, but then you'd have to adapt the code slightly), this can be done via the output compare modulator:
void setup() {
// CTC, OC0A toggle on compare match, prescale 1/8
TCCR0A = _BV(COM0A0)|_BV(WGM01);
TCCR0B = _BV(CS01);
// toggle every 35.5 μs at 16 MHz and 1/8 prescale
OCR0A = 70;
// phase and frequency correct PWM, TOP is OCR1A, OC1C clear on compare match and set at BOTTOM, no prescale
TCCR1A = _BV(COM1C1)|_BV(WGM10);
TCCR1B = _BV(WGM13)|_BV(CS10);
// period of 2 ms at 16 MHz and no prescale
OCR1A = 31999;
// on-time of 1 ms at 16 MHz and no prescale
OCR1C = 15999;
// no interrupts from the timers
TIMSK0 = 0;
TIMSK1 = 0;
// only output a 1 when both timers are outputting a 1
PORTB &= ~_BV(PORTB7);
// halt the timers and reset the prescaler
GTCCR |= _BV(TSM);
GTCCR |= _BV(PSRSYNC);
// reset both timers
TCNT0 = 0;
TCNT1 = 0;
// enable output
DDRB |= _BV(DDB7);
// let the timers run
GTCCR &= ~_BV(TSM);
}
void loop() {
// Just adjust the frequencies and duty cycle as required here.
// Everything is handled by the hardware and takes effect immediately upon writing to the register.
// OCR1A: 1 less than the desired period of the slower signal, in 16ths of microseconds. Can be up to 65535.
// OCR1C: 1 less than the desired on-time of the slower signal, in 16ths of microseconds. Can be up to 65535.
// OCR0A: 1 less than the desired period of the faster signal, in microseconds. Can be up to 255.
// The on-time of the faster signal is always half of the period.
// If necessary, you can trade precision for more range for any of the above values by adjusting the prescaler.
}
With that sketch, pin 13 on the Mega will have the desired waveform. There's two big advantages to this method. First, it doesn't require any CPU resources at all (no loops or interrupts) once it's set up, so you can dedicate all of loop to reading the potentiometer and adjusting the duty cycle without worrying about glitches in the output. Second, being entirely hardware controlled means its output will be accurate and perfectly consistent (the 500 Hz component is perfect, and the 14 kHz component is approximately 14085 Hz). The one disadvantage, though, is that millis and everything else in the Arduino library that uses timers internally won't work quite right, since we're using the same hardware timers that they depend on.