Skip to content

Instantly share code, notes, and snippets.

@pepijndevos pepijndevos/gbsynth.ino
Last active Dec 25, 2018

Embed
What would you like to do?
#include <SPI.h>
#include "registers.h"
#define SEMI 1.059463
#define LED 20
#define BITS(val, ofst, wdt) (((val) & ((1<<wdt)-1)) << ofst)
void writeReg(byte addr, byte data) {
SPI.transfer(addr);
delay(1);
SPI.transfer(data);
delay(1);
}
void ch1Sweep(int sweep_time, int sweep_length, int dir) {
byte data = BITS(sweep_time, 4, 3) | BITS(sweep_length, 0, 3) | BITS(dir, 3, 1);
writeReg(rAUD1SWEEP, data);
}
void ch1Length(int audio_length, int dutycycle) {
byte data = BITS(dutycycle, 6, 2) | BITS(audio_length, 0, 5);
writeReg(rAUD1LEN, data);
}
void ch1Envelope(int initial, int env_num, int dir) {
byte data = BITS(initial, 4, 4) | BITS(env_num, 0, 3) | BITS(dir, 3, 1);
writeReg(rAUD1ENV, data);
}
void ch1Play(float freq, int counter) {
int period = 2048*(freq-64)/freq;
writeReg(rAUD1LOW, period & 0xFF);
byte data = 0x80 | BITS(period >> 8, 0, 3) | BITS(counter, 6, 1);
writeReg(rAUD1HIGH, data);
}
void ch2Length(int audio_length, int dutycycle) {
byte data = BITS(dutycycle, 6, 2) | BITS(audio_length, 0, 5);
writeReg(rAUD2LEN, data);
}
void ch2Envelope(int initial, int env_num, int dir) {
byte data = BITS(initial, 4, 4) | BITS(env_num, 0, 3) | BITS(dir, 3, 1);
writeReg(rAUD2ENV, data);
}
void ch2Play(float freq, int counter, int re) {
int period = 2048*(freq-64)/freq;
writeReg(rAUD2LOW, period & 0xFF);
byte data = BITS(re, 7, 1) | BITS(period >> 8, 0, 3) | BITS(counter, 6, 1);
writeReg(rAUD2HIGH, data);
}
void setup() {
Serial.begin(115200);
Serial.print("hello world\n");
SPI.begin();
SPI.beginTransaction(SPISettings(8000, MSBFIRST, SPI_MODE3));
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
}
int oldValue = 0;
void loop() {
//ch1Sweep(0, 7, 0);
//ch1Length(63, 2);
//ch1Envelope(15, 7, 0);
//ch1Play(f, 0);
//delay(500);
int sensorValue = analogRead(A9);
Serial.print(sensorValue);
Serial.print(" ");
Serial.println(oldValue);
bool lowValue = sensorValue < 1;
bool oldLowValue = oldValue < 1;
int outputValue = map(sensorValue, 0, 1023, 440, 1760);
int oldOutputValue = map(oldValue, 0, 1023, 440, 1760);
if(!lowValue && oldLowValue) { // rising edge
ch2Length(63, 2);
ch2Envelope(15, 0, 0);
ch2Play(outputValue, 0, 1);
} else if (lowValue && !oldLowValue) { // falling edge
ch2Envelope(15, 3, 0);
ch2Play(oldOutputValue, 0, 1);
} else if(!lowValue) { // high
//ch2Length(63, 2);
//ch2Envelope(15, 0, 0);
ch2Play(outputValue, 0, 0);
}
oldValue = sensorValue;
delay(10);
}
// --
// -- AUDVOL/NR50 (0x24)
// -- Channel control / ON-OFF / Volume (R/W)
// --
// -- Bit 7 - Vin->SO2 ON/OFF (Vin??)
// -- Bit 6-4 - SO2 output level (volume) (# 0-7)
// -- Bit 3 - Vin->SO1 ON/OFF (Vin??)
// -- Bit 2-0 - SO1 output level (volume) (# 0-7)
// --
#define rNR50 0x24
#define rAUDVOL rNR50
// --
// -- AUDTERM/NR51 (0x25)
// -- Selection of Sound output terminal (R/W)
// --
// -- Bit 7 - Output sound 4 to SO2 terminal
// -- Bit 6 - Output sound 3 to SO2 terminal
// -- Bit 5 - Output sound 2 to SO2 terminal
// -- Bit 4 - Output sound 1 to SO2 terminal
// -- Bit 3 - Output sound 4 to SO1 terminal
// -- Bit 2 - Output sound 3 to SO1 terminal
// -- Bit 1 - Output sound 2 to SO1 terminal
// -- Bit 0 - Output sound 0 to SO1 terminal
// --
#define rNR51 0x25
#define rAUDTERM rNR51
// --
// -- AUDENA/NR52 (0x26)
// -- Sound on/off (R/W)
// --
// -- Bit 7 - All sound on/off (sets all audio regs to 0!)
// -- Bit 3 - Sound 4 ON flag (doesn't work!)
// -- Bit 2 - Sound 3 ON flag (doesn't work!)
// -- Bit 1 - Sound 2 ON flag (doesn't work!)
// -- Bit 0 - Sound 1 ON flag (doesn't work!)
// --
#define rNR52 0x26
#define rAUDENA rNR52
//***************************************************************************
//*
//* SoundChannel #1 registers
//*
//***************************************************************************
// --
// -- AUD1SWEEP/NR10 (0x10)
// -- Sweep register (R/W)
// --
// -- Bit 6-4 - Sweep Time
// -- Bit 3 - Sweep Increase/Decrease
// -- 0: Addition (frequency increases???)
// -- 1: Subtraction (frequency increases???)
// -- Bit 2-0 - Number of sweep shift (# 0-7)
// -- Sweep Time: (n*7.8ms)
// --
#define rNR10 0x10
#define rAUD1SWEEP rNR10
// --
// -- AUD1LEN/NR11 (0x11)
// -- Sound length/Wave pattern duty (R/W)
// --
// -- Bit 7-6 - Wave Pattern Duty (00:12.5% 01:25% 10:50% 11:75%)
// -- Bit 5-0 - Sound length data (# 0-63)
// --
#define rNR11 0x11
#define rAUD1LEN rNR11
// --
// -- AUD1ENV/NR12 (0x12)
// -- Envelope (R/W)
// --
// -- Bit 7-4 - Initial value of envelope
// -- Bit 3 - Envelope UP/DOWN
// -- 0: Decrease
// -- 1: Range of increase
// -- Bit 2-0 - Number of envelope sweep (# 0-7)
// --
#define rNR12 0x12
#define rAUD1ENV rNR12
// --
// -- AUD1LOW/NR13 (0x13)
// -- Frequency lo (W)
// --
#define rNR13 0x13
#define rAUD1LOW rNR13
// --
// -- AUD1HIGH/NR14 (0x14)
// -- Frequency hi (W)
// --
// -- Bit 7 - Initial (when set, sound restarts)
// -- Bit 6 - Counter/consecutive selection
// -- Bit 2-0 - Frequency's higher 3 bits
// --
#define rNR14 0x14
#define rAUD1HIGH rNR14
//***************************************************************************
//*
//* SoundChannel #2 registers
//*
//***************************************************************************
// --
// -- AUD2LEN/NR21 (0x16)
// -- Sound Length; Wave Pattern Duty (R/W)
// --
// -- see AUD1LEN for info
// --
#define rNR21 0x16
#define rAUD2LEN rNR21
// --
// -- AUD2ENV/NR22 (0x17)
// -- Envelope (R/W)
// --
// -- see AUD1ENV for info
// --
#define rNR22 0x17
#define rAUD2ENV rNR22
// --
// -- AUD2LOW/NR23 (0x18)
// -- Frequency lo (W)
// --
#define rNR23 0x18
#define rAUD2LOW rNR23
// --
// -- AUD2HIGH/NR24 (0x19)
// -- Frequency hi (W)
// --
// -- see AUD1HIGH for info
// --
#define rNR24 0x19
#define rAUD2HIGH rNR24
//***************************************************************************
//*
//* SoundChannel #3 registers
//*
//***************************************************************************
// --
// -- AUD3ENA/NR30 (0x1A)
// -- Sound on/off (R/W)
// --
// -- Bit 7 - Sound ON/OFF (1EQUON,0EQUOFF)
// --
#define rNR30 0x1A
#define rAUD3ENA rNR30
// --
// -- AUD3LEN/NR31 (0x1B)
// -- Sound length (R/W)
// --
// -- Bit 7-0 - Sound length
// --
#define rNR31 0x1B
#define rAUD3LEN rNR31
// --
// -- AUD3LEVEL/NR32 (0x1C)
// -- Select output level
// --
// -- Bit 6-5 - Select output level
// -- 00: 0/1 (mute)
// -- 01: 1/1
// -- 10: 1/2
// -- 11: 1/4
// --
#define rNR32 0x1C
#define rAUD3LEVEL rNR32
// --
// -- AUD3LOW/NR33 (0x1D)
// -- Frequency lo (W)
// --
// -- see AUD1LOW for info
// --
#define rNR33 0x1D
#define rAUD3LOW rNR33
// --
// -- AUD3HIGH/NR34 (0x1E)
// -- Frequency hi (W)
// --
// -- see AUD1HIGH for info
// --
#define rNR34 0x1E
#define rAUD3HIGH rNR34
// --
// -- AUD4LEN/NR41 (0x20)
// -- Sound length (R/W)
// --
// -- Bit 5-0 - Sound length data (# 0-63)
// --
#define rNR41 0x20
#define rAUD4LEN rNR41
// --
// -- AUD4ENV/NR42 (0x21)
// -- Envelope (R/W)
// --
// -- see AUD1ENV for info
// --
#define rNR42 0x21
#define rAUD4ENV rNR42
// --
// -- AUD4POLY/NR42 (0x22)
// -- Polynomial counter (R/W)
// --
// -- Bit 7-4 - Selection of the shift clock frequency of the (scf)
// -- polynomial counter (0000-1101)
// -- freqEQUdrf*1/2^scf (not sure)
// -- Bit 3 - Selection of the polynomial counter's step
// -- 0: 15 steps
// -- 1: 7 steps
// -- Bit 2-0 - Selection of the dividing ratio of frequencies (drf)
// -- 000: f/4 001: f/8 010: f/16 011: f/24
// -- 100: f/32 101: f/40 110: f/48 111: f/56 (fEQU4.194304 Mhz)
// --
#define rNR42_2 0x22
#define rAUD4POLY rNR42_2
// --
// -- AUD4GO/NR43 (0x23)
// -- (has wrong name and value (ff30) in Dr.Pan's doc!)
// --
// -- Bit 7 - Inital
// -- Bit 6 - Counter/consecutive selection
// --
#define rNR43 0x23
#define rAUD4GO rNR43 // silly name!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.