mididec.h、mididec.c
/*************************************************/ /* mididec.h : MIDI decoder */ /* for ATtiny10 */ /* */ /* 2012/01/16 : Created by pcm1723 */ /*************************************************/ #ifndef _MIDIDEC_H_ #define _MIDIDEC_H_ #include <inttypes.h> #include <stdlib.h> #include <string.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> // MIDI receive channel ( 0 origin ) #define MIDI_rcv_ch (0) typedef union tag_u16_u8_t { uint16_t u16; uint8_t u8[2]; } u16_u8_t; typedef struct { uint8_t on_cnt; // key on count int16_t gate_que; #if (0) uint8_t gate; // key on/off #endif } unit_prop_t, *unit_prop_p; typedef struct { uint8_t MD_note; // MIDI note number (0..127) uint8_t MD_bend[2]; // MIDI pitch bend uint8_t MD_bend_range; // MIDI RPN#1 pitch bend range (1..127) uint8_t MD_RPN_MLB; // MIDI RPN MSB and LSB in a byte #if (0) uint8_t MD_progno; // MIDI program number (0..127) uint8_t MD_modulation; // MIDI CC#1 modulation (0..127) uint8_t MD_volume; // MIDI CC#7 ch volume (0..127) uint8_t MD_expression; // MIDI CC#11 expression (0..127) uint8_t MD_dent_MSB; // MIDI CC#6 data entry MSB (0..127) uint8_t MD_dent_LSB; // MIDI CC#38 data entry LSB (0..127) int16_t MD_RPN_ML; // MIDI RPN MSB and LSB (0x0000..0x7f7f) int16_t bend_f; // pitch bend value b15..b8:int, b7..b0:frac #endif } ch_prop_t, *ch_prop_p; extern ch_prop_t ch_prop[1]; extern unit_prop_t unit_prop[1]; extern void mididec(uint8_t data); extern int8_t md_data_byte( void ); extern int8_t md_cc_func(/* ch_prop_t *c_p */); extern uint8_t MD_data; extern uint8_t MD_ch; extern uint8_t MD_2nd; extern uint8_t MD_3rd; extern uint8_t MS_run_stat; extern int8_t MD_bcnt; //extern uint8_t sysex_cnt; //extern uint8_t MIDI_rcv_ch; // generator polynomial for CRC-8 // g(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1 #define CRC8_GX (0xD5) // CRC result for GM reset (excluding 0xF0 and 0xF7) // GM System ON = (0xF7) 0x7E 0x7F 0x09 0x01 (0xF7) #define GM_RESET_CRC (0xF0) #endif
/*************************************************/ /* mididec.c : MIDI decoder */ /* for ATtiny10 */ /* */ /* 2012/01/16 : Created by pcm1723 */ /*************************************************/ #include "mididec.h" #include "midifunc.h" uint8_t MD_data; uint8_t MD_ch; uint8_t MD_2nd; uint8_t MD_3rd; uint8_t MS_run_stat; int8_t MD_bcnt; //uint8_t sysex_cnt; //uint8_t MIDI_rcv_ch; ch_prop_t ch_prop[1]; unit_prop_t unit_prop[1]; #if (0) uint8_t crc_sr; static inline void update_crc8(uint8_t d) { uint8_t i; crc_sr ^= d; for (i = 0; i < 8; i++) { // for each bit if (0x80 & crc_sr) { // feedback crc_sr <<= 1; crc_sr ^= CRC8_GX; // polynomial pattern } else { // shift only crc_sr <<= 1; } // if (0x80 & crc_sr) ... } // for (i = ... } // void update_crc8() #endif /* MIDI Control Change and mode message (status byte == 0xBn) */ int8_t md_cc_func(/* ch_prop_t *c_p */) { // int i; switch (MD_2nd) { // switch by control number #if (0) case 0x01 : // MODULATION (1) c_p->MD_modulation = MD_3rd; break; case 0x07 : // VOLUME (7) c_p->MD_volume = MD_3rd; calc_vol_exp(c_p); break; case 0x0a : // PAN (10) c_p->MD_pan = MD_3rd; break; case 0x0b : // EXPRESSION (11) c_p->MD_expression = MD_3rd; calc_vol_exp(c_p); break; case 0x5b : // REVERB SEND LEVEL (91) c_p->MD_rev_send = MD_3rd; break; case 0x7e : // MONO MODE ON (126) case 0x7f : // POLY MODE ON (127) if (0x7e == MD_2nd) c_p->MD_legato = 127; // set legato if mono mode else c_p->MD_legato = 0; // set non-legato if poly mode all_note_off(c_p); /* demoflag = 0; */ break; #endif case 0x78 : // ALL SOUND OFF (120) case 0x7a : // LOCAL ON/OFF (122) case 0x7b : // ALL NOTE OFF (123) case 0x7c : // OMNI MODE OFF (124) case 0x7d : // OMNI MODE ON (125) all_note_off(/* c_p */); /* demoflag = 0; */ break; #if (0) case 0x79 : // RESET ALL CONTROLLERS (121) /* reset_all_controllers(c_p); demoflag = 0; */ break; #endif #if (1) case 0x06 : // DATA ENTRY MSB (6) if (0x00 == ch_prop[0].MD_RPN_MLB) { // RPN#0000 // Pitch bend sensitibity ch_prop[0].MD_bend_range = MD_3rd; return(1); } // if // ch_prop[0].MD_dent_MSB = MD_3rd; // decode_rpn (c_p, c_p->MD_RPN_ML, 0x100); // for MSB // decode_nrpn(c_p, c_p->MD_NRPN_ML, 0x100); // for MSB break; #endif #if (0) case 0x26 : // DATA ENTRY LSB (38) c_p->MD_dent_LSB = MD_3rd; // decode_rpn (c_p, c_p->MD_RPN_ML, 0); // for LSB // decode_nrpn(c_p, c_p->MD_NRPN_ML, 0); // for LSB break; case 0x60 : // DATA INCREMENT (96) /* decode_rpn (c_p, c_p->MD_RPN_ML, 1); // for data increment */ break; case 0x61 : // DATA DECREMENT (97) /* decode_rpn (c_p, c_p->MD_RPN_ML, -1); // for data decremant */ break; #endif case 0x62 : // NRPN LSB (98) // c_p->MD_NRPN_ML = MD_3rd | (0x7f00 & c_p->MD_NRPN_ML); ch_prop[0].MD_RPN_MLB = 0x7f; // cancel RPN break; case 0x63 : // NRPN MSB (99) // c_p->MD_NRPN_ML = (MD_3rd <<8) | (0x7f & c_p->MD_NRPN_ML); ch_prop[0].MD_RPN_MLB = 0x7f; // cancel RPN break; case 0x64 : // RPN LSB (100) ch_prop[0].MD_RPN_MLB = (0x0f & MD_3rd) | (0xf0 & ch_prop[0].MD_RPN_MLB); // c_p->MD_NRPN_ML = 0x7f7f; // cancel NRPN break; case 0x65 : // RPN MSB (101) ch_prop[0].MD_RPN_MLB = ((0x0f & MD_3rd) << 4) | (0x0f & ch_prop[0].MD_RPN_MLB); // c_p->MD_NRPN_ML = 0x7f7f; // cancel NRPN break; #if (0) case 0x40 : // HOLD1/DAMPER (64) case 0x42 : // SOSTENUTO (66) case 0x43 : // SOFT (67) // pedal_sw(c_p, MD_2nd, MD_3rd); break; case 0x44 : // LEGATO SW (68) // c_p->MD_legato = MD_3rd; break; case 0x05 : // PORTAMENTO TIME (5) /* c_p->MD_porta_time = MD_3rd; calc_porta_time(c_p, MD_3rd); */ break; case 0x41 : // PORTAMENT ON/OFF (65) // c_p->MD_porta_sw = MD_3rd; break; case 0x54 : // PORTAMENT CONTROL (84) // c_p->MD_porta_src = MD_3rd; break; case 0x47 : // TIMBRE/HARMONIC CONTENT (71) // c_p->MD_timbre = MD_3rd - 0x40; break; case 0x4a : // BRIGHTNESS (74) // c_p->MD_brightness = MD_3rd - 0x40; break; case 0x48 : // ENVELOPE RELEASE (72) case 0x49 : // ENVELOPE ATTACK (73) case 0x4b : // ENVELOPE DECAY (75) // edit_voice(c_p, MD_2nd, MD_3rd); break; case 0x4c : // VIBRATO RATE (76) /* c_p->MD_vib_rate = MD_3rd - 0x40; calc_vibrato(c_p); */ break; case 0x4d : // VIBRATO DEPTH (77) /* c_p->MD_vib_depth = MD_3rd - 0x40; calc_vibrato(c_p); */ break; case 0x4e : // VIBRATO DELAY (78) /* c_p->MD_vib_delay = MD_3rd - 0x40; calc_vibrato(c_p); */ break; #endif default: break; } // switch (MD_2nd) return(0); } // int8_t md_cc_func() /* process data byte part of MIDI message */ int8_t md_data_byte(void) { uint8_t mrs; // masked MIDI running status if (0 > MD_bcnt) { #if (0) update_crc8(MD_data); #endif return(0); // MD_bcnt is negative? exit if so } // if (0 > MD_bcnt) { ... #if (0) if (0 < sysex_cnt) { // SysEx sysex_cnt++; } // if (0 < sysex_cnt) ... else #endif { // other message if (0 == MD_bcnt) { // status omitted, default to running status MD_bcnt++; // modify byte count and fall into MD_bcnt==1 } if (1 == MD_bcnt) { // 2nd byte of the message MD_2nd = MD_data; // note number mrs = (0xf0 & MS_run_stat); // check for 2-byte message if (0xc0 == mrs) { // Program Change if (MIDI_rcv_ch == MD_ch) { // supported channel #if (0) ch_prop_t *c_p = &(ch_prop[0]); c_p->MD_progno = MD_2nd; /* setup_voice(c_p, MD_2nd); #ifdef LCD mon_pc_disp(c_p, MD_2nd); #endif */ #endif } // if (MIDI_rcv_ch == MD_ch) MD_bcnt = 0; // wait for status byte } else if (0xd0 == mrs) { // Channel key pressure if (MIDI_rcv_ch == MD_ch) { // supported channel #if (0) ch_prop_t *c_p = &(ch_prop[0]); c_p->MD_modulation = MD_2nd; // route to modulation //#ifdef LCD // mon_cc_bend_disp(c_p, 'A', MD_2nd, -1); //#endif #endif } // if (MIDI_rcv_ch == MD_ch) MD_bcnt = 0; // wait for status byte } else { if (0xf1 == MS_run_stat) { // MTC quater frame MD_bcnt = 0; // ignore, wait for next status } else if (0xf3 == MS_run_stat) { // Song select // seq_songsel(MD_2nd); // MD_bcnt = 0; // wait for next status } else { // other 3-byte message (0x8n, 0x9n, 0xAn, 0xBn, 0xEn) MD_bcnt++; // wait for verocity } // else } // else } else if (2 == MD_bcnt) { // 3rd byte of the message MD_bcnt = 0; // wait for next MIDI message if (MIDI_rcv_ch == MD_ch) { // supported channel // ch_prop_t *c_p = &(ch_prop[0]); MD_3rd = MD_data; // verocity mrs = (0xF0 & MS_run_stat); if (0x90 == mrs) { // MIDI NOTE-ON message if (0 == MD_3rd) { // (vel == 0) stands for NOTE-OFF midi_note_off(/* c_p, */ MD_2nd); } // if (0 == MD_3rd) else { // NOTE-ON with velocity midi_note_on(/* c_p, */ MD_2nd, MD_3rd); } // else } // if (0x90 == else if (0x80 == mrs) { // NOTE-OFF message midi_note_off(/* c_p, */ MD_2nd); } // else if (0x80 == else if (0xb0 == mrs) { // CONTROL-CHANGE return(1); // md_cc_func(/* c_p */); /* #ifdef LCD mon_cc_bend_disp(c_p, 'C', MD_2nd, MD_3rd); #endif */ } // else if (0xb0 == else if (0xe0 == mrs) { // PITCH BEND message #if (1) // int16_t b; // vendor linear value // b = ((((int16_t)MD_3rd) << 7) | MD_2nd) - 0x2000; ch_prop[0].MD_bend[1] = (MD_3rd-0x40); ch_prop[0].MD_bend[0] = (MD_2nd << 1); pitch_bend(/* c_p, b*/); /* #ifdef LCD mon_cc_bend_disp(c_p, 'B', MD_2nd, MD_3rd); #endif */ #endif } // else if (0xe0 == else { // ignore other message (0xf2: song position pointer, etc.) MD_bcnt = 0; // wait for next message } // else } // if (MAXMIDICH < MD_ch) ... } else MD_bcnt = 0; } // if (0 < sysex_cnt) {} else ... return(0); } // int8_t md_data_byte() void mididec(uint8_t data) { uint8_t mdd; MD_data = data; // received data if (0x80 & MD_data) { // is status byte ? if (0xf8 != (0xf8 & MD_data)) { // if system realtime message, do not affect running status MS_run_stat = MD_data; // set running status MD_ch = 0x0F & MD_data; // extract MIDI channel } // if (0xf8 ... mdd = (0xf8 & MD_data); if (0xf0 == mdd) { // System exclusive message if (0xf0 == MD_data) { // start of SysEx message #if (0) sysex_cnt = 0; // point to top of SysEx buffer MD_bcnt = 1; #else MD_bcnt = -1; // skip data bytes // crc_sr = 0; // reset CRC calc #endif // sysex_buf[sysex_cnt++] = MD_data; // copy the first 'F0' byte } // if (0xf0 == ... else if (0xf7 == MD_data) { // end of SysEx message // if (0 <= MD_bcnt) { // data successfully copied // sysex_buf[sysex_cnt++] = MD_data; // copy the last 'F7' byte #if (0) if (GM_RESET_CRC == crc_sr) { GM_reset(); } // if (GM_RESET_CRC == crc_sr) ... #endif MD_bcnt = 0; // wait for next status // sysex_dec(sysex_cnt); // sysex_cnt = 0; // exit SysEx mode // } // if (0 <= } // else if } else if (0xf8 == mdd) { // System realtime message } // ignore else { // Note ON/OFF, CC, PC, Pitch Bend, etc. MD_bcnt = 1; // wait for next byte } // if () ... } // if (0x80 & MD_data) ... else { // parameter byte md_data_byte(); } // if (0 == MIDI_bcnt) ... } // void mididec()