(I can't upload multiple images, hence i put this illustration to one single image instead)
I really want a consistent sampling in Task 3, while Task 2 overshadows the Task 1...
The ISR interval can be changed any time (for custom sample rate)
(I can't upload multiple images, hence i put this illustration to one single image instead)
I really want a consistent sampling in Task 3, while Task 2 overshadows the Task 1...
The ISR interval can be changed any time (for custom sample rate)
You wanted co-operative multitasking, but programmed for interrupt oriented multi-tasking. Why?
I think that your question is lacking details. Although real multitasking is mostly outside my area of knowledge, some more details might help others to help you
The example image I had illustrated above, the second illustration, is when i put the Task 2 inside ISR. And the Wokwi project is when I put the Task 2 inside the main loop(). The result is still not something I wanted. It supposed to be sounded like this however 1-bit Sampler Monotonic Music Player (XO-Chip Music) - Wokwi Arduino and ESP32 Simulator, where the Task 2 ran consistently, doesn't be slowed down by the Task 3.
With those long blocks of code blocking, I’d guess there are delay()s, or for/while() loops that are hogging the cpu in some way.
I’m sure what you want can be done, but without seeing your code, or attached devices, it’s pretty hard to tell.
Actually, i want that long block (Task 2) became interrupted, therefore that long block became paused at a time, the CPU does the Task 3, and the Task 3 is short task.
The Task 1 would be only continued when Task 2 and Task 3 already done. Task 3 retriggered again on the next interrupt
There is might be misunderstanding to my question. The Task 2 on the first illustration is actually a long task, being sliced by the interrupts. Task 3 is the important ones therefore should be executed first, and it only last in short time before Task 2 continued again. When Task 2 is done, the Task 1 continues until next interrupt
OP's code where it should be
// Written by Kouzerumatsukite (28-30 Ags 2022)
// The "Tsukite the Bananafox" song is composed by me
// Original: https://www.youtube.com/watch?v=YDCRszWIDwk
// the song in this project is the stripped version of it.
// And the `macro-based` music driver here is written by me,
// which in the design was inspired by Trackers known to me,
// like FamiTracker, VortexTracker, and Monotone Tracker.
// Its simply migration from
// https://johnearnest.github.io/Octo/index.html?key=TloHp4JQ
// (click the site to activate sound, click X to view source)
// Monotonic (square wave only) version:
// https://wokwi.com/projects/341297619980517970
// The playback consistency relies on the audiobuffer
// the buffer length is set to 2048 samples
// means it lags 4 frames behind before buffer runs out,
// This should be good enough for 15625hz samplerate
//BROAD: Use 128X64 screen;
//Comment this if you're using 128x32
#define SCREEN_BROAD 1
//#define DEBUG 1 // monitor the states to serial
//#define MONITOR 1 // monitor the buffer health to serial
#include <avr/pgmspace.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#ifdef SCREEN_BROAD
#define SCREEN_HEIGHT 64
#else
#define SCREEN_HEIGHT 32
#endif
static Adafruit_SSD1306 display(128, SCREEN_HEIGHT, &Wire, -1, 800000L, 100000L);
#define ____ 0b00000000
#define H___ 0b11000000
#define HH__ 0b11110000
#define HHH_ 0b11111100
#define HHHH 0b11111111
const byte PROGMEM smpData[]{
// SAMPLE BUFFER DATA [ 128 bytes ]
____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x00 | Silence
HH__, ____, ____, ____, HH__, ____, ____, ____, HH__, ____, ____, ____, HH__, ____, ____, ____, // 0x10 | 12.5% Pulse Duty
HHHH, ____, ____, ____, HHHH, ____, ____, ____, HHHH, ____, ____, ____, HHHH, ____, ____, ____, // 0x20 | 25.0% Pulse Duty
HHHH, HHHH, ____, ____, HHHH, HHHH, ____, ____, HHHH, HHHH, ____, ____, HHHH, HHHH, ____, ____, // 0x30 | 50.0% Pulse Duty
0x41, 0x47, 0xE1, 0xE4, 0x91, 0x16, 0xD9, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 | 50.0% Pulse Noise
0x35, 0x53, 0xAF, 0xFA, 0xF8, 0x87, 0x04, 0xC4, 0x06, 0xA6, 0x05, 0x75, 0x87, 0xCF, 0x44, 0xA8, // 0x50 | 100.0% Pulse Noise
0x66, 0xFC, 0x55, 0x02, 0x7F, 0x83, 0xC0, 0xC2, 0xA0, 0xA3, 0x70, 0xF2, 0x48, 0x8B, 0xEC, 0xCE, // 0x60 | 100.0% Pulse Noise
0x9A, 0xA9, 0x57, 0x7D, 0xFC, 0x43, 0x02, 0x62, 0x03, 0xD3, 0x82, 0xBA, 0xC3, 0x67, 0x22, 0x54, // 0x70 | 100.0% Pulse Noise
HHHH, HHH_, ____, ____, HHHH, HHH_, ____, ____, HHHH, HHH_, ____, ____, HHHH, HHH_, ____, ____, // 0x80 | 43.25% Pulse Duty
HHHH, HH__, ____, ____, HHHH, HH__, ____, ____, HHHH, HH__, ____, ____, HHHH, HH__, ____, ____, // 0x90 | 37.50% Pulse Duty
HHHH, H___, ____, ____, HHHH, H___, ____, ____, HHHH, H___, ____, ____, HHHH, H___, ____, ____, // 0xA0 | 31.75% Pulse Duty
HHH_, ____, ____, ____, HHH_, ____, ____, ____, HHH_, ____, ____, ____, HHH_, ____, ____, ____, // 0xB0 | 18.25% Pulse Duty
};
const byte PROGMEM instrSet[]{
// SAMPLE AND ORNAMENT SEQUENCE MAPPER [ 128 bytes ]
// 0 1 2 3 4 5 6 7
// 8 9 10 11 12 13 14 15
// __________ __________ __________ __________ __________ __________ __________ __________
//| smpI ornI| smpI ornI| smpI ornI| smpI ornI| smpI ornI| smpI ornI| smpI ornI| smpI ornI|
0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x30, 0x30, 0x80, 0x01, 0x80, 0x11, 0xC0, 0x01, 0xC0, 0x11, // Silence + HKS & 12
0x01, 0x00, 0x11, 0x10, 0x21, 0x20, 0x31, 0x30, 0x01, 0x21, 0x40, 0x21, 0x80, 0x21, 0xC0, 0x21, // User-def instruments
0x40, 0x00, 0x50, 0x10, 0x60, 0x20, 0x70, 0x30, 0x40, 0x40, 0x50, 0x50, 0x60, 0x60, 0x70, 0x70, // 12.5% Lead + HKS +
0x40, 0x80, 0x50, 0x90, 0x60, 0xA0, 0x70, 0xB0, 0x40, 0xC0, 0x50, 0xD0, 0x60, 0xE0, 0x70, 0xF0, // maj-min-dim chords
0x80, 0x00, 0x90, 0x10, 0xA0, 0x20, 0xB0, 0x30, 0x80, 0x40, 0x90, 0x50, 0xA0, 0x60, 0xB0, 0x70, // 25.0% Lead + HKS +
0x80, 0x80, 0x90, 0x90, 0xA0, 0xA0, 0xB0, 0xB0, 0x80, 0xC0, 0x90, 0xD0, 0xA0, 0xE0, 0xB0, 0xF0, // maj-min-dim chords
0xC0, 0x00, 0xD0, 0x10, 0xE0, 0x20, 0xF0, 0x30, 0xC0, 0x40, 0xD0, 0x50, 0xE0, 0x60, 0xF0, 0x70, // 50.0% Lead + HKS +
0xC0, 0x80, 0xD0, 0x90, 0xE0, 0xA0, 0xF0, 0xB0, 0xC0, 0xC0, 0xD0, 0xD0, 0xE0, 0xE0, 0xF0, 0xF0, // maj-min-dim chords
};
const byte PROGMEM smpRef[]{
// SAMPLE SEQUENCE DATA [ 256 bytes ]
// Loop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// PREDEFINED SAMPLE DATA
15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x00] Silence
15, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x10] Hat only
15, 0x50, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x20] Kick only
15, 0x70, 0x60, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // [0x30] Snare only
15, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // [0x40] 12.5 % Pulse Tone
15, 0x70, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // [0x50] Hat + 12.5 % Pulse
15, 0x50, 0x40, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // [0x60] Kick + 12.5 % Pulse
15, 0x70, 0x60, 0x50, 0x40, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // [0x70] Snare + 12.5 % Pulse
15, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // [0x80] 25 % Pulse Tone
15, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // [0x90] Hat + 25 % Pulse
15, 0x50, 0x40, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // [0xA0] Kick + 25 % Pulse
15, 0x70, 0x60, 0x50, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // [0xB0] Snare + 25 % Pulse
15, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // [0xC0] 50 % Pulse Tone
15, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // [0xD0] Hat + 50 % Pulse
15, 0x50, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // [0xE0] Kick + 50 % Pulse
15, 0x70, 0x60, 0x50, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // [0xF0] Snare + 50 % Pulse
8, 0x20, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, 0xA0, 0x20, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, // [0x01] 25%-50% PWM Tone
8, 0x70, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, 0xA0, 0x20, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, // [0x11] Hat + 25%-50% PWM
8, 0x50, 0x40, 0x30, 0x80, 0x30, 0x80, 0x90, 0xA0, 0x20, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, // [0x21] Kick + 25%-50% PWM
8, 0x70, 0x60, 0x50, 0x40, 0x30, 0x80, 0x90, 0xA0, 0x20, 0xA0, 0x90, 0x80, 0x30, 0x80, 0x90, // [0x31] Snare + 25%-50% PWM
// theres no other samples needed beside above, hence nothing.
};
const byte PROGMEM ornData[]{
// ORNAMENT SEQUENCE DATA [ 256 bytes ]
// Odd values (e.g. 63 67 71 ) is fixed pitch alter.
// Even values (e.g 4 8 12 -4 -8 -12 ) is relative pitch alter.
// Zero value won't alter the current pitch.
// Loop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// PREDEFINED ORNAMENTS DATA
13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x00] Tone
13, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x10] Hat + tone
13, 147, 103, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x20] Kick + tone
13, 107, 171, 159, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x30] Snare + tone
13, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, 0, // [0x40] Major chord tone
13, 211, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, // [0x50] Hat + major chord
13, 147, 103, 67, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, 0, // [0x60] Kick + major chord
13, 107, 171, 159, 147, 16, 28, 0, 16, 28, 0, 16, 28, 0, 16, 28, // [0x70] Snare + major chord
13, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, 0, // [0x80] Minor chord tone
13, 211, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, // [0x90] Hat + minor chord
13, 147, 103, 67, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, 0, // [0xA0] Kick + minor chord
13, 107, 171, 159, 147, 12, 28, 0, 12, 28, 0, 12, 28, 0, 12, 28, // [0xB0] Snare + minor chord
13, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, 0, // [0xC0] Diminish chord tone
13, 211, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, // [0xD0] Hat + diminish chord
13, 147, 103, 67, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, 0, // [0xE0] Kick + diminish chord
13, 107, 171, 159, 147, 12, 24, 0, 12, 24, 0, 12, 24, 0, 12, 24, // [0xF0] Snare + diminish chord
15, -20, -16, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x01] SlideUp
15, 20, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [0x11] SlideDown
10, 2, 2, 0, -2, -2, 0, 2, 2, 0, -2, -2, 0, 2, 2, 0, // [0x21] Vibratio
};
const PROGMEM byte seqData[]{
// the sequence data, song name: Tsukite the Bananafox
0x13,
0x80,
0x00,
0x00,
0x43,
0x80,
0x00,
0x00,
0x73,
0x00,
0x00,
0x00,
0x43,
0x80,
0x5F,
0x10,
0x57,
0x88,
0x00,
0x00,
0x57,
0x88,
0x00,
0x00,
0x57,
0x8C,
0x00,
0x00,
0x57,
0x88,
0x57,
0x8C,
0x00,
0x00,
0x57,
0x8C,
0x57,
0x88,
0x57,
0xD0,
0x57,
0x8C,
0x00,
0x00,
0x53,
0x84,
0x57,
0x80,
0x53,
0x88,
0x00,
0x00,
0x53,
0x88,
0x00,
0x00,
0x53,
0x8C,
0x00,
0x00,
0x53,
0x88,
0x53,
0x8C,
0x00,
0x00,
0x53,
0x8C,
0x53,
0x88,
0x43,
0x90,
0x53,
0x8C,
0x00,
0x00,
0x4B,
0x84,
0x43,
0x80,
0x43,
0x88,
0x4B,
0x80,
0x53,
0x88,
0x57,
0x80,
0x5F,
0x8C,
0x00,
0x00,
0x5F,
0x88,
0x5F,
0x8C,
0x00,
0x00,
0x5F,
0x8C,
0x5F,
0x88,
0x5F,
0xD0,
0x5F,
0x8C,
0x00,
0x00,
0x57,
0x84,
0x53,
0x84,
0x43,
0x88,
0x00,
0x00,
0x43,
0x88,
0x00,
0x00,
0x43,
0x8C,
0x43,
0x90,
0x43,
0x88,
0x43,
0x8C,
0x00,
0x00,
0x43,
0x38,
0x00,
0x00,
0x00,
0x00,
0x5F,
0x8C,
0x73,
0xD0,
0x5F,
0x8C,
0x5F,
0x8C,
0x43,
0x88,
0x4B,
0x80,
0x53,
0x8C,
0x57,
0x80,
0x5F,
0x80,
0x73,
0xD8,
0x57,
0x8C,
0x53,
0x80,
0x43,
0x88,
0x43,
0x38,
0x5F,
0x8C,
0x53,
0x88,
0x57,
0x80,
0x73,
0xD8,
0x53,
0x8C,
0x4B,
0x80,
0x43,
0x88,
0x43,
0x38,
0x53,
0x8C,
0x57,
0x80,
0x5F,
0x80,
0x73,
0xD8,
0x57,
0x8C,
0x53,
0x80,
0x43,
0x88,
0x43,
0x38,
0x5F,
0x8C,
0x67,
0x88,
0x57,
0x80,
0x73,
0xD8,
0x53,
0x8C,
0x4B,
0x8C,
0x43,
0x88,
0x2F,
0x14,
0x53,
0x8C,
0x57,
0x80,
0x5F,
0x80,
0x73,
0xD8,
0x57,
0x8C,
0x53,
0x80,
0x43,
0x88,
0x43,
0x38,
0x5F,
0x8C,
0x53,
0x88,
0x57,
0x80,
0x5F,
0x88,
0x57,
0x8C,
0x53,
0x88,
0x43,
0x88,
0x43,
0x38,
0x53,
0x8C,
0x57,
0x80,
0x5F,
0x80,
0x73,
0xD8,
0x57,
0x8C,
0x53,
0x80,
0x5F,
0x88,
0x73,
0xD0,
0x57,
0x8C,
0x53,
0x88,
0x5F,
0x80,
0x73,
0xDC,
0x67,
0x8C,
0x5F,
0x8C,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x73,
0x59,
0x00,
0x02,
0x87,
0x8D,
0x37,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x8F,
0x8D,
0x00,
0x02,
0x83,
0x89,
0x57,
0xC2,
0x87,
0x85,
0x87,
0x3A,
0x73,
0x59,
0x00,
0x02,
0x83,
0x8D,
0x43,
0xC2,
0x7B,
0x85,
0x00,
0x02,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x73,
0x59,
0x00,
0x02,
0x8F,
0xCD,
0xA3,
0x1A,
0xA3,
0xC5,
0x00,
0x02,
0x9F,
0xC9,
0x5F,
0xC2,
0x9F,
0xC5,
0x00,
0x02,
0xA3,
0xCD,
0x00,
0x02,
0x8F,
0xC9,
0x67,
0xC2,
0x8F,
0xCD,
0x8F,
0x3E,
0x87,
0xC9,
0x00,
0x02,
0x97,
0xCD,
0x00,
0x02,
0x8F,
0xCD,
0x73,
0x1E,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x73,
0x59,
0x00,
0x02,
0x87,
0x8D,
0x37,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x8F,
0x8D,
0x00,
0x02,
0x83,
0x89,
0x57,
0xC2,
0x87,
0x85,
0x00,
0x02,
0x8F,
0x89,
0x00,
0x02,
0x87,
0x8D,
0x43,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x73,
0x89,
0x43,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x73,
0x59,
0x00,
0x02,
0x8F,
0x8D,
0xA3,
0x12,
0xA3,
0x85,
0xA3,
0x3A,
0xAB,
0x8D,
0x00,
0x02,
0xAB,
0x85,
0xAB,
0x3A,
0xA3,
0x8D,
0x00,
0x02,
0x9F,
0x8D,
0x00,
0x02,
0x9F,
0x85,
0x9F,
0x3A,
0x9F,
0x8D,
0x8F,
0x16,
0x8F,
0x8D,
0x00,
0x02,
0x8F,
0x8D,
0x8F,
0x3A,
0xA3,
0x4C,
0x9F,
0x80,
0xA3,
0x48,
0x8F,
0x4C,
0x73,
0x90,
0x83,
0x88,
0x87,
0x8C,
0x87,
0x38,
0x00,
0x00,
0x83,
0x8C,
0x87,
0xC8,
0x83,
0x88,
0x87,
0x8C,
0x8F,
0xC8,
0x87,
0x8C,
0x83,
0x8C,
0x87,
0x89,
0x53,
0xC2,
0x83,
0x85,
0x73,
0x92,
0x87,
0x8D,
0x00,
0x02,
0x73,
0x89,
0x53,
0xC2,
0x73,
0x85,
0x00,
0x02,
0x73,
0x89,
0x73,
0x3A,
0x8F,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x00,
0x02,
0x97,
0x89,
0x57,
0xC2,
0x8F,
0x85,
0x87,
0xD2,
0x8F,
0x8D,
0x8F,
0x3A,
0x8F,
0x89,
0x57,
0xC2,
0x87,
0x85,
0x87,
0x82,
0x83,
0x89,
0x83,
0x3A,
0x87,
0x8D,
0x00,
0x02,
0x83,
0x85,
0x83,
0x3A,
0x87,
0x89,
0x5F,
0xC2,
0x83,
0x85,
0x73,
0x92,
0x87,
0x8D,
0x00,
0x02,
0x8F,
0x89,
0x5F,
0xC2,
0x8F,
0x85,
0x8F,
0x3A,
0x9F,
0x89,
0xA3,
0x82,
0x9F,
0x8D,
0x00,
0x02,
0xA3,
0x85,
0x00,
0x02,
0x8F,
0x89,
0x57,
0xC2,
0x87,
0x85,
0x87,
0xD2,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x89,
0x57,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x8F,
0x89,
0x00,
0x02,
0x8F,
0x8D,
0x8F,
0x3A,
0x8F,
0x8D,
0x8F,
0x3A,
0x87,
0x89,
0x53,
0xC2,
0x83,
0x85,
0x73,
0x92,
0x87,
0x8D,
0x00,
0x02,
0x83,
0x89,
0x53,
0xC2,
0x87,
0x85,
0x00,
0x02,
0x83,
0x89,
0x83,
0x3A,
0x87,
0x8D,
0x00,
0x02,
0x83,
0x85,
0x83,
0x3A,
0x83,
0x89,
0x57,
0xC2,
0x7B,
0x85,
0x87,
0xD2,
0x83,
0x8D,
0x00,
0x02,
0x7B,
0x89,
0x57,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x7B,
0x89,
0x7B,
0x3A,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x00,
0x02,
0x8F,
0x89,
0x5F,
0xC2,
0x87,
0x85,
0x8F,
0xD2,
0x8F,
0x8D,
0x00,
0x02,
0x87,
0x89,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x87,
0x89,
0x87,
0x3A,
0x8F,
0x8D,
0x00,
0x02,
0x87,
0x85,
0x00,
0x02,
0x8F,
0x89,
0x5F,
0xC2,
0x87,
0x85,
0x8F,
0xD2,
0x8F,
0x8D,
0x00,
0x02,
0x87,
0x89,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x97,
0x89,
0x00,
0x02,
0x83,
0x8D,
0x00,
0x02,
0x87,
0x8D,
0x00,
0x02,
0x73,
0x49,
0x53,
0xC2,
0x6F,
0x45,
0x73,
0x92,
0x73,
0x4D,
0x00,
0x02,
0x8F,
0x49,
0x53,
0xC2,
0x8F,
0x45,
0x8F,
0x36,
0x8F,
0x49,
0x8F,
0x36,
0x87,
0x4D,
0x53,
0xC2,
0x83,
0x45,
0x00,
0x02,
0x87,
0x49,
0x57,
0xC2,
0x8F,
0x45,
0x87,
0xD2,
0x8F,
0x4D,
0x8F,
0x36,
0x8F,
0x49,
0x57,
0xC2,
0xA3,
0x45,
0x00,
0x02,
0x9F,
0x49,
0x00,
0x02,
0xA3,
0x4D,
0x57,
0xC2,
0x9F,
0x45,
0x00,
0x02,
0xAB,
0x49,
0x5F,
0xC2,
0xAB,
0x45,
0x8F,
0xD2,
0xA3,
0x4D,
0xA3,
0x36,
0x9F,
0x49,
0x5F,
0xC2,
0x8F,
0x45,
0x00,
0x02,
0x8F,
0x49,
0x8F,
0x36,
0x87,
0x4D,
0x5F,
0xC2,
0x87,
0x45,
0x00,
0x02,
0x83,
0x49,
0x57,
0xC2,
0x83,
0x45,
0x87,
0x42,
0x87,
0x0D,
0x87,
0x42,
0x8F,
0x49,
0x57,
0xC2,
0x73,
0x45,
0x00,
0x02,
0x73,
0x49,
0x00,
0x02,
0x8F,
0x4D,
0x57,
0xC2,
0x8F,
0x4D,
0x8F,
0x36,
0x87,
0x89,
0x57,
0xC2,
0x83,
0x85,
0x87,
0xD2,
0x87,
0x8D,
0x00,
0x02,
0x83,
0x89,
0x57,
0xC2,
0x87,
0x85,
0x00,
0x02,
0x83,
0x89,
0x00,
0x02,
0x87,
0x8D,
0x57,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x83,
0x89,
0x53,
0xC2,
0x7B,
0x85,
0x83,
0xE2,
0x83,
0x8D,
0x00,
0x02,
0x7B,
0x89,
0x53,
0xC2,
0x83,
0x85,
0x00,
0x02,
0x7B,
0x89,
0x00,
0x02,
0x83,
0x8D,
0x53,
0xC2,
0x87,
0x8D,
0x00,
0x02,
0x8F,
0x89,
0x5F,
0xC2,
0x87,
0x85,
0x8F,
0xD2,
0x8F,
0x8D,
0x00,
0x02,
0x87,
0x89,
0x5F,
0xC2,
0x8F,
0x85,
0x00,
0x02,
0x97,
0x89,
0x00,
0x02,
0x8F,
0x8D,
0x5F,
0xC2,
0x87,
0x85,
0x00,
0x02,
0x73,
0x8D,
0x43,
0xC2,
0x73,
0x85,
0x73,
0xD2,
0x73,
0x85,
0x00,
0x02,
0x6F,
0x8D,
0x3F,
0xC2,
0x6F,
0x85,
0x00,
0x02,
0x6F,
0x8D,
0x00,
0x02,
0x6F,
0x8D,
0x5F,
0x16,
0x5F,
0x8D,
0x00,
0x02,
};
uint16_t ornPtr = 1; // ornament pointer
uint16_t smpPtr = 1; // sample pointer
uint8_t tickCtr = 0; // tick counter
uint8_t tickFin = 1; // tick final
uint8_t rowCtr = 255; // row counter
uint8_t rowFin = 8; // row final
uint16_t pageCtr = 0; // page counter
uint16_t pageFin = 67; // page fin
uint8_t notekey = 0; // current loaded pitch
uint8_t pitch = 0; // currently playing pitch
uint16_t freq = 0; // translated to freq
const byte PROGMEM seqTime[]{
// Song timeline of pages
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
};
const byte seqLoop = 9; // The song loop point
const byte PROGMEM seqTicks[]{
// Ticks speed
// _______ _______ _______ _______
// |Speed A|Speed B|Speed C|Speed D|
9,
5,
4,
3,
};
static char* toHex(uint64_t value, uint8_t digits)
{
static char result[17];
if (digits > 16) digits = 16;
for (byte k = 0; k < digits; k++)
result[k] = "0123456789ABCDEF"[value >> (digits - 1 - k) * 4 & 15];
result[digits] = 0;
return result;
}
static char* toPatt(uint16_t value)
{
static char result[8];
uint8_t note = (value >> 8) - 3 >> 2;
uint8_t macr = (value & 0xFF) >> 2;
if ((value >> 8) == 0)
{
result[0] = '.';
result[1] = '.';
result[2] = '.';
}
else
{
if (value & 0xF0)
{
result[0] = "GAABCCDDEFFG"[note % 12];
result[1] = "#-#--#-#--#-"[note % 12];
result[2] = (note - 4) / 12 + 0x31;
}
else
{
result[0] = '-';
result[1] = '-';
result[2] = '-';
}
}
result[3] = 32;
result[4] = "-UUUAAAABBBBCCCC"[macr / 4];
result[5] = ".---.JID.JID.JID"[macr / 4];
result[6] = macr < 16 ? ".HKS0123456789AB"[macr] : ".HDS"[macr & 3];
result[7] = 0;
return result;
}
void setupTimers()
{
// Modified in slight bit for suitable need, from reference:
// https://makezine.com/projects/advanced-arduino-sound-synthesis/#:~:text=Just%20connect%20a%20digital%20output,and%20ground%20without%20any%20amplification.
/******** Set up timer2 to call ISR ********/
TCCR2A = 0;
TCCR2B = 0;
TCCR2B |= 0b011; // 3-bit of prescaler
TIMSK2 = (1 << OCIE2A); // Call ISR when TCNT2 = OCRA2
OCR2A = 32; // Set frequency of generated wave
sei(); // Enable interrupts to generate waveform!
}
/******** Lookup table ********/
static byte* bufferData = NULL; // Storage for waveform
static uint16_t bufferPosA = 0;
static uint16_t bufferPosB = 0;
static uint16_t bufferNeed = 0;
static uint8_t buffPtr;
#ifdef SCREEN_BROAD
#define AUDIO_BUFFER_LENGTH 0x1FF
#else
#define AUDIO_BUFFER_LENGTH 0xFF
#endif
uint8_t getBufferByte(uint16_t addr)
{
addr &= AUDIO_BUFFER_LENGTH;
//addr = (addr&7)<<7 | (addr>>3&63);
addr = addr & 63 | addr >> 6 << 7;
return bufferData[addr];
};
void setBufferByte(uint16_t addr, uint8_t val)
{
addr &= AUDIO_BUFFER_LENGTH;
//addr = (addr&7)<<7 | (addr>>3&63);
addr = addr & 63 | addr >> 6 << 7;
bufferData[addr] = val;
};
static uint16_t sampPos = 0;
static bool lastSamp;
bool getSamp()
{
sampPos += freq;
lastSamp = pgm_read_byte(smpData + buffPtr + (sampPos >> 12 & 15)) >> 7 - (sampPos >> 9 & 7) & 1;
return lastSamp;
};
static bool refreshDisp = false;
static byte refreshTick = 0;
void performTick()
{
refreshTick--;
buffPtr = pgm_read_byte(smpRef + smpPtr); // update buffer
uint8_t orn = pgm_read_byte(ornData + ornPtr);
pitch = orn & 1 ? orn : notekey + (int8_t)orn;
freq = (uint16_t)(128 * pow(2, (double)(pitch - 64.) / 48.) * OCR2A / 32);
if (!digitalRead(2))
{
uint16_t l = 256 / OCR2A * 32;
for (byte k = 0; k < l / 8; k++)
{
if (bufferPosA - bufferPosB + 8 > AUDIO_BUFFER_LENGTH * 8)
{
break;
}
byte val = getSamp();
val += val + getSamp();
val += val + getSamp();
val += val + getSamp();
val += val + getSamp();
val += val + getSamp();
val += val + getSamp();
val += val + getSamp();
setBufferByte(bufferPosA >> 3, val);
bufferPosA += 8;
}
}
if (!(++ornPtr & 15))
{
ornPtr -= 16;
ornPtr += pgm_read_byte(ornData + ornPtr);
}
if (!(++smpPtr & 15))
{
smpPtr -= 16;
smpPtr += pgm_read_byte(smpRef + smpPtr);
}
if (++tickCtr == tickFin)
{
tickCtr = 0; // update row
if (++rowCtr == rowFin)
{
rowCtr = 0; // update page
if (++pageCtr == pageFin) pageCtr = seqLoop; // loop
}
auto idx = seqData + rowCtr * 2 + 16 * pgm_read_byte(seqTime + pageCtr);
uint16_t seq = (pgm_read_byte(idx + 0) << 8) + pgm_read_byte(idx + 1);
;
tickFin = pgm_read_byte(seqTicks + (seq & 3)); // extract tickspeed
if (seq >> 8)
{
notekey = seq >> 8; // extract pitch
auto insidx = instrSet + (seq >> 2 & 0b111111) * 2;
uint16_t ins = (pgm_read_byte(insidx) << 8) + pgm_read_byte(insidx + 1); // extract instrument
smpPtr = ins >> 8 & 0xF0 | (ins >> 8 & 0xF) << 8 | 1; // sample pointer
ornPtr = ins >> 0 & 0xF0 | (ins >> 0 & 0xF) << 8 | 1; // orn pointer
}
refreshDisp = true;
}
// print buffer health
// vvbvvvvvvvvvvvvvvvvvvvvv
//Serial.println(bufferNeed);
// ^^^^^^^^^^^^^^^^^^^^^^^^
// print buffer health
}
void performDisp()
{
refreshDisp = false;
display.setTextSize(1);
#ifndef SCREEN_BROAD
#define TRK_LEN 4
byte o = rowCtr & 0b100;
#else
#define TRK_LEN 8
byte o = 0;
#endif
auto idx = seqData + 16 * pgm_read_byte(seqTime + pageCtr + o);
for (byte j = o; j < TRK_LEN + o; j++)
{
//display.setCursor((j>>2)*64,(j&3)*8);
display.setCursor(0, (j - o) * 8);
display.setTextColor(j != rowCtr, j == rowCtr);
uint16_t seq = (pgm_read_byte(idx + 0 + j * 2) << 8) + pgm_read_byte(idx + 1 + j * 2);
display.print(j);
display.print(" ");
display.print(toPatt(seq));
display.print(seq & 3);
}
display.display();
}
#include <avr/interrupt.h> // Use timer interrupt library
static uint16_t divVal = 256;
static uint16_t divCnt = divVal;
static uint16_t sampleCount = 0;
static double sampleSpeed = 0;
/******** Called every time TCNT2 = OCR2A ********/
ISR(TIMER2_COMPA_vect)
{ // Called when TCNT2 == OCR2A
TCNT2 -= OCR2A;
if (bufferPosA - bufferPosB)
{
PORTB = 0 - (getBufferByte(bufferPosB >> 3) >> 7 - (bufferPosB & 7) & 1);
if ((bufferPosB & 0b111) == 7) setBufferByte(bufferPosB >> 3, 0);
bufferPosB++;
}
if (!--divCnt)
{
divCnt += divVal;
refreshTick++;
}
sampleCount++;
}
void setup()
{
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(13, OUTPUT);
digitalWrite(0, LOW);
digitalWrite(1, LOW);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
//display.ssd1306_command(0xDA);
//display.ssd1306_command(0x10);
display.display();
display.clearDisplay();
bufferData = display.getBuffer() + 64;
// put your setup code here, to run once:
setupTimers();
divVal = 256 / OCR2A * 32;
divCnt = divVal;
}
uint32_t lastMillis = millis();
void fillzero(int32_t value)
{
if (value < 1000)
{
Serial.print(' ');
if (value < 100)
{
Serial.print(' ');
if (value < 10)
{
Serial.print(' ');
}
}
}
}
void loop()
{
uint16_t bufferLast = bufferPosA - bufferPosB;
while (refreshTick) performTick();
uint16_t bufferLeft = bufferPosA - bufferPosB;
#ifdef MONITOR
fillzero(bufferLast);
Serial.print(bufferLast);
Serial.print(", ");
fillzero(bufferLeft);
Serial.print(bufferLeft);
Serial.println();
#endif
//if(refreshDisp) // update screen only when the row updates
performDisp();
#ifdef DEBUG
Serial.print("PRT: ");
Serial.print(toHex(pageCtr, 2));
Serial.print(toHex(rowCtr, 2));
Serial.print(toHex(tickCtr, 2));
Serial.print(", PNO: ");
Serial.print(toHex(pitch, 2));
Serial.print(toHex(notekey, 2));
Serial.print(toHex(orn, 2));
Serial.print(", Ptrs: ");
Serial.print(toHex(ornPtr, 3));
Serial.print(toHex(smpPtr, 3));
Serial.println();
#endif
/* //monitor the samplerate
uint32_t currMillis = millis();
if(currMillis - lastMillis >= 1000){
double val = (double)(currMillis-lastMillis)/1000.;
val = sampleCount / val; sampleCount = 0;
if(sampleSpeed==0.) sampleSpeed = val;
else sampleSpeed += (val-sampleSpeed)/4;
Serial.println(sampleSpeed);
lastMillis = millis();
}
*/
}
Honestly that code is intimating
That's why I was presenting simpler question, which is straight to the point.
Anyhow though, all the white spaces, tab, and line arrangements are important for me, as it's for my aid of data manipulations of something. Therefore it's harder if the array elements became unrolled, or get the white spaces removed.
I did notice that some things changed due to the auto-format; I did not expect some of them to go from a e.g. few lines to 67 lines.
If you would have posted your code here, we would not have had that problem. I suggest that you post your code here.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.