reworked assigner note on

This commit is contained in:
Gordon JC Pearce 2024-09-17 21:10:00 +01:00
parent 72fa8a2aab
commit 3e16f5314f
3 changed files with 229 additions and 158 deletions

View File

@ -2,6 +2,8 @@
#include "cpuboard.hpp" #include "cpuboard.hpp"
// startup needs to clear RAM etc
// 0xffbe = 0x0c; transpose = 12;
// Disassembly of assigner.bin, 8192 bytes [0x0 to 0x1fff] // Disassembly of assigner.bin, 8192 bytes [0x0 to 0x1fff]
// ; start // ; start
// 0000: 4e 9a JRE $009C // 0000: 4e 9a JRE $009C
@ -20,7 +22,7 @@
// 000a: 04 08 10 LXI SP,$1008 // 000a: 04 08 10 LXI SP,$1008
// 000d: 20 40 INRW $0040 // 000d: 20 40 INRW $0040
// 000f: 80 CALT ($0080) // 000f: 80 CALT ($0080)
//
// ; bit patterns used for Note Off // ; bit patterns used for Note Off
// ; ANDed with a flag byte to mask it off // ; ANDed with a flag byte to mask it off
// 0010: fe JR $000F // 0010: fe JR $000F
@ -30,7 +32,7 @@
// 0014: ef JR $0004 // 0014: ef JR $0004
// 0015: df JR $0035 // 0015: df JR $0035
// 0016: bf 7f STAX (HL+$7F) // 0016: bf 7f STAX (HL+$7F)
//
// ; timer/event // ; timer/event
// 0018: 00 NOP // 0018: 00 NOP
// 0019: 00 NOP // 0019: 00 NOP
@ -873,7 +875,7 @@
// 0592: 11 EXX // 0592: 11 EXX
// 0593: aa EI // 0593: aa EI
// 0594: 62 RETI // 0594: 62 RETI
//
// ; serial interrupt handler // ; serial interrupt handler
// 0595: 10 EXA // 0595: 10 EXA
// 0596: 11 EXX // 0596: 11 EXX
@ -910,7 +912,7 @@
// 05d5: 75 a0 00 EQIW $00A0,$00 // 05d5: 75 a0 00 EQIW $00A0,$00
// 05d8: 71 a0 80 MVIW $00A0,$80 // 05d8: 71 a0 80 MVIW $00A0,$80
// 05db: d3 JR $05EF ; return from interrupt // 05db: d3 JR $05EF ; return from interrupt
//
// ; handle control change // ; handle control change
// 05dc: 1b MOV C,A // 05dc: 1b MOV C,A
// 05dd: 0a MOV A,B // 05dd: 0a MOV A,B
@ -927,7 +929,7 @@
// 05f0: 11 EXX // 05f0: 11 EXX
// 05f1: aa EI // 05f1: aa EI
// 05f2: 62 RETI // 05f2: 62 RETI
//
// ; wasn't control or note // ; wasn't control or note
// 05f3: 67 c0 NEI A,$C0 ; program change? // 05f3: 67 c0 NEI A,$C0 ; program change?
// 05f5: c4 JR $05FA // 05f5: c4 JR $05FA
@ -1050,53 +1052,111 @@
// //
// ; handle note on/off? // ; handle note on/off?
// ; called with status in $ff4e, value in $ff3e and velocity in C // ; called with status in $ff4e, value in $ff3e and velocity in C
void Assigner::noteOn(uint8_t c) {
// 06ca: 01 3e LDAW $003E ; first byte // 06ca: 01 3e LDAW $003E ; first byte
a = ram[0x3e];
h06cc:
// 06cc: 27 17 GTI A,$17 ; greater than 23 // 06cc: 27 17 GTI A,$17 ; greater than 23
// 06ce: 4e 36 JRE $0706 ; no, add an octave // 06ce: 4e 36 JRE $0706 ; no, add an octave
if (a > 0x17) {
// skip
} else
goto h0706;
h06d0:
// 06d0: 37 6d LTI A,$6D ; less than 108 // 06d0: 37 6d LTI A,$6D ; less than 108
// 06d2: 4e 36 JRE $070A ; no, subtract an octave // 06d2: 4e 36 JRE $070A ; no, subtract an octave
if (a < 0x6d) {
// skip
} else
goto h070a;
// 06d4: 74 e0 be SUBW $00BE ; subtract a value - transpose? // 06d4: 74 e0 be SUBW $00BE ; subtract a value - transpose?
a -= ram[0xbe];
// 06d7: 1a MOV B,A ; save in b // 06d7: 1a MOV B,A ; save in b
b = a;
// 06d8: 48 22 SLR B // 06d8: 48 22 SLR B
// 06da: 48 22 SLR B // 06da: 48 22 SLR B
// 06dc: 48 22 SLR B ; divide by 8 // 06dc: 48 22 SLR B ; divide by 8
b >>= 3;
// 06de: 07 07 ANI A,$07 ; lower three bits // 06de: 07 07 ANI A,$07 ; lower three bits
a &= 0x07;
// 06e0: 75 4e 90 EQIW $004E,$90 ; note on? // 06e0: 75 4e 90 EQIW $004E,$90 ; note on?
// 06e3: d5 JR $06F9 ; no, jump ahead // 06e3: d5 JR $06F9 ; no, jump ahead
if (ram[0x4e] == 0x90) {
// skip
} else
goto h06f9;
// 06e4: 74 6b 00 NEI C,$00 ; velocity 0 // 06e4: 74 6b 00 NEI C,$00 ; velocity 0
// 06e7: d1 JR $06F9 ; no, jump ahead // 06e7: d1 JR $06F9 ; no, jump ahead
if (c != 0) {
// skip
} else
goto h06f9;
// ; otherwise fall through and handle Note On // ; otherwise fall through and handle Note On
// 06e8: 34 08 00 LXI HL,$0008 ; lookup table runs 01, 02, 04, 08, 10, 20, 40, 80 // 06e8: 34 08 00 LXI HL,$0008 ; lookup table runs 01, 02, 04, 08, 10, 20, 40, 80
// ; inverse of the one at 0x0010 // ; inverse of the one at 0x0010
// 06eb: ac LDAX (HL+A) ; look up table based on note // 06eb: ac LDAX (HL+A) ; look up table based on note
hl = 0x08;
a = bitMask[hl + a]; // fetch bit corresponding to lower bits of note
// 06ec: 1b MOV C,A ; save // 06ec: 1b MOV C,A ; save
// 06ed: 34 40 ff LXI HL,$FF40 ; bit flags // 06ed: 34 40 ff LXI HL,$FF40 ; bit flags
// 06f0: ad LDAX (HL+B) ; byte pointed to by upper part // 06f0: ad LDAX (HL+B) ; byte pointed to by upper part
// 06f1: 60 9b ORA A,C ; or in whichever note is flagged // 06f1: 60 9b ORA A,C ; or in whichever note is flagged
// 06f3: bd STAX (HL+B) ; save in flag // 06f3: bd STAX (HL+B) ; save in flag
//
// ; c = a; // save A for later
hl = 0x40; // MIDI key bitmap
a = ram[hl + b];
a |= c;
ram[hl + b] = a; // OR in the bit we saved and save it back
// ; this sets up the MIDI routine to expect a two-byte message again
// which allows for running status
// 06f4: 71 3f 01 MVIW $003F,$01 ; expect two bytes // 06f4: 71 3f 01 MVIW $003F,$01 ; expect two bytes
// 06f7: 4f 53 JRE $064C ; return // 06f7: 4f 53 JRE $064C ; return
// return;
h06f9:
// ; note off? // ; note off?
// ; A contains lower three bits of note, B contains upper 4 bits // ; A contains lower three bits of note, B contains upper 4 bits
// 06f9: 34 10 00 LXI HL,$0010 ; lookup table runs fe, fd, fb, f7, ef, df, bf, 7f // 06f9: 34 10 00 LXI HL,$0010 ; lookup table runs fe, fd, fb, f7, ef, df, bf, 7f
// ; inverse of 0x0008 // ; inverse of 0x0008
// 06fc: ac LDAX (HL+A) ; look up the table based on the note // 06fc: ac LDAX (HL+A) ; look up the table based on the note
hl = 0x10;
a = bitMask[hl + a];
// 06fd: 1b MOV C,A ; fetch value, store in C // 06fd: 1b MOV C,A ; fetch value, store in C
// 06fe: 34 40 ff LXI HL,$FF40 ; table in RAM // 06fe: 34 40 ff LXI HL,$FF40 ; table in RAM
// 0701: ad LDAX (HL+B) ; $FF40 + upper four bits as offset // 0701: ad LDAX (HL+B) ; $FF40 + upper four bits as offset
// 0702: 60 8b ANA A,C ; mask off the bit for the note // 0702: 60 8b ANA A,C ; mask off the bit for the note
// 0704: bd STAX (HL+B) ; store at $FF40 + offset // 0704: bd STAX (HL+B) ; store at $FF40 + offset
c = a;
hl = 0x40;
a = ram[hl + b];
a &= c;
ram[hl + b] = a;
return;
// jump back to set up for running status
// 0705: ee JR $06F4 // 0705: ee JR $06F4
//
h0706:
// ; add or subtract an octave to bring out-of-range notes in // ; add or subtract an octave to bring out-of-range notes in
// 0706: 46 0c ADI A,$0C ; add 12 to note value in A // 0706: 46 0c ADI A,$0C ; add 12 to note value in A
// 0708: 4f c2 JRE $06CC ; jump back and test if it's in range yet // 0708: 4f c2 JRE $06CC ; jump back and test if it's in range yet
a += 12; // semitones
goto h06cc; // test again
h070a:
// 070a: 66 0c SUI A,$0C ; subtract 12 from note value in A // 070a: 66 0c SUI A,$0C ; subtract 12 from note value in A
// 070c: 4f c2 JRE $06D0 ; jump back and test if it's in range yet // 070c: 4f c2 JRE $06D0 ; jump back and test if it's in range yet
// a -= 12; // semitones
goto h06d0;
// ; store first value // ; store first value
// 070e: 63 3e STAW $003E // 070e: 63 3e STAW $003E
// 0710: 4f 3a JRE $064C ; return from interrupt // 0710: 4f 3a JRE $064C ; return from interrupt
@ -1185,7 +1245,7 @@
// 07a8: 4f 4a JRE $06F4 ; return, two byte running status // 07a8: 4f 4a JRE $06F4 ; return, two byte running status
// 07aa: 71 a1 80 MVIW $00A1,$80 ; reset bend? // 07aa: 71 a1 80 MVIW $00A1,$80 ; reset bend?
// 07ad: 4f 45 JRE $06F4 ; return, two byte running status // 07ad: 4f 45 JRE $06F4 ; return, two byte running status
// }
// ; handle TX interrupt // ; handle TX interrupt
// 07af: 01 c1 LDAW $00C1 ; buffer pointers? // 07af: 01 c1 LDAW $00C1 ; buffer pointers?
// 07b1: 74 f8 c2 EQAW $00C2 // 07b1: 74 f8 c2 EQAW $00C2

View File

@ -71,14 +71,16 @@ void Chassis::noteOn(uint8_t note) {
ic1.ram[0x4e] = 0x90; ic1.ram[0x4e] = 0x90;
ic1.ram[0x3e] = note; ic1.ram[0x3e] = note;
ic1.noteOn(); ic1.noteOn(0x40);
/* #ifdef D_MIDIBITMAP
printf("note on -> ");
for (uint8_t i = 0x40; i < 0x4f; i++) { for (uint8_t i = 0x40; i < 0x4f; i++) {
printf("%02x ", ic1.ram[i]); printf("%02x ", ic1.ram[i]);
} }
printf("\n"); printf("\n");
*/ #endif
s.keyon = true; s.keyon = true;
for (i = 0; i < NUM_VOICES; i++) { for (i = 0; i < NUM_VOICES; i++) {
vPtr++; vPtr++;
@ -98,16 +100,18 @@ void Chassis::noteOn(uint8_t note) {
} }
void Chassis::noteOff(uint8_t note) { void Chassis::noteOff(uint8_t note) {
ic1.ram[0x4e] = 0x80; ic1.ram[0x4e] = 0x90;
ic1.ram[0x3e] = note; ic1.ram[0x3e] = note;
ic1.noteOn(); ic1.noteOn(0);
/* #ifdef D_MIDIBITMAP
printf("note off -> ");
for (uint8_t i = 0x40; i < 0x4f; i++) { for (uint8_t i = 0x40; i < 0x4f; i++) {
printf("%02x ", ic1.ram[i]); printf("%02x ", ic1.ram[i]);
} }
printf("\n"); printf("\n");
*/ #endif
s.keyon = false; s.keyon = false;
for (uint32_t i = 0; i < NUM_VOICES; i++) { for (uint32_t i = 0; i < NUM_VOICES; i++) {
if (s.voice[i].note == note && !s.voice[i].isFree()) { if (s.voice[i].note == note && !s.voice[i].isFree()) {
@ -133,7 +137,7 @@ void Chassis::doMidi(const MidiEvent *ev, uint32_t count, uint32_t timeLimit) {
} }
lastEvent = i; lastEvent = i;
ic1.voiceOn(); //ic1.voiceOn();
} }
void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) { void Chassis::run(const float **, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount) {

View File

@ -2,16 +2,23 @@
#include <cstdint> #include <cstdint>
#define D_MIDIBITMAP
class Assigner { class Assigner {
public: public:
uint8_t ram[256]; uint8_t ram[256];
uint16_t a = 0, b = 0, c = 0, eal = 0, eah = 0; uint16_t a = 0, b = 0, c = 0, eal = 0, eah = 0;
uint32_t bc, de, hl, ea = 0; uint32_t bc, de, hl, ea = 0;
void noteOn(); void noteOn(uint8_t c);
void voiceOn(); void voiceOn();
void resetVoices(); void resetVoices();
// void clearNotes(); // void clearNotes();
// void assignNote(); // void assignNote();
private:
uint8_t bitMask[24] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
}; };