Commit 3b3ebc1a authored by Jacob Vosmaer's avatar Jacob Vosmaer

Move dac stuff into dac.c

parent 7435ffed
PRG = crowbx
OBJ = crowbx.o midi.o
OBJ = crowbx.o midi.o dac.o
MCU_TARGET = atmega328p
#MCU_TARGET = at90s2313
#MCU_TARGET = at90s2333
......
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include "midi.h"
#include "voices.h"
const uint8_t dac_chan[NUM_VOICES] = {2, 3, 4, 5};
// Offset to get a consistent "zero" on each CV output
const uint16_t dac_offset[NUM_VOICES] = {
57,
48,
50,
55,
};
// This number corresponds to a 1V increase at the respective CV output.
const uint16_t dac_scale[NUM_VOICES] = {
8382,
8382,
8383,
8384,
};
// This tuning is chosen to be 'good enough' for the 8382-8384 scale range above
const uint16_t dac_semitones[12] = {
0,
699,
1397,
2096,
2794,
3493,
4192,
4890,
5589,
6287,
6986,
7684,
};
uint8_t
spi_io(uint8_t data)
{
SPDR = data;
loop_until_bit_is_set(SPSR, SPIF);
return SPDR;
}
#define DAC_SYNC PORTB1
#define MOSI PORTB3
#define MISO PORTB4
#define SCK PORTB5
#define SS PORTB2
void
send_dac(uint8_t command, uint16_t data)
{
PORTB &= ~_BV(DAC_SYNC);
spi_io(command);
spi_io(data >> 8);
spi_io(data & 0xff);
PORTB |= _BV(DAC_SYNC);
}
void
spi_init(void)
{
// slave select, sck, mosi all as output
DDRB |= _BV(SS) | _BV(MOSI) | _BV(SCK);
PORTB |= _BV(MISO); // MISO pull-up to save power
// spi enable
SPCR |= _BV(SPE) | _BV(MSTR) | _BV(CPOL);
SPSR |= _BV(SPI2X);
}
void
dac_init(void)
{
DDRB |= _BV(DAC_SYNC);
spi_init();
// dac sync high for power saving
PORTB |= _BV(DAC_SYNC);
_delay_ms(1); // let dac boot up
send_dac(0b01000000, 0b1111000000001111); // power down dacs 0, 1, 6, 7
}
#define DAC_MAX 65535
#define MIDI_LOWEST 24
void
dac_set_note(uint8_t voice, uint8_t note)
{
if (voice >= NUM_VOICES) {
return;
}
// Don't go lower than "C0"
if (note < MIDI_LOWEST) {
note = MIDI_LOWEST;
}
if (note > 127) {
note = 127;
}
uint8_t octave = (note - MIDI_LOWEST) / 12;
if (octave > 7) {
return;
}
uint16_t data = dac_offset[voice] + octave * dac_scale[voice];
uint16_t semi_offset = dac_semitones[(note - MIDI_LOWEST) % 12];
if ((DAC_MAX - data) < semi_offset) {
data = DAC_MAX;
} else {
data += semi_offset;
}
send_dac(0b00110000 | dac_chan[voice], data);
}
#include "dac.h"
int
main(void)
......
#include <avr/io.h>
#include <util/delay.h>
#include "dac.h"
#include "voices.h"
const uint8_t dac_chan[NUM_VOICES] = {2, 3, 4, 5};
// Offset to get a consistent "zero" on each CV output
const uint16_t dac_offset[NUM_VOICES] = {
57,
48,
50,
55,
};
// This number corresponds to a 1V increase at the respective CV output.
const uint16_t dac_scale[NUM_VOICES] = {
8382,
8382,
8383,
8384,
};
// This tuning is chosen to be 'good enough' for the 8382-8384 scale range above
const uint16_t dac_semitones[12] = {
0,
699,
1397,
2096,
2794,
3493,
4192,
4890,
5589,
6287,
6986,
7684,
};
uint8_t
spi_io(uint8_t data)
{
SPDR = data;
loop_until_bit_is_set(SPSR, SPIF);
return SPDR;
}
#define DAC_SYNC PORTB1
#define MOSI PORTB3
#define MISO PORTB4
#define SCK PORTB5
#define SS PORTB2
void
send_dac(uint8_t command, uint16_t data)
{
PORTB &= ~_BV(DAC_SYNC);
spi_io(command);
spi_io(data >> 8);
spi_io(data & 0xff);
PORTB |= _BV(DAC_SYNC);
}
void
spi_init(void)
{
// slave select, sck, mosi all as output
DDRB |= _BV(SS) | _BV(MOSI) | _BV(SCK);
PORTB |= _BV(MISO); // MISO pull-up to save power
// spi enable
SPCR |= _BV(SPE) | _BV(MSTR) | _BV(CPOL);
SPSR |= _BV(SPI2X);
}
void
dac_init(void)
{
DDRB |= _BV(DAC_SYNC);
spi_init();
// dac sync high for power saving
PORTB |= _BV(DAC_SYNC);
_delay_ms(1); // let dac boot up
send_dac(0b01000000, 0b1111000000001111); // power down dacs 0, 1, 6, 7
}
#define DAC_MAX 65535
#define MIDI_LOWEST 24
void
dac_set_note(uint8_t voice, uint8_t note)
{
if (voice >= NUM_VOICES) {
return;
}
// Don't go lower than "C0"
if (note < MIDI_LOWEST) {
note = MIDI_LOWEST;
}
if (note > 127) {
note = 127;
}
uint8_t octave = (note - MIDI_LOWEST) / 12;
if (octave > 7) {
return;
}
uint16_t data = dac_offset[voice] + octave * dac_scale[voice];
uint16_t semi_offset = dac_semitones[(note - MIDI_LOWEST) % 12];
if ((DAC_MAX - data) < semi_offset) {
data = DAC_MAX;
} else {
data += semi_offset;
}
send_dac(0b00110000 | dac_chan[voice], data);
}
#ifndef dac_h
#define dac_h
void dac_set_note(uint8_t voice, uint8_t note);
void dac_init(void);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment