Skip to content

Instantly share code, notes, and snippets.

@pepijndevos
Last active December 25, 2018 12:42
Show Gist options
  • Save pepijndevos/83e5a96435a48966cdf88f4c325ac76b to your computer and use it in GitHub Desktop.
Save pepijndevos/83e5a96435a48966cdf88f4c325ac76b to your computer and use it in GitHub Desktop.
#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