I am trying to use an Arduino Mini Pro 328P 5V 16Mhz https://www.sparkfun.com/products/11113 for signal decoding and am encountering interrupt jitter more than I expected. Below is a test program, it uses timer 1 in Fast PWM mode to generate 20Khz pulses on OC1B which also triggers an interrupt routine that pulses the LED.
When connecting the PWM output to scope channel 2 (trigger) and the LED output to scope channel 1 I am seeing a jitter of 4.5usec (~70 cycles) in the start time of the LED pulse relative to OC1B. I suspected some background interrupts (timer0?) and tried to disabled them for no avail. (scope is in infinite screen persistence mode)
Bingo! With your code I get 1 clock cycle jitter. Better than I expected. I guess this is because of the 2 cycle instructions. Thanks Badly.
Now that the interrupts are disabled (like it and will keep it this way), what are my options? Is there a simple non interrupt serial output library that I can use for debugging, even a blocking call should be fine? What about a crude delay()?
I think can figure out how to implement them myself but would be nice to use something of the shelf.
EDIT: on a second thought, the serial does not need to be blocking. It can use buffers and poll using a serial_update() method calls from loop().
Thanks Badly. Very useful pointers. I looked at the examples and came with this simple class that uses uart hardware but no interrupts. I need tx only so did not bothered with rx.
#ifndef DEBUG_OUT_H
#define DEBUG_OUT_H
#include <arduino.h>
#include <print.h>
// A serial output that uses hardware uart0 but with no interrupts.
// Requires periodic calls to update();
class DebugOut :
public Print {
public:
DebugOut()
:
_start(0),
_count(0) {
}
void init() {
// 38400 baud @ 16MHz.
UBRR0H = 0;
UBRR0L = 25;
// Enable the transmitter. Reciever is disabled.
UCSR0B = (1 << TXEN0);
UCSR0C = (3 << UCSZ00);
}
// Overrides Print::write().
size_t write(uint8_t b) {
if (_count >= kQueueSize) {
return 0;
}
enqueue(b);
return 1;
}
// Called periodically from loop() to do the transmission. Non
// blocking.
void update() {
if (_count && ( UCSR0A & (1 << UDRE0))) {
UDR0 = dequeue();
}
}
bool is_empty() {
return !_count;
}
private:
// Max TX queue size. Should be less than 255/2 to
// avoid byte arithmetic overflow below.
static const byte kQueueSize = 80;
byte _buffer[kQueueSize];
// Index of first (oldest) byte. [0, kQueueSize).
byte _start;
// Number of bytes in the queue. [0, kQueueSize].
byte _count;
// Assumes _count < kQueueSize.
void enqueue(byte b) {
// kQueueSize is small enough that this will not overflow.
byte next = _start + _count;
if (next >= kQueueSize) {
next -= kQueueSize;
}
_buffer[next] = b;
_count++;
}
// Assumes _count > 0.
byte dequeue() {
const byte b = _buffer[_start];
if (++_start >= kQueueSize) {
_start = 0;
}
_count--;
return b;
}
};
#endif
I will do something similar for having millis() without interrupts. 16 bit Timer 1 running freely with some prescaler, periodic update() calls from loop() that read the timer, detects overflows and computes a milliseconds time (I need one value per loop iteration, the loop code is not blocking). Between these two I think I have everything I need to start writing my real code.