...
 
Commits (4)
......@@ -5,3 +5,4 @@
*.bin
*.map
*.elf
midi-test
PRG = crowbx
OBJ = crowbx.o midi.o dac.o voice.o
OBJ = crowbx.o midi.o dac.o voice.o uart.o
MCU_TARGET = atmega328p
#MCU_TARGET = at90s2313
#MCU_TARGET = at90s2333
......@@ -75,6 +75,12 @@ all: $(PRG).elf lst text
$(PRG).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
TESTCC = gcc -Wall -std=c99
test:
$(TESTCC) -o midi-test midi-test.c midi.c
./midi-test
clean:
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
......
#include <stdio.h>
#include <assert.h>
#include "midi.h"
#include "midi-test.h"
void
test_init(void)
{
desc("test status_init()");
status_init();
assert_status(MIDI_NUM_STATUSES, 0, 0);
}
void
test_note_on(void)
{
desc("test note on handling");
status_init();
assert_status(MIDI_NUM_STATUSES, 0, 0);
// fresh note on
midi_parse(0x90);
midi_parse(0x60);
assert_status(MIDI_NOTE_ON, 0, 0);
midi_parse(0x64);
assert_status(MIDI_NOTE_ON, 1, 0x6064);
// running status
midi_parse(0x10);
assert_status(MIDI_NOTE_ON, 0, 0);
midi_parse(0x70);
assert_status(MIDI_NOTE_ON, 1, 0x1070);
// real time garbage
midi_parse(0xf8);
assert_status(MIDI_NOTE_ON, 1, 0x1070);
midi_parse(0x11);
midi_parse(0xf8);
midi_parse(0x25);
assert_status(MIDI_NOTE_ON, 1, 0x1125);
// velocity 0
midi_parse(0x17);
midi_parse(0);
assert_status(MIDI_NOTE_ON, 1, 0x1700);
// new status byte
midi_parse(0x90);
midi_parse(0x60);
midi_parse(0x64);
assert_status(MIDI_NOTE_ON, 1, 0x6064);
// end running status
midi_parse(0xa0); // poly pressure
assert_status(MIDI_NUM_STATUSES, 0, 0);
// unexpected status byte
midi_parse(0x90);
midi_parse(0x60);
midi_parse(0x90); // should reset data
assert_status(MIDI_NOTE_ON, 0, 0);
midi_parse(0x64);
assert_status(MIDI_NOTE_ON, 0, 0);
midi_parse(0x70);
assert_status(MIDI_NOTE_ON, 1, 0x6470);
}
void
test_note_off(void)
{
desc("test note off handling");
status_init();
assert_status(MIDI_NUM_STATUSES, 0, 0);
midi_parse(0x80);
assert_status(MIDI_NOTE_OFF, 0, 0);
midi_parse(0x12);
midi_parse(0x34);
assert_status(MIDI_NOTE_OFF, 1, 0x1234);
midi_parse(0x56);
midi_parse(0x78);
assert_status(MIDI_NOTE_OFF, 1, 0x5678);
midi_parse(0x80);
midi_parse(0x12);
midi_parse(0);
assert_status(MIDI_NOTE_OFF, 1, 0x1200);
}
int
main(int argc, char** argv)
{
test_init();
test_note_on();
test_note_off();
}
#ifndef midi_test_h
#define midi_test_h
// Access to midi.c internals
void status_init(void);
void midi_parse(uint8_t);
uint8_t midi_available(void);
#define desc(s) printf("TEST: %s\n", s)
#define assert_status(status, avail, data) assert(midi_status() == status); \
assert(!midi_available() == !avail); \
if (avail) assert(midi_data() == data)
// Fake uart functions to let midi.c compile
void uart_init(void) { }
uint16_t uart_read(void) { return 0; }
#endif
......@@ -7,9 +7,9 @@ UART I/O and MIDI parsing.
*/
#include "midi.h"
#include <avr/io.h>
#include "uart.h"
static uint8_t midi_channel;
uint8_t midi_channel;
void
midi_set_channel(uint8_t channel)
......@@ -19,7 +19,7 @@ midi_set_channel(uint8_t channel)
uint8_t status;
uint16_t data;
static uint8_t parsed_len;
uint8_t parsed_len;
const uint8_t statuses[MIDI_NUM_STATUSES] = {
0b1001, // note on
......@@ -74,6 +74,7 @@ midi_parse(uint8_t midi_byte)
for (uint8_t i = 0; i < MIDI_NUM_STATUSES; i++) {
if (midi_byte == ((statuses[i] << 4) | midi_channel)) {
status = i;
clear_data();
return;
}
}
......@@ -105,37 +106,28 @@ midi_parse(uint8_t midi_byte)
}
void
midi_init()
status_init(void)
{
UBRR0H = 0;
UBRR0L = 31;
UCSR0B = _BV(RXEN0);
// Enable pull-up resistor on RX pin
PORTD |= _BV(PORTD0);
clear_data();
reset_status();
}
void
midi_init()
{
uart_init();
status_init();
}
uint8_t
midi_read(void)
{
uint8_t uart_status = UCSR0A;
if (!(uart_status & _BV(RXC0))) {
// No UART data available
return 0;
}
// Read data to clear all status bits
uint8_t uart_data = UDR0;
if (uart_status & (_BV(FE0) | _BV(DOR0) | _BV(UPE0))) {
// There was a UART error
uint16_t uart_data = uart_read();
if (uart_data >> 8) {
// uart error
return 0;
}
midi_parse(uart_data);
midi_parse(uart_data & 0xff);
return midi_available();
}
#include <avr/io.h>
#include "uart.h"
void
uart_init(void)
{
UBRR0H = 0;
UBRR0L = 31;
UCSR0B = _BV(RXEN0);
// Enable pull-up resistor on RX pin
PORTD |= _BV(PORTD0);
}
#define UART_ERROR (1<<8)
uint16_t
uart_read(void)
{
uint8_t uart_status = UCSR0A;
if (!(uart_status & _BV(RXC0))) {
// No UART data available
return UART_ERROR;
}
// Read data to clear all status bits
uint8_t uart_data = UDR0;
if (uart_status & (_BV(FE0) | _BV(DOR0) | _BV(UPE0))) {
// There was a UART error
return UART_ERROR;
}
return uart_data;
}
\ No newline at end of file
#ifndef uart_h
#define uart_h
uint16_t uart_read(void);
void uart_init(void);
#endif