diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2017-06-21 16:16:17 +0200 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2017-06-21 16:16:17 +0200 |
commit | 9d923b5a00916478a84d21c431532e5d3065968c (patch) | |
tree | 88d706bc0ee1496791bb917c03fc10011b9d4777 /floppyMusic | |
parent | f9357256249657af2374e3c334b9180e63dc5a30 (diff) | |
download | avrFloppy-9d923b5a00916478a84d21c431532e5d3065968c.tar.gz |
Implemented MIDI interface
Diffstat (limited to 'floppyMusic')
-rw-r--r-- | floppyMusic/floppy.c | 10 | ||||
-rw-r--r-- | floppyMusic/floppy.h | 25 | ||||
-rw-r--r-- | floppyMusic/floppyMusic.cproj | 73 | ||||
-rw-r--r-- | floppyMusic/main.c | 26 | ||||
-rw-r--r-- | floppyMusic/midi.c | 124 | ||||
-rw-r--r-- | floppyMusic/midi.h | 37 | ||||
-rw-r--r-- | floppyMusic/uart.c | 45 | ||||
-rw-r--r-- | floppyMusic/uart.h | 30 |
8 files changed, 209 insertions, 161 deletions
diff --git a/floppyMusic/floppy.c b/floppyMusic/floppy.c index 6a12af6..b065302 100644 --- a/floppyMusic/floppy.c +++ b/floppyMusic/floppy.c @@ -15,11 +15,11 @@ ISR(TIMER0_OVF_vect) *fPORT = 0xff; //Deactivate all previously activated pins - for(uint8_t i = 0; i < 8; i++) + for(uint8_t i = 0; i < 8; i++) //Perform check of every channel { - if(floppy_nextrun[i] == timer_overflow_counter && floppy_frequencies[i] > 0) + if(floppy_nextrun[i] == timer_overflow_counter && floppy_frequencies[i] > 0) //check if pulse is due { - floppy_nextrun[i] += floppy_frequencies[i]; + floppy_nextrun[i] += floppy_frequencies[i]; //set next pulse floppy_pulse(i); } } @@ -27,7 +27,7 @@ ISR(TIMER0_OVF_vect) sei(); } -void floppy_setup(char *_pulse_port, char *_pulse_ddr, char *_direction_port, char *_direction_ddr) +void floppy_setup(unsigned char *_pulse_port, unsigned char *_pulse_ddr, unsigned char *_direction_port, unsigned char *_direction_ddr) { //Setup Ports fPORT = _pulse_port; @@ -89,6 +89,8 @@ void floppy_setup(char *_pulse_port, char *_pulse_ddr, char *_direction_port, ch uint8_t floppy_calc_freq(uint32_t _f_hz) { + + ///TODO Shift notes out of effective range of FDD into range if(_f_hz < 31) return 255; if(_f_hz > 7813) diff --git a/floppyMusic/floppy.h b/floppyMusic/floppy.h index cc069c0..b0a45cb 100644 --- a/floppyMusic/floppy.h +++ b/floppyMusic/floppy.h @@ -10,7 +10,7 @@ #define FLOPPY_H_ #ifndef F_CPU -#define F_CPU 16000000UL +#error F_CPU not defined for floppy.h #endif #include <avr/io.h> @@ -22,15 +22,32 @@ uint8_t floppy_frequencies[8]; uint8_t floppy_nextrun[8]; uint8_t floppy_head_return_counter[8]; -char *fPORT, *fDDR, *dPORT, *dDDR; //Ports for floppy and Direction of Heads - -void floppy_setup(char *_pulse_port, char *_pulse_ddr, char *_direction_port, char *_direction_ddr); +unsigned char *fPORT, *fDDR, *dPORT, *dDDR; //Ports for floppy and Direction of Heads +void floppy_setup(unsigned char *_pulse_port, unsigned char *_pulse_ddr, unsigned char *_direction_port, unsigned char *_direction_ddr); +/* +* *_pulse_port : port where stepper is connected, eg &PORTA +* *_pulse_ddr : its direction register, eg &DDRA +* *_direction_port : Port where direction pins are connected, eg &PORTB +* *_direction_ddr : its direction register, eg &DDRB +*/ void floppy_set_frequency(uint8_t _floppy_id, uint8_t _freq); +/* +* _floppy_id : [0-7] channel select +* _freq : [0-255] numerical value representing frequency. use floppy_calc_freq() to calculate from frequency in Hz +*/ void floppy_pulse(uint8_t _floppy_id); +/* +* pulses FDD, keeps track of when to apply head-reverse signal +* _floppy_id : [0-7] channel select +*/ uint8_t floppy_calc_freq(uint32_t _f_hz); +/* +* Converts frequency in Hz into value used by floppy_set_frequency() +* _f_hz : Frequency in Hz +*/ #endif /* FLOPPY_H_ */
\ No newline at end of file diff --git a/floppyMusic/floppyMusic.cproj b/floppyMusic/floppyMusic.cproj index 0ab48be..34cd8d5 100644 --- a/floppyMusic/floppyMusic.cproj +++ b/floppyMusic/floppyMusic.cproj @@ -82,39 +82,39 @@ <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <ToolchainSettings> <AvrGcc> - <avrgcc.common.Device>-mmcu=atmega32 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega32"</avrgcc.common.Device> - <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> - <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> - <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> - <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> - <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> - <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> - <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> - <avrgcc.compiler.symbols.DefSymbols> - <ListValues> - <Value>NDEBUG</Value> - </ListValues> - </avrgcc.compiler.symbols.DefSymbols> - <avrgcc.compiler.directories.IncludePaths> - <ListValues> - <Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include</Value> - </ListValues> - </avrgcc.compiler.directories.IncludePaths> - <avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level> - <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> - <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> - <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> - <avrgcc.linker.libraries.Libraries> - <ListValues> - <Value>libm</Value> - </ListValues> - </avrgcc.linker.libraries.Libraries> - <avrgcc.assembler.general.IncludePaths> - <ListValues> - <Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include</Value> - </ListValues> - </avrgcc.assembler.general.IncludePaths> -</AvrGcc> + <avrgcc.common.Device>-mmcu=atmega32 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\gcc\dev\atmega32"</avrgcc.common.Device> + <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> + <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> + <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> + <avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec> + <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> + <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> + <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> + <avrgcc.compiler.symbols.DefSymbols> + <ListValues> + <Value>NDEBUG</Value> + </ListValues> + </avrgcc.compiler.symbols.DefSymbols> + <avrgcc.compiler.directories.IncludePaths> + <ListValues> + <Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include</Value> + </ListValues> + </avrgcc.compiler.directories.IncludePaths> + <avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level> + <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> + <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> + <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> + <avrgcc.linker.libraries.Libraries> + <ListValues> + <Value>libm</Value> + </ListValues> + </avrgcc.linker.libraries.Libraries> + <avrgcc.assembler.general.IncludePaths> + <ListValues> + <Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.2.132\include</Value> + </ListValues> + </avrgcc.assembler.general.IncludePaths> + </AvrGcc> </ToolchainSettings> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> @@ -131,6 +131,7 @@ <avrgcc.compiler.symbols.DefSymbols> <ListValues> <Value>DEBUG</Value> + <Value>F_CPU=16000000UL</Value> </ListValues> </avrgcc.compiler.symbols.DefSymbols> <avrgcc.compiler.directories.IncludePaths> @@ -179,12 +180,6 @@ <Compile Include="music.h"> <SubType>compile</SubType> </Compile> - <Compile Include="uart.c"> - <SubType>compile</SubType> - </Compile> - <Compile Include="uart.h"> - <SubType>compile</SubType> - </Compile> </ItemGroup> <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" /> </Project>
\ No newline at end of file diff --git a/floppyMusic/main.c b/floppyMusic/main.c index 7583bc8..6256e97 100644 --- a/floppyMusic/main.c +++ b/floppyMusic/main.c @@ -5,28 +5,38 @@ * Author : Jonas */ - #ifndef F_CPU - #define F_CPU 16000000UL //CPU Running at 16MHz - #endif +#define _TEST_MODE #include <avr/io.h> #include "floppy.h" +#include "midi.h" + +#ifdef _TEST_MODE #include "music.h" -#include "uart.h" +#endif int main(void) { - uart_init(9600); floppy_setup(&PORTC, &DDRC, &PORTB, &DDRB); + + #ifdef _TEST_MODE //Play imperial March in test mode + DDRA = 0xff; - uart_send_string("Hallo\n"); - while (1) + for(;;) { play_imperial_march(); _delay_ms(2000); - uart_send_string("Hallo\n"); } + + #else //Normal MIDI mode + + midi_setup(); + + for(;;); + + #endif + } diff --git a/floppyMusic/midi.c b/floppyMusic/midi.c index ff70a95..ae99371 100644 --- a/floppyMusic/midi.c +++ b/floppyMusic/midi.c @@ -5,38 +5,126 @@ * Author: Jonas */ + /* + Octave|| Note Numbers + # || + || C | C# | D | D# | E | F | F# | G | G# | A | A# | B + ----------------------------------------------------------------------------- + 0 || 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 + 1 || 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 + 2 || 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 + 3 || 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 + 4 || 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 + 5 || 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 + 6 || 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 + 7 || 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 + 8 || 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 + 9 || 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 + 10 || 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | + */ + #include "midi.h" -void midi_setup() -{ - uart_init(9600); -} +extern const uint16_t midi_code_frequency_table[] = {8,9,9,10,10,11,12,12,13,14,15,15,16,17,18,19,21,22,23,25,26,28,29,31,33,35,37,39,41,44,46,49,52,55,58,62,65,69,73,78,82,87,93,98,104,110,117,123,131,139,147,156,165,175,185,196,208,220,233,247,262,277,294,311,330,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976,2093,2217,2349,2489,2637,2794,2960,3136,3322,3520,3729,3951,4186,4435,4699,4978,5274,5588,5920,6272}; -void midi_recieve(struct midi_command *_command) +ISR(USART_RXC_vect) { - if(!(UCSRB & (1<<RXEN))) //Return if UART reciever not enabled - return; - + cli(); char status, data1, data2; char command, channel, note, velocity; - status = uart_recieve(); - data1 = uart_recieve(); - data2 = uart_recieve(); + //read data from interface + status = midi_recieve(); + data1 = midi_recieve(); + data2 = midi_recieve(); - command = status & 0x0f; //Mask out last 4 bits + sei(); + + //split data + command = status & 0x0f; //Mask out last 4 bits channel = (status >> 4) & 0x0f; // Shift channel into first 4 bits; note = data1; velocity = data2; - _command->command = command; - _command->channel=channel; - _command->note = note; - _command->velocity = velocity; + switch(command) + { + case 0x08: //Note off + midi_update_note(note, 0); + break; + midi_update_note(note, 1); + case 0x09: //Note on + + break; + + case 0x0A: //Note Fade Out + //unused + break; + + case 0x0B: //Control Change + //unused + break; + + case 0x0C: //Channel Fade Out + //unused + break; + + case 0x0E: //Note Pitch change + //unused + break; + } + } -void midi_send(struct midi_command _command) +void midi_setup() { + midi_active_channels = 0x00; + + //UART init + unsigned int ubrr = (F_CPU / (16 * _MIDI_LINK_SPEED)) - 1; + + UBRRH = (unsigned char) (ubrr>>8) & 0xff; + UBRRL = (unsigned char) ubrr & 0xff; + + UCSRB = (1<<RXEN) | (1<<TXEN); + UCSRC = (1<<URSEL) | (1<<USBS) | (3<<UCSZ0); + + UCSRB |= (1<<RXCIE); //enable interrupt +} + + char midi_recieve() + { + while(!(UCSRA & (1<<RXC))); //Wait for data + + return UDR; + } + + void midi_update_note(uint16_t _note, uint8_t _status) + { + if(_status) //Note on + { + int i; + for(i = 0; i < 8; i++) //search for first free channel + if(!(midi_active_channels & (1<<i))) + break; + + midi_current_notes[i] = _note; //write current note to channel + midi_active_channels |= (1<<i); //set channel active + floppy_set_frequency(i, floppy_calc_freq(midi_code_frequency_table[_note]) ); //play note + } -}
\ No newline at end of file + else //Note off + { + int i; + for(i = 0; i < 8; i++) //search for active channel playing _note + { + if(midi_current_notes[i] == _note) + { + floppy_set_frequency(i, 0); //mute + midi_current_notes[i] = 0xff; //unset current, 0xff is outside MIDI standards + midi_active_channels &= ~(1<<i); //unset channel active + break; + } + } + } + } diff --git a/floppyMusic/midi.h b/floppyMusic/midi.h index f30f1c4..733fe05 100644 --- a/floppyMusic/midi.h +++ b/floppyMusic/midi.h @@ -5,30 +5,41 @@ * Author: Jonas */ +#ifndef F_CPU +#error F_CPU not defined for midi.h +#endif #ifndef MIDI_H_ #define MIDI_H_ -#define _MIDI_SEND 0 -#define _MIDI_RECIEVE 1 +#define _MIDI_LINK_SPEED 30000UL //Standard MIDI linkspeed is 30k baud -#include "uart.h" -struct midi_command -{ - char command; - char channel; - char note; - char velocity; -}; +#include <avr/interrupt.h> +#include <avr/io.h> -void midi_setup(); +#include "floppy.h" + +char midi_active_channels; +uint16_t midi_current_notes[8]; +const uint16_t midi_code_frequency_table[232]; -void midi_recieve(struct midi_command *_command); +void midi_setup(); +/* +* initializes UART communication and Interrupts +*/ -void midi_send(struct midi_command _command); +void midi_update_note(uint16_t _note, uint8_t _status); +/* +* _note : MIDI standard note # +* _status : 0=OFF >0=ON +*/ +char midi_recieve(); +/* +* reads UART recieve buffer +*/ #endif /* MIDI_H_ */
\ No newline at end of file diff --git a/floppyMusic/uart.c b/floppyMusic/uart.c deleted file mode 100644 index 3aac221..0000000 --- a/floppyMusic/uart.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * uart.c - * - * Created: 02.05.2017 20:48:26 - * Author: Jonas - */ - - #include "uart.h" - - void uart_init(unsigned int _baud) - { - unsigned int ubrr = (F_CPU / (16 * _baud)) - 1; - - UBRRH = (unsigned char)(ubrr>>8) & 0xff; - UBRRL = (unsigned char)ubrr & 0xff; - - UCSRB = (1<<RXEN)|(1<<TXEN); - UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); - } - - void uart_send(char _data) - { - while(!(UCSRA & (1<<UDRE))); //Wait for previous data to be sent - UDR = _data; - } - - void uart_send_string(char *_data) - { - char *data = _data; - - while(*data != '\0') - { - uart_send(*data); - data++; - } - } - - char uart_recieve() - { - while(!(UCSRA & (1<<RXC))); //Wait for data - - return UDR; - } - - diff --git a/floppyMusic/uart.h b/floppyMusic/uart.h deleted file mode 100644 index 1954357..0000000 --- a/floppyMusic/uart.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * uart.h - * - * Created: 02.05.2017 20:48:16 - * Author: Jonas - */ - - -#ifndef UART_H_ -#define UART_H_ - -#ifndef F_CPU -#define F_CPU 16000000UL //CPU Running at 16MHz -#endif - -#include <avr/io.h> - - -#define _GET_UBBR(BAUD) ( (F_CPU / 16 * BAUD) - 1) - -void uart_init(unsigned int _baud); - -void uart_send(char _data); - -void uart_send_string(char *_data); - -char uart_recieve(void); - - -#endif /* UART_H_ */
\ No newline at end of file |