Skip to content

Commit 95e2509

Browse files
author
Ken Rossato
committed
Initial commit
0 parents  commit 95e2509

File tree

17 files changed

+1526
-0
lines changed

17 files changed

+1526
-0
lines changed

Makefile

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
TARGET = chiptune
2+
3+
MCU = atmega328p
4+
F_CPU = 16000000UL
5+
BAUD = 31250UL
6+
7+
CC = avr-gcc
8+
OBJCOPY = avr-objcopy
9+
AVRSIZE = avr-size
10+
AVRDUDE = avrdude
11+
12+
AVRDUDE_FLAGS = -C avrisp -P /dev/ttyACM0 -b 19200
13+
14+
CSOURCES=$(wildcard *.c)
15+
SSOURCES=$(wildcard *.S)
16+
SOURCES=$(CSOURCES) $(SSOURCES)
17+
OBJECTS=$(CSOURCES:.c=.o) $(SSOURCES:.S=.o)
18+
HEADERS=$(wildcard *.h)
19+
20+
NOISE_SHIFT_REGISTERS = -ffixed-r2 -ffixed-r3
21+
22+
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I.
23+
24+
CFLAGS = -O2 -std=gnu99 -Wall -Wimplicit-function-declaration
25+
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
26+
CFLAGS += -ffunction-sections -fdata-sections
27+
CFLAGS += $(NOISE_SHIFT_REGISTERS)
28+
29+
LDFLAGS = -Wl,-Map,$(TARGET).map
30+
LDFLAGS += -Wl,--gc-sections
31+
32+
ARCH = -mmcu=$(MCU)
33+
34+
%.o: %.c $(HEADERS) Makefile
35+
$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH) -c -o $@ $<
36+
37+
.S.o: $(HEADERS) Makefile
38+
$(CC) $(CPPFLAGS) $(ARCH) -c -o $@ $<;
39+
40+
$(TARGET).elf: $(OBJECTS)
41+
$(CC) $(LDFLAGS) $(ARCH) $^ -o $@
42+
43+
%.hex: %.elf
44+
$(OBJCOPY) -j .text -j .data -O ihex $< $@
45+
46+
.PHONY: all size clean flash
47+
48+
all: $(TARGET).hex
49+
50+
size: $(TARGET).elf
51+
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
52+
53+
clean:
54+
rm -f *.elf *.hex *.o
55+
56+
flash: $(TARGET).hex
57+
$(AVRDUDE) -p $(MCU) $(AVRDUDE_FLAGS) -U flash:w:$<

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Arduino chiptune synthesizer
2+
============================
3+
4+
This is my 8-bit synthesizer project for the Arduino UNO. It'll probably work with minimal modification on any 8-bit AVR with at least 2k of RAM at 16MHz. I compile with avr-gcc and upload with a SPI programmer, but it doesn't take up a ton of flash space so you should in theory be able to keep Optiboot if you tweak the makefile.
5+
6+
Features:
7+
* 8 simultaneous independent channels at 44.1kHz
8+
* Input over MIDI and 7x8 key matrix with separate assignable voices
9+
* Square wave, triangle wave, and noise
10+
* Square wave duty cycle adjustable to 50%, 25%, or 12.5%
11+
* Attack-decay-sustain envelopes
12+
* Vibrato, arpeggio, and echo effects
13+
* Preprogrammed percussion using sliding pitches and shaped noise
14+
* "Burst note" setting that plays hi-hat with notes
15+
* 8-beat record and playback (work in progress)
16+
17+
This project is inspired by Linus Åkesson's incredible [Chipophone](http://linusakesson.net/chipophone/index.php). My source code is written from scratch and is hopefully a little more reusable (I aim for MIDI and Arduino compatibility). It uses the same MCP49x1 DAC for output and can be wired up with a few external components:
18+
19+
For the audio output:
20+
21+
* MCP4921 DAC (can substitute 4911 or 4901)
22+
* 470uF electrolytic capacitor to block DC on the output
23+
* 100nF electorlytic capacitor to filter out noise on the volume knob
24+
* 10kOhm linear potentiometer to select the Vref level
25+
* 56kOhm volume limiting resistor
26+
* Audio jack
27+
28+
For MIDI input:
29+
30+
* 6N138 optoisolator
31+
* 1N4148 diode
32+
* 220 and 470 ohm resistors
33+
* MIDI socket
34+
35+
For key-matrix input:
36+
37+
* 74HC164 or 74HC595 shift register

constants.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef CONSTANTS_H
2+
#define CONSTANTS_H
3+
4+
#include <avr/io.h>
5+
6+
#define NO_VALUE 255
7+
8+
#define DRUM_MACHINE_1 252
9+
#define DRUM_MACHINE_2 253
10+
#define DRUM_HAT_NOTE 254
11+
#define TOTAL_NOTES 256
12+
13+
#define NBANKS 3
14+
#define BANK_KEYS 0
15+
#define BANK_MIDI 1
16+
#define BANK_CPU 2
17+
18+
#define MODE_BURST_BIT 0
19+
#define MODE_ARPEGGIO_BIT 1
20+
#define MODE_VIBRATO_BIT 2
21+
#define MODE_ECHO_BIT 3
22+
#define MODE_PEDAL_BIT 4
23+
24+
#define MODE_NONE 0
25+
#define MODE_BURST _BV(MODE_BURST_BIT)
26+
#define MODE_ARPEGGIO _BV(MODE_ARPEGGIO_BIT)
27+
#define MODE_VIBRATO _BV(MODE_VIBRATO_BIT)
28+
#define MODE_ECHO _BV(MODE_ECHO_BIT)
29+
#define MODE_PEDAL _BV(MODE_PEDAL_BIT)
30+
31+
#define NCHANNELS 8
32+
33+
#define SHAPE_NOISE_BIT 0
34+
#define SHAPE_PCM_BIT 1
35+
#define SHAPE_SQUARE_BIT 2
36+
#define SHAPE_TRIANGLE_BIT 3
37+
#define SHAPE_DRUM_BIT 7
38+
39+
#define SHAPE_NONE 0
40+
#define SHAPE_NOISE _BV(SHAPE_NOISE_BIT)
41+
#define SHAPE_PCM _BV(SHAPE_PCM_BIT)
42+
#define SHAPE_SQUARE _BV(SHAPE_SQUARE_BIT)
43+
#define SHAPE_TRIANGLE _BV(SHAPE_TRIANGLE_BIT)
44+
#define SHAPE_DRUM _BV(SHAPE_DRUM_BIT)
45+
46+
#define DAC_BUF 6
47+
#define DAC_GA 5
48+
#define DAC_SHDN 4
49+
#define DAC_DEFAULT (_BV(DAC_GA) | _BV(DAC_SHDN))
50+
51+
#define NINSTRUMENTS 4
52+
#define INSTRUMENT_DEFAULT 0
53+
#define INSTRUMENT_HAT 1
54+
#define INSTRUMENT_CYMBOL 2
55+
#define INSTRUMENT_SNARE 3
56+
57+
#endif

drum.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/* drum.c -
2+
Drum definitions and playback queue
3+
4+
(c) 2016 Ken Rossato
5+
*/
6+
7+
#include "main.h"
8+
#include "drum.h"
9+
10+
uint8_t drum_machine_page = 0;
11+
const struct drum_t *drum_machine[2] = {&drums[0], &drums[0]};
12+
13+
const struct drum_t drums[NDRUMS] = {
14+
[DRUM_HAT] = {
15+
.freq = 0xFFFF,
16+
.slide = 0,
17+
.shape = SHAPE_NOISE,
18+
.instrument = &instruments[INSTRUMENT_HAT],
19+
.duration = 5
20+
},
21+
[DRUM_TOM_HI] = {
22+
.freq = 0x030A, // C4
23+
.slide = -0x30,
24+
.shape = SHAPE_TRIANGLE,
25+
.instrument = &instruments[INSTRUMENT_DEFAULT],
26+
.duration = 8,
27+
},
28+
[DRUM_TOM] = {
29+
.freq = 0x028E, // A3
30+
.slide = -0x30,
31+
.shape = SHAPE_TRIANGLE,
32+
.instrument = &instruments[INSTRUMENT_DEFAULT],
33+
.duration = 8,
34+
},
35+
[DRUM_TOM_LO] = {
36+
.freq = 0x0247, // G3
37+
.slide = -0x30,
38+
.shape = SHAPE_TRIANGLE,
39+
.instrument = &instruments[INSTRUMENT_DEFAULT],
40+
.duration = 8,
41+
},
42+
[DRUM_CYMBOL] = {
43+
.freq = 0x8000,
44+
.slide = 0,
45+
.shape = SHAPE_NOISE,
46+
.instrument = &instruments[INSTRUMENT_CYMBOL],
47+
.duration = 15
48+
},
49+
[DRUM_SNARE_NOISE] = {
50+
.freq = 0x1800,
51+
.slide = 0x1733,
52+
.shape = SHAPE_NOISE,
53+
.instrument = &instruments[INSTRUMENT_SNARE],
54+
.duration = 15
55+
},
56+
[DRUM_SNARE_TONE] = {
57+
.freq = 0x030A, // C4
58+
.slide = -0x20,
59+
.shape = SHAPE_TRIANGLE,
60+
.instrument = &instruments[INSTRUMENT_DEFAULT],
61+
.duration = 15
62+
},
63+
[DRUM_SNARE_LO_TONE] = {
64+
.freq = 0x0269, // G#3
65+
.slide = -0x14,
66+
.shape = SHAPE_TRIANGLE,
67+
.instrument = &instruments[INSTRUMENT_DEFAULT],
68+
.duration = 15
69+
},
70+
[DRUM_KICK] = {
71+
.freq = 0x15B, // A#2
72+
.slide = -0x10,
73+
.shape = SHAPE_TRIANGLE,
74+
.instrument = &instruments[INSTRUMENT_DEFAULT],
75+
.duration = 15
76+
},
77+
[DRUM_KICK_SQUARE] = {
78+
.freq = 0x15B,
79+
.slide = -0x10,
80+
.shape = SHAPE_SQUARE,
81+
.instrument = &instruments[INSTRUMENT_CYMBOL],
82+
.duration = 15
83+
}
84+
};
85+
86+
uint8_t allocate_drum_note(uint8_t drum) {
87+
drum_machine_page = (drum_machine_page + 1) & 2;
88+
drum_machine[drum_machine_page] = &drums[drum];
89+
return DRUM_MACHINE_1 + drum_machine_page;
90+
}

drum.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* drum.h -
2+
Drum definitions and playback queue
3+
4+
(c) 2016 Ken Rossato
5+
*/
6+
7+
#ifndef DRUM_H
8+
#define DRUM_H
9+
10+
#include "main.h"
11+
12+
#define DRUM_HAT 0
13+
#define DRUM_TOM_HI 1
14+
#define DRUM_TOM 2
15+
#define DRUM_TOM_LO 3
16+
#define DRUM_CYMBOL 4
17+
#define DRUM_SNARE_NOISE 5
18+
#define DRUM_SNARE_TONE 6
19+
#define DRUM_SNARE_LO_TONE 7
20+
#define DRUM_KICK 8
21+
#define DRUM_KICK_SQUARE 9
22+
#define NDRUMS 10
23+
24+
struct drum_t {
25+
uint16_t freq;
26+
int16_t slide;
27+
uint8_t shape;
28+
const struct instrument_t *instrument;
29+
uint8_t duration;
30+
};
31+
extern const struct drum_t drums[];
32+
extern const struct drum_t *drum_machine[];
33+
34+
uint8_t allocate_drum_note(uint8_t drum);
35+
36+
#endif

0 commit comments

Comments
 (0)