| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
#include <SDL.h> |
| 6 |
#include <stdio.h> |
| 7 |
#include <time.h> |
| 8 |
#include "glue.h" |
| 9 |
#include "midi.h" |
| 10 |
#include "audio.h" |
| 11 |
#include "endian.h" |
| 12 |
|
| 13 |
#ifdef _WIN32 |
| 14 |
#include <windows.h> |
| 15 |
#define LIBRARY_TYPE HMODULE |
| 16 |
#define LOAD_LIBRARY(name) LoadLibrary(name) |
| 17 |
#define GET_FUNCTION(lib, name) (void *)GetProcAddress(lib, name) |
| 18 |
#define CLOSE_LIBRARY(lib) FreeLibrary(lib) |
| 19 |
#else |
| 20 |
#include <dlfcn.h> |
| 21 |
#define LIBRARY_TYPE void* |
| 22 |
#define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY) |
| 23 |
#define GET_FUNCTION(lib, name) dlsym(lib, name) |
| 24 |
#define CLOSE_LIBRARY(lib) dlclose(lib) |
| 25 |
#endif |
| 26 |
|
| 27 |
#define ASSIGN_FUNCTION(lib, var, name) {\ |
| 28 |
var = GET_FUNCTION(lib, name);\ |
| 29 |
if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ |
| 30 |
} |
| 31 |
|
| 32 |
enum MIDI_states { |
| 33 |
MSTATE_Normal, |
| 34 |
MSTATE_Param, |
| 35 |
MSTATE_SysEx, |
| 36 |
}; |
| 37 |
|
| 38 |
struct midi_serial_regs |
| 39 |
{ |
| 40 |
LOW_HIGH_UNION(dl, dll, dlm); |
| 41 |
|
| 42 |
bool ier_erbi; |
| 43 |
bool ier_etbei; |
| 44 |
bool ier_elsi; |
| 45 |
bool ier_edssi; |
| 46 |
|
| 47 |
uint8_t iir; |
| 48 |
|
| 49 |
bool fcr_fifo_enable; |
| 50 |
uint8_t fcr_ififo_trigger_level_bytes; |
| 51 |
|
| 52 |
uint8_t lcr_word_length_bits; |
| 53 |
bool lcr_stb; |
| 54 |
bool lcr_pen; |
| 55 |
bool lcr_eps; |
| 56 |
bool lcr_stick; |
| 57 |
bool lcr_break; |
| 58 |
bool lcr_dlab; |
| 59 |
|
| 60 |
bool mcr_dtr; |
| 61 |
bool mcr_rts; |
| 62 |
bool mcr_out1; |
| 63 |
bool mcr_out2; |
| 64 |
bool mcr_loop; |
| 65 |
bool mcr_afe; |
| 66 |
|
| 67 |
bool lsr_oe; |
| 68 |
bool lsr_pe; |
| 69 |
bool lsr_fe; |
| 70 |
bool lsr_bi; |
| 71 |
bool lsr_eif; |
| 72 |
|
| 73 |
bool msr_dcts; |
| 74 |
bool msr_ddsr; |
| 75 |
bool msr_teri; |
| 76 |
bool msr_ddcd; |
| 77 |
bool msr_cts; |
| 78 |
bool msr_dsr; |
| 79 |
bool msr_ri; |
| 80 |
bool msr_dcd; |
| 81 |
|
| 82 |
uint8_t obyte_bits_remain; |
| 83 |
uint8_t ibyte_bits_remain; |
| 84 |
uint8_t rx_timeout; |
| 85 |
bool rx_timeout_enabled; |
| 86 |
|
| 87 |
bool thre_intr; |
| 88 |
uint8_t thre_bits_remain; |
| 89 |
|
| 90 |
uint8_t scratch; |
| 91 |
uint8_t ififo[16]; |
| 92 |
uint8_t ifsz; |
| 93 |
uint8_t ofifo[16]; |
| 94 |
uint8_t ofsz; |
| 95 |
|
| 96 |
int64_t clock; |
| 97 |
int32_t clockdec; |
| 98 |
|
| 99 |
time_t last_warning; |
| 100 |
|
| 101 |
uint8_t midi_event_fifo[256]; |
| 102 |
int mfsz; |
| 103 |
uint8_t in_midi_last_command; |
| 104 |
|
| 105 |
SDL_mutex *fifo_mutex; |
| 106 |
}; |
| 107 |
|
| 108 |
struct midi_serial_regs mregs[2]; |
| 109 |
static bool serial_midi_mutexes_initialized = false; |
| 110 |
|
| 111 |
void midi_serial_iir_check(uint8_t sel); |
| 112 |
bool fs_midi_in_connect = false; |
| 113 |
|
| 114 |
#ifdef HAS_FLUIDSYNTH |
| 115 |
|
| 116 |
int handle_midi_event(void* data, fluid_midi_event_t* event); |
| 117 |
|
| 118 |
static uint8_t sysex_buffer[1024]; |
| 119 |
static int sysex_bufptr; |
| 120 |
|
| 121 |
static enum MIDI_states midi_state[2] = {MSTATE_Normal, MSTATE_Normal}; |
| 122 |
static uint8_t out_midi_last_command[2] = {0, 0}; |
| 123 |
static uint8_t out_midi_first_param[2]; |
| 124 |
static uint16_t out_midi_nrpn[2][16]; |
| 125 |
static uint16_t out_midi_rpn[2][16]; |
| 126 |
static bool out_midi_nrpn_active[2][16]; |
| 127 |
|
| 128 |
static bool midi_initialized = false; |
| 129 |
|
| 130 |
static fluid_settings_t* fl_settings; |
| 131 |
static fluid_midi_driver_t* fl_mdriver; |
| 132 |
static fluid_synth_t* fl_synth; |
| 133 |
static int fl_sf2id; |
| 134 |
|
| 135 |
typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); |
| 136 |
typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); |
| 137 |
typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); |
| 138 |
typedef fluid_midi_driver_t* (*new_fluid_midi_driver_f_t)(fluid_settings_t*, handle_midi_event_func_t, void*); |
| 139 |
typedef int (*fluid_settings_setnum_f_t)(fluid_settings_t*,const char*, double); |
| 140 |
typedef int (*fluid_settings_setint_f_t)(fluid_settings_t*,const char*, int); |
| 141 |
typedef int (*fluid_settings_setstr_f_t)(fluid_settings_t*,const char*, const char*); |
| 142 |
typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*, const char *, int); |
| 143 |
typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); |
| 144 |
typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); |
| 145 |
typedef int (*fluid_synth_system_reset_f_t)(fluid_synth_t*); |
| 146 |
typedef int (*fluid_synth_noteoff_f_t)(fluid_synth_t*, int, int); |
| 147 |
typedef int (*fluid_synth_noteon_f_t)(fluid_synth_t*, int, int, int); |
| 148 |
typedef int (*fluid_synth_key_pressure_f_t)(fluid_synth_t*, int, int, int); |
| 149 |
typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); |
| 150 |
typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); |
| 151 |
typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); |
| 152 |
typedef int (*fluid_synth_write_s16_f_t)(fluid_synth_t*, int, void*, int, int, void*, int, int); |
| 153 |
typedef int (*fluid_midi_event_get_channel_f_t)(const fluid_midi_event_t*); |
| 154 |
typedef int (*fluid_midi_event_get_control_f_t)(const fluid_midi_event_t*); |
| 155 |
typedef int (*fluid_midi_event_get_key_f_t)(const fluid_midi_event_t*); |
| 156 |
typedef int (*fluid_midi_event_get_lyrics_f_t)(const fluid_midi_event_t*, void**, int*); |
| 157 |
typedef int (*fluid_midi_event_get_pitch_f_t)(const fluid_midi_event_t*); |
| 158 |
typedef int (*fluid_midi_event_get_program_f_t)(const fluid_midi_event_t*); |
| 159 |
typedef int (*fluid_midi_event_get_text_f_t)(const fluid_midi_event_t*, void**, int*); |
| 160 |
typedef int (*fluid_midi_event_get_type_f_t)(const fluid_midi_event_t*); |
| 161 |
typedef int (*fluid_midi_event_get_value_f_t)(const fluid_midi_event_t*); |
| 162 |
typedef int (*fluid_midi_event_get_velocity_f_t)(const fluid_midi_event_t*); |
| 163 |
typedef int (*fluid_midi_event_set_type_f_t)(fluid_midi_event_t*, int); |
| 164 |
|
| 165 |
static new_fluid_settings_f_t dl_new_fluid_settings; |
| 166 |
static new_fluid_synth_f_t dl_new_fluid_synth; |
| 167 |
static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; |
| 168 |
static new_fluid_midi_driver_f_t dl_new_fluid_midi_driver; |
| 169 |
static fluid_settings_setnum_f_t dl_fluid_settings_setnum; |
| 170 |
static fluid_settings_setint_f_t dl_fluid_settings_setint; |
| 171 |
static fluid_settings_setstr_f_t dl_fluid_settings_setstr; |
| 172 |
static fluid_synth_sfload_f_t dl_fs_sfload; |
| 173 |
static fluid_synth_program_change_f_t dl_fs_program_change; |
| 174 |
static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; |
| 175 |
static fluid_synth_system_reset_f_t dl_fs_system_reset; |
| 176 |
static fluid_synth_noteoff_f_t dl_fs_noteoff; |
| 177 |
static fluid_synth_noteon_f_t dl_fs_noteon; |
| 178 |
static fluid_synth_key_pressure_f_t dl_fs_key_pressure; |
| 179 |
static fluid_synth_cc_f_t dl_fs_cc; |
| 180 |
static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; |
| 181 |
static fluid_synth_sysex_f_t dl_fs_sysex; |
| 182 |
static fluid_synth_write_s16_f_t dl_fs_write_s16; |
| 183 |
static fluid_midi_event_get_channel_f_t dl_fluid_midi_event_get_channel; |
| 184 |
static fluid_midi_event_get_control_f_t dl_fluid_midi_event_get_control; |
| 185 |
static fluid_midi_event_get_key_f_t dl_fluid_midi_event_get_key; |
| 186 |
static fluid_midi_event_get_lyrics_f_t dl_fluid_midi_event_get_lyrics; |
| 187 |
static fluid_midi_event_get_pitch_f_t dl_fluid_midi_event_get_pitch; |
| 188 |
static fluid_midi_event_get_program_f_t dl_fluid_midi_event_get_program; |
| 189 |
static fluid_midi_event_get_text_f_t dl_fluid_midi_event_get_text; |
| 190 |
static fluid_midi_event_get_type_f_t dl_fluid_midi_event_get_type; |
| 191 |
static fluid_midi_event_get_value_f_t dl_fluid_midi_event_get_value; |
| 192 |
static fluid_midi_event_get_velocity_f_t dl_fluid_midi_event_get_velocity; |
| 193 |
static fluid_midi_event_set_type_f_t dl_fluid_midi_event_set_type; |
| 194 |
|
| 195 |
|
| 196 |
void midi_init() |
| 197 |
{ |
| 198 |
if (midi_initialized) { |
| 199 |
return; |
| 200 |
} |
| 201 |
|
| 202 |
#ifdef _WIN32 |
| 203 |
LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); |
| 204 |
#elif __APPLE__ |
| 205 |
LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.dylib"); |
| 206 |
#else |
| 207 |
LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so.3"); |
| 208 |
#endif |
| 209 |
|
| 210 |
if (!handle) { |
| 211 |
|
| 212 |
#ifdef _WIN32 |
| 213 |
fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); |
| 214 |
#else |
| 215 |
fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); |
| 216 |
#endif |
| 217 |
return; |
| 218 |
} |
| 219 |
|
| 220 |
#ifndef _WIN32 |
| 221 |
dlerror(); |
| 222 |
#endif |
| 223 |
|
| 224 |
ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); |
| 225 |
ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); |
| 226 |
ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); |
| 227 |
ASSIGN_FUNCTION(handle, dl_new_fluid_midi_driver, "new_fluid_midi_driver"); |
| 228 |
ASSIGN_FUNCTION(handle, dl_fluid_settings_setnum, "fluid_settings_setnum"); |
| 229 |
ASSIGN_FUNCTION(handle, dl_fluid_settings_setint, "fluid_settings_setint"); |
| 230 |
ASSIGN_FUNCTION(handle, dl_fluid_settings_setstr, "fluid_settings_setstr"); |
| 231 |
ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); |
| 232 |
ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); |
| 233 |
ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); |
| 234 |
ASSIGN_FUNCTION(handle, dl_fs_system_reset, "fluid_synth_system_reset"); |
| 235 |
ASSIGN_FUNCTION(handle, dl_fs_noteoff, "fluid_synth_noteoff"); |
| 236 |
ASSIGN_FUNCTION(handle, dl_fs_noteon, "fluid_synth_noteon"); |
| 237 |
ASSIGN_FUNCTION(handle, dl_fs_key_pressure, "fluid_synth_key_pressure"); |
| 238 |
ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); |
| 239 |
ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); |
| 240 |
ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); |
| 241 |
ASSIGN_FUNCTION(handle, dl_fs_write_s16, "fluid_synth_write_s16"); |
| 242 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_channel, "fluid_midi_event_get_channel"); |
| 243 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_control, "fluid_midi_event_get_control"); |
| 244 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_key, "fluid_midi_event_get_key"); |
| 245 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_lyrics, "fluid_midi_event_get_lyrics"); |
| 246 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_pitch, "fluid_midi_event_get_pitch"); |
| 247 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_program, "fluid_midi_event_get_program"); |
| 248 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_text, "fluid_midi_event_get_text"); |
| 249 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_type, "fluid_midi_event_get_type"); |
| 250 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_value, "fluid_midi_event_get_value"); |
| 251 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_velocity, "fluid_midi_event_get_velocity"); |
| 252 |
ASSIGN_FUNCTION(handle, dl_fluid_midi_event_set_type, "fluid_midi_event_set_type"); |
| 253 |
|
| 254 |
fl_settings = dl_new_fluid_settings(); |
| 255 |
dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", |
| 256 |
AUDIO_SAMPLERATE); |
| 257 |
dl_fluid_settings_setnum(fl_settings, "synth.gain", FL_DEFAULT_GAIN); |
| 258 |
dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); |
| 259 |
dl_fluid_settings_setint(fl_settings, "midi.autoconnect", fs_midi_in_connect); |
| 260 |
fl_synth = dl_new_fluid_synth(fl_settings); |
| 261 |
if (fs_midi_in_connect) { |
| 262 |
fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); |
| 263 |
} |
| 264 |
|
| 265 |
midi_initialized = true; |
| 266 |
fprintf(stderr, "Initialized MIDI synth at $%04X.\n", midi_card_addr); |
| 267 |
} |
| 268 |
|
| 269 |
void midi_load_sf2(uint8_t* filename) |
| 270 |
{ |
| 271 |
if (!midi_initialized) return; |
| 272 |
fl_sf2id = dl_fs_sfload(fl_synth, (const char *)filename, true); |
| 273 |
if (fl_sf2id == FLUID_FAILED) { |
| 274 |
fprintf(stderr, "Unable to load soundfont.\n"); |
| 275 |
} |
| 276 |
} |
| 277 |
|
| 278 |
|
| 279 |
|
| 280 |
void midi_byte_out(uint8_t sel, uint8_t b) |
| 281 |
{ |
| 282 |
uint8_t chan = out_midi_last_command[sel] & 0xf; |
| 283 |
|
| 284 |
if (!midi_initialized) return; |
| 285 |
switch (midi_state[sel]) { |
| 286 |
case MSTATE_Normal: |
| 287 |
if (b < 0x80) { |
| 288 |
if ((out_midi_last_command[sel] & 0xf0) == 0xc0) { |
| 289 |
dl_fs_program_change(fl_synth, out_midi_last_command[sel] & 0xf, b); |
| 290 |
} else if ((out_midi_last_command[sel] & 0xf0) == 0xd0) { |
| 291 |
dl_fs_channel_pressure(fl_synth, out_midi_last_command[sel] & 0xf, b); |
| 292 |
} else if (out_midi_last_command[sel] >= 0x80) { |
| 293 |
out_midi_first_param[sel] = b; |
| 294 |
midi_state[sel] = MSTATE_Param; |
| 295 |
} |
| 296 |
} else { |
| 297 |
if (b < 0xf0) { |
| 298 |
out_midi_last_command[sel] = b; |
| 299 |
} else if (b == 0xf0) { |
| 300 |
sysex_bufptr = 0; |
| 301 |
midi_state[sel] = MSTATE_SysEx; |
| 302 |
out_midi_last_command[sel] = 0; |
| 303 |
} else if (b == 0xff) { |
| 304 |
dl_fs_system_reset(fl_synth); |
| 305 |
out_midi_last_command[sel] = 0; |
| 306 |
} else if (b < 0xf8) { |
| 307 |
out_midi_last_command[sel] = 0; |
| 308 |
} |
| 309 |
} |
| 310 |
break; |
| 311 |
case MSTATE_Param: |
| 312 |
switch (out_midi_last_command[sel] & 0xf0) { |
| 313 |
case 0x80: |
| 314 |
dl_fs_noteoff(fl_synth, chan, out_midi_first_param[sel]); |
| 315 |
break; |
| 316 |
case 0x90: |
| 317 |
if (b == 0) { |
| 318 |
dl_fs_noteoff(fl_synth, chan, out_midi_first_param[sel]); |
| 319 |
} else { |
| 320 |
dl_fs_noteon(fl_synth, chan, out_midi_first_param[sel], b); |
| 321 |
} |
| 322 |
break; |
| 323 |
case 0xa0: |
| 324 |
dl_fs_key_pressure(fl_synth, chan, out_midi_first_param[sel], b); |
| 325 |
break; |
| 326 |
case 0xb0: |
| 327 |
switch (out_midi_first_param[sel]) { |
| 328 |
case 98: |
| 329 |
out_midi_nrpn_active[sel][chan] = true; |
| 330 |
out_midi_nrpn[sel][chan] = (out_midi_nrpn[sel][chan] & 0x00ff) | (b << 8); |
| 331 |
break; |
| 332 |
case 99: |
| 333 |
out_midi_nrpn_active[sel][chan] = true; |
| 334 |
out_midi_nrpn[sel][chan] = (out_midi_nrpn[sel][chan] & 0xff00) | b; |
| 335 |
break; |
| 336 |
case 100: |
| 337 |
out_midi_nrpn_active[sel][chan] = false; |
| 338 |
out_midi_rpn[sel][chan] = (out_midi_rpn[sel][chan] & 0x00ff) | (b << 8); |
| 339 |
break; |
| 340 |
case 101: |
| 341 |
out_midi_nrpn_active[sel][chan] = false; |
| 342 |
out_midi_rpn[sel][chan] = (out_midi_rpn[sel][chan] & 0xff00) | b; |
| 343 |
break; |
| 344 |
} |
| 345 |
dl_fs_cc(fl_synth, chan, out_midi_first_param[sel], b); |
| 346 |
if (out_midi_nrpn_active[sel][chan] && out_midi_nrpn[sel][chan] == 0x0121 && out_midi_first_param[sel] == 6) { |
| 347 |
dl_fs_cc(fl_synth, chan, 71, b); |
| 348 |
} |
| 349 |
break; |
| 350 |
case 0xe0: |
| 351 |
dl_fs_pitch_bend(fl_synth, chan, ((uint16_t)out_midi_first_param[sel]) | (uint16_t)b << 7); |
| 352 |
break; |
| 353 |
} |
| 354 |
midi_state[sel] = MSTATE_Normal; |
| 355 |
break; |
| 356 |
case MSTATE_SysEx: |
| 357 |
if (b & 0x80) { |
| 358 |
if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { |
| 359 |
sysex_buffer[sysex_bufptr] = 0; |
| 360 |
if (!strncmp((char *)sysex_buffer, "\x7F\x7F\x04\x01\x00", sysex_bufptr-1)) { |
| 361 |
|
| 362 |
dl_fluid_settings_setnum(fl_settings, "synth.gain", FL_DEFAULT_GAIN*((float)sysex_buffer[sysex_bufptr-1]/127)); |
| 363 |
} else if (!strncmp((char *)sysex_buffer, "\x7E\x7F\x09\x01", sysex_bufptr)) { |
| 364 |
|
| 365 |
dl_fs_system_reset(fl_synth); |
| 366 |
} else { |
| 367 |
dl_fs_sysex(fl_synth, (char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); |
| 368 |
} |
| 369 |
} |
| 370 |
midi_state[sel] = MSTATE_Normal; |
| 371 |
return midi_byte_out(sel, b); |
| 372 |
} else { |
| 373 |
sysex_buffer[sysex_bufptr] = b; |
| 374 |
|
| 375 |
|
| 376 |
if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { |
| 377 |
sysex_bufptr++; |
| 378 |
} |
| 379 |
} |
| 380 |
break; |
| 381 |
} |
| 382 |
} |
| 383 |
|
| 384 |
void midi_synth_render(int16_t* buf, int len) |
| 385 |
{ |
| 386 |
if (midi_initialized) { |
| 387 |
dl_fs_write_s16(fl_synth, len, buf, 0, 2, buf, 1, 2); |
| 388 |
} else { |
| 389 |
memset(buf, 0, len * 2 * sizeof(int16_t)); |
| 390 |
} |
| 391 |
} |
| 392 |
|
| 393 |
void midi_event_enqueue_byte(struct midi_serial_regs* mrp, uint8_t val) |
| 394 |
{ |
| 395 |
if (mrp->mfsz >= 256) return; |
| 396 |
mrp->midi_event_fifo[mrp->mfsz++] = val; |
| 397 |
} |
| 398 |
|
| 399 |
void midi_event_enqueue_short(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t val) |
| 400 |
{ |
| 401 |
if (mrp->mfsz >= 255) { |
| 402 |
mrp->in_midi_last_command = 0; |
| 403 |
return; |
| 404 |
} |
| 405 |
if (mrp->in_midi_last_command != cmd) { |
| 406 |
mrp->midi_event_fifo[mrp->mfsz++] = cmd; |
| 407 |
mrp->in_midi_last_command = cmd; |
| 408 |
} |
| 409 |
mrp->midi_event_fifo[mrp->mfsz++] = val; |
| 410 |
} |
| 411 |
|
| 412 |
void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t key, uint8_t val) |
| 413 |
{ |
| 414 |
if (mrp->mfsz >= 254) { |
| 415 |
mrp->in_midi_last_command = 0; |
| 416 |
return; |
| 417 |
} |
| 418 |
if (mrp->in_midi_last_command != cmd) { |
| 419 |
mrp->midi_event_fifo[mrp->mfsz++] = cmd; |
| 420 |
mrp->in_midi_last_command = cmd; |
| 421 |
} |
| 422 |
mrp->midi_event_fifo[mrp->mfsz++] = key; |
| 423 |
mrp->midi_event_fifo[mrp->mfsz++] = val; |
| 424 |
} |
| 425 |
|
| 426 |
void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int buflen) |
| 427 |
{ |
| 428 |
int i; |
| 429 |
|
| 430 |
mrp->in_midi_last_command = 0; |
| 431 |
if (mrp->mfsz >= 255L - (buflen + 2)) { |
| 432 |
return; |
| 433 |
} |
| 434 |
|
| 435 |
mrp->midi_event_fifo[mrp->mfsz++] = 0xf0; |
| 436 |
for (i = 0; i < buflen; i++) { |
| 437 |
mrp->midi_event_fifo[mrp->mfsz++] = bufptr[i]; |
| 438 |
} |
| 439 |
mrp->midi_event_fifo[mrp->mfsz++] = 0xf7; |
| 440 |
} |
| 441 |
|
| 442 |
int handle_midi_event(void* data, fluid_midi_event_t* event) |
| 443 |
{ |
| 444 |
struct midi_serial_regs* mrp = (struct midi_serial_regs*)data; |
| 445 |
SDL_LockMutex(mrp->fifo_mutex); |
| 446 |
|
| 447 |
uint8_t type = dl_fluid_midi_event_get_type(event); |
| 448 |
uint8_t chan = dl_fluid_midi_event_get_channel(event); |
| 449 |
uint8_t cmd = (type < 0x80 || type >= 0xf0) ? type : (type | (chan & 0xf)); |
| 450 |
uint8_t key, val; |
| 451 |
uint8_t *bufptr; |
| 452 |
int buflen; |
| 453 |
|
| 454 |
switch (type) { |
| 455 |
case FS_NOTE_OFF: |
| 456 |
case FS_NOTE_ON: |
| 457 |
key = dl_fluid_midi_event_get_key(event); |
| 458 |
val = dl_fluid_midi_event_get_velocity(event); |
| 459 |
midi_event_enqueue_normal(mrp, cmd, key, val); |
| 460 |
break; |
| 461 |
case FS_KEY_PRESSURE: |
| 462 |
key = dl_fluid_midi_event_get_key(event); |
| 463 |
val = dl_fluid_midi_event_get_value(event); |
| 464 |
midi_event_enqueue_normal(mrp, cmd, key, val); |
| 465 |
break; |
| 466 |
case FS_CONTROL_CHANGE: |
| 467 |
key = dl_fluid_midi_event_get_control(event); |
| 468 |
val = dl_fluid_midi_event_get_value(event); |
| 469 |
midi_event_enqueue_normal(mrp, cmd, key, val); |
| 470 |
break; |
| 471 |
case FS_PITCH_BEND: |
| 472 |
key = dl_fluid_midi_event_get_pitch(event) & 0x7f; |
| 473 |
val = (dl_fluid_midi_event_get_pitch(event) >> 7) & 0x7f; |
| 474 |
midi_event_enqueue_normal(mrp, cmd, key, val); |
| 475 |
break; |
| 476 |
case FS_PROGRAM_CHANGE: |
| 477 |
case FS_CHANNEL_PRESSURE: |
| 478 |
val = dl_fluid_midi_event_get_program(event); |
| 479 |
midi_event_enqueue_short(mrp, cmd, val); |
| 480 |
break; |
| 481 |
case FS_MIDI_TIME_CODE: |
| 482 |
val = dl_fluid_midi_event_get_value(event); |
| 483 |
midi_event_enqueue_short(mrp, type, val); |
| 484 |
mrp->in_midi_last_command = 0; |
| 485 |
break; |
| 486 |
case FS_MIDI_TUNE_REQUEST: |
| 487 |
case 0xF4: |
| 488 |
case 0xF5: |
| 489 |
midi_event_enqueue_byte(mrp, type); |
| 490 |
mrp->in_midi_last_command = 0; |
| 491 |
break; |
| 492 |
case FS_MIDI_SYNC: |
| 493 |
case FS_MIDI_TICK: |
| 494 |
case FS_MIDI_START: |
| 495 |
case FS_MIDI_CONTINUE: |
| 496 |
case FS_MIDI_STOP: |
| 497 |
case FS_MIDI_ACTIVE_SENSING: |
| 498 |
case FS_MIDI_SYSTEM_RESET: |
| 499 |
midi_event_enqueue_byte(mrp, type); |
| 500 |
break; |
| 501 |
case FS_MIDI_SYSEX: |
| 502 |
|
| 503 |
|
| 504 |
|
| 505 |
|
| 506 |
|
| 507 |
|
| 508 |
dl_fluid_midi_event_set_type(event, FS_MIDI_TEXT); |
| 509 |
if (dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen) == FLUID_OK && bufptr != NULL) { |
| 510 |
midi_event_enqueue_sysex(mrp, bufptr, buflen); |
| 511 |
} |
| 512 |
break; |
| 513 |
} |
| 514 |
|
| 515 |
|
| 516 |
|
| 517 |
SDL_UnlockMutex(mrp->fifo_mutex); |
| 518 |
return FLUID_OK; |
| 519 |
} |
| 520 |
|
| 521 |
|
| 522 |
#else |
| 523 |
void midi_load_sf2(uint8_t* filename) |
| 524 |
{ |
| 525 |
|
| 526 |
} |
| 527 |
|
| 528 |
void midi_init() |
| 529 |
{ |
| 530 |
fprintf(stderr, "No FluidSynth support.\n"); |
| 531 |
} |
| 532 |
|
| 533 |
void midi_byte_out(uint8_t sel, uint8_t b) |
| 534 |
{ |
| 535 |
|
| 536 |
} |
| 537 |
|
| 538 |
void midi_synth_render(int16_t* buf, int len) |
| 539 |
{ |
| 540 |
|
| 541 |
memset(buf, 0, len * 2 * sizeof(int16_t)); |
| 542 |
} |
| 543 |
|
| 544 |
#endif |
| 545 |
|
| 546 |
void midi_serial_init() |
| 547 |
{ |
| 548 |
uint8_t sel; |
| 549 |
|
| 550 |
for (sel=0; sel<2; sel++) { |
| 551 |
mregs[sel].ier_erbi = false; |
| 552 |
mregs[sel].ier_etbei = false; |
| 553 |
mregs[sel].ier_elsi = false; |
| 554 |
mregs[sel].ier_edssi = false; |
| 555 |
|
| 556 |
mregs[sel].iir = 0x01; |
| 557 |
|
| 558 |
mregs[sel].fcr_fifo_enable = false; |
| 559 |
mregs[sel].fcr_ififo_trigger_level_bytes = 1; |
| 560 |
|
| 561 |
mregs[sel].lcr_word_length_bits = 5; |
| 562 |
mregs[sel].lcr_stb = false; |
| 563 |
mregs[sel].lcr_pen = false; |
| 564 |
mregs[sel].lcr_eps = false; |
| 565 |
mregs[sel].lcr_stick = false; |
| 566 |
mregs[sel].lcr_break = false; |
| 567 |
mregs[sel].lcr_dlab = false; |
| 568 |
|
| 569 |
mregs[sel].mcr_dtr = false; |
| 570 |
mregs[sel].mcr_rts = false; |
| 571 |
mregs[sel].mcr_out1 = false; |
| 572 |
mregs[sel].mcr_out2 = false; |
| 573 |
mregs[sel].mcr_loop = false; |
| 574 |
mregs[sel].mcr_afe = false; |
| 575 |
|
| 576 |
mregs[sel].lsr_oe = false; |
| 577 |
mregs[sel].lsr_pe = false; |
| 578 |
mregs[sel].lsr_fe = false; |
| 579 |
mregs[sel].lsr_bi = false; |
| 580 |
mregs[sel].lsr_eif = false; |
| 581 |
|
| 582 |
mregs[sel].msr_dcts = false; |
| 583 |
mregs[sel].msr_ddsr = false; |
| 584 |
mregs[sel].msr_teri = false; |
| 585 |
mregs[sel].msr_ddcd = false; |
| 586 |
|
| 587 |
mregs[sel].msr_cts = false; |
| 588 |
mregs[sel].msr_dsr = false; |
| 589 |
mregs[sel].msr_ri = false; |
| 590 |
mregs[sel].msr_dcd = false; |
| 591 |
|
| 592 |
mregs[sel].obyte_bits_remain = 0; |
| 593 |
mregs[sel].rx_timeout = 0; |
| 594 |
mregs[sel].rx_timeout_enabled = false; |
| 595 |
mregs[sel].thre_intr = false; |
| 596 |
mregs[sel].thre_bits_remain = 0; |
| 597 |
|
| 598 |
mregs[sel].ibyte_bits_remain = 7; |
| 599 |
|
| 600 |
mregs[sel].ifsz = 0; |
| 601 |
mregs[sel].ififo[0] = 0; |
| 602 |
mregs[sel].ofsz = 0; |
| 603 |
mregs[sel].clock = 0; |
| 604 |
mregs[sel].clockdec = 0; |
| 605 |
mregs[sel].last_warning = 0; |
| 606 |
|
| 607 |
mregs[sel].mfsz = 0; |
| 608 |
mregs[sel].in_midi_last_command = 0; |
| 609 |
} |
| 610 |
|
| 611 |
if (!serial_midi_mutexes_initialized) { |
| 612 |
for (sel=0; sel<2; sel++) { |
| 613 |
mregs[sel].fifo_mutex = SDL_CreateMutex(); |
| 614 |
} |
| 615 |
serial_midi_mutexes_initialized = true; |
| 616 |
} |
| 617 |
} |
| 618 |
|
| 619 |
void midi_serial_iir_check(uint8_t sel) |
| 620 |
{ |
| 621 |
uint8_t fifoen = (uint8_t)mregs[sel].fcr_fifo_enable << 6 | (uint8_t)mregs[sel].fcr_fifo_enable << 7; |
| 622 |
if (mregs[sel].ier_elsi && (mregs[sel].lsr_oe || mregs[sel].lsr_pe || mregs[sel].lsr_fe || mregs[sel].lsr_bi)) { |
| 623 |
mregs[sel].iir = (0x06 | fifoen); |
| 624 |
} else if (mregs[sel].ier_erbi && !mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0) { |
| 625 |
mregs[sel].iir = (0x04 | fifoen); |
| 626 |
} else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz >= mregs[sel].fcr_ififo_trigger_level_bytes) { |
| 627 |
mregs[sel].iir = (0x04 | fifoen); |
| 628 |
} else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0 && mregs[sel].rx_timeout_enabled && mregs[sel].rx_timeout == 0) { |
| 629 |
mregs[sel].iir = (0x0c | fifoen); |
| 630 |
} else if (mregs[sel].ier_etbei && mregs[sel].thre_intr) { |
| 631 |
mregs[sel].iir = (0x02 | fifoen); |
| 632 |
} else if (mregs[sel].ier_edssi && ((!mregs[sel].mcr_afe && mregs[sel].msr_dcts) || mregs[sel].msr_ddcd || mregs[sel].msr_ddsr || mregs[sel].msr_teri)) { |
| 633 |
mregs[sel].iir = (0x00 | fifoen); |
| 634 |
} else { |
| 635 |
mregs[sel].iir = (0x01 | fifoen); |
| 636 |
} |
| 637 |
} |
| 638 |
|
| 639 |
void midi_serial_step(int clocks) |
| 640 |
{ |
| 641 |
uint8_t sel, i; |
| 642 |
for (sel=0; sel<2; sel++) { |
| 643 |
mregs[sel].clock -= (int64_t)mregs[sel].clockdec * clocks; |
| 644 |
while (mregs[sel].clock < 0) { |
| 645 |
|
| 646 |
SDL_LockMutex(mregs[sel].fifo_mutex); |
| 647 |
|
| 648 |
if (mregs[sel].obyte_bits_remain > 0) { |
| 649 |
mregs[sel].obyte_bits_remain--; |
| 650 |
} |
| 651 |
if (mregs[sel].ofsz > 0) { |
| 652 |
if (mregs[sel].obyte_bits_remain == 0) { |
| 653 |
midi_byte_out(sel, mregs[sel].ofifo[0]); |
| 654 |
mregs[sel].ofsz--; |
| 655 |
if (mregs[sel].ofsz > 0) { |
| 656 |
for (i=0; i<mregs[sel].ofsz; i++) { |
| 657 |
mregs[sel].ofifo[i] = mregs[sel].ofifo[i+1]; |
| 658 |
} |
| 659 |
} else if (mregs[sel].thre_bits_remain == 0) { |
| 660 |
mregs[sel].thre_intr = true; |
| 661 |
} |
| 662 |
mregs[sel].obyte_bits_remain = 2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; |
| 663 |
} |
| 664 |
} else { |
| 665 |
if (mregs[sel].thre_bits_remain > 0) { |
| 666 |
mregs[sel].thre_bits_remain--; |
| 667 |
if (mregs[sel].thre_bits_remain == 0) { |
| 668 |
mregs[sel].thre_intr = true; |
| 669 |
} |
| 670 |
} |
| 671 |
} |
| 672 |
|
| 673 |
if (mregs[sel].rx_timeout > 0) { |
| 674 |
mregs[sel].rx_timeout--; |
| 675 |
} |
| 676 |
|
| 677 |
if (mregs[sel].ibyte_bits_remain > 0 && mregs[sel].mfsz > 0) { |
| 678 |
mregs[sel].ibyte_bits_remain--; |
| 679 |
} |
| 680 |
if (mregs[sel].ibyte_bits_remain == 0 && mregs[sel].mfsz > 0) { |
| 681 |
if (mregs[sel].ifsz < (mregs[sel].fcr_fifo_enable ? 16 : 1)) { |
| 682 |
mregs[sel].ififo[mregs[sel].ifsz++] = mregs[sel].midi_event_fifo[0]; |
| 683 |
mregs[sel].rx_timeout_enabled = true; |
| 684 |
mregs[sel].rx_timeout = 4 * (2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen); |
| 685 |
} else { |
| 686 |
mregs[sel].lsr_oe = true; |
| 687 |
if (!mregs[sel].fcr_fifo_enable) { |
| 688 |
|
| 689 |
|
| 690 |
mregs[sel].ififo[mregs[sel].ifsz-1] = mregs[sel].midi_event_fifo[0]; |
| 691 |
} |
| 692 |
} |
| 693 |
mregs[sel].mfsz--; |
| 694 |
if (mregs[sel].mfsz > 0) { |
| 695 |
for (i=0; i<mregs[sel].mfsz; i++) { |
| 696 |
mregs[sel].midi_event_fifo[i] = mregs[sel].midi_event_fifo[i+1]; |
| 697 |
} |
| 698 |
} |
| 699 |
mregs[sel].ibyte_bits_remain = 2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; |
| 700 |
} |
| 701 |
|
| 702 |
SDL_UnlockMutex(mregs[sel].fifo_mutex); |
| 703 |
mregs[sel].clock += 0x1000000LL; |
| 704 |
midi_serial_iir_check(sel); |
| 705 |
} |
| 706 |
} |
| 707 |
} |
| 708 |
|
| 709 |
uint8_t midi_serial_dequeue_ibyte(uint8_t sel) |
| 710 |
{ |
| 711 |
SDL_LockMutex(mregs[sel].fifo_mutex); |
| 712 |
uint8_t ret = mregs[sel].ififo[0]; |
| 713 |
uint8_t i; |
| 714 |
|
| 715 |
if (mregs[sel].ifsz > 0) { |
| 716 |
mregs[sel].ifsz--; |
| 717 |
if (mregs[sel].ifsz == 0) { |
| 718 |
mregs[sel].rx_timeout_enabled = false; |
| 719 |
} else { |
| 720 |
for (i=0; i<mregs[sel].ifsz; i++) { |
| 721 |
mregs[sel].ififo[i] = mregs[sel].ififo[i+1]; |
| 722 |
} |
| 723 |
mregs[sel].rx_timeout_enabled = true; |
| 724 |
mregs[sel].rx_timeout = 4 * (2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen); |
| 725 |
} |
| 726 |
midi_serial_iir_check(sel); |
| 727 |
} |
| 728 |
|
| 729 |
SDL_UnlockMutex(mregs[sel].fifo_mutex); |
| 730 |
return ret; |
| 731 |
} |
| 732 |
|
| 733 |
void midi_serial_enqueue_obyte(uint8_t sel, uint8_t val) |
| 734 |
{ |
| 735 |
SDL_LockMutex(mregs[sel].fifo_mutex); |
| 736 |
if (mregs[sel].ofsz < (mregs[sel].fcr_fifo_enable ? 16 : 1)) { |
| 737 |
mregs[sel].ofifo[mregs[sel].ofsz] = val; |
| 738 |
mregs[sel].thre_intr = false; |
| 739 |
mregs[sel].ofsz++; |
| 740 |
if (mregs[sel].ofsz == 1) { |
| 741 |
if (mregs[sel].fcr_fifo_enable) { |
| 742 |
|
| 743 |
mregs[sel].thre_bits_remain = 1 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; |
| 744 |
} |
| 745 |
} else { |
| 746 |
mregs[sel].thre_bits_remain = 0; |
| 747 |
} |
| 748 |
} else { |
| 749 |
fprintf(stderr, "Serial MIDI: Warning: UART %d TX Overflow\n", sel); |
| 750 |
} |
| 751 |
midi_serial_iir_check(sel); |
| 752 |
SDL_UnlockMutex(mregs[sel].fifo_mutex); |
| 753 |
} |
| 754 |
|
| 755 |
uint8_t midi_serial_read(uint8_t reg, bool debugOn) |
| 756 |
{ |
| 757 |
|
| 758 |
uint8_t sel = (reg & 8) >> 3; |
| 759 |
switch (reg & 7) { |
| 760 |
case 0x0: |
| 761 |
if (mregs[sel].lcr_dlab) { |
| 762 |
return mregs[sel].dll; |
| 763 |
} else { |
| 764 |
if (debugOn) { |
| 765 |
return mregs[sel].ififo[0]; |
| 766 |
} else { |
| 767 |
return midi_serial_dequeue_ibyte(sel); |
| 768 |
} |
| 769 |
} |
| 770 |
break; |
| 771 |
case 0x1: |
| 772 |
if (mregs[sel].lcr_dlab) { |
| 773 |
return mregs[sel].dlm; |
| 774 |
} else { |
| 775 |
return (((uint8_t)mregs[sel].ier_edssi << 3) | |
| 776 |
((uint8_t)mregs[sel].ier_elsi << 2) | |
| 777 |
((uint8_t)mregs[sel].ier_etbei << 1) | |
| 778 |
((uint8_t)mregs[sel].ier_erbi)); |
| 779 |
} |
| 780 |
break; |
| 781 |
case 0x2: { |
| 782 |
uint8_t ret = mregs[sel].iir; |
| 783 |
if (!debugOn) { |
| 784 |
mregs[sel].thre_intr = false; |
| 785 |
midi_serial_iir_check(sel); |
| 786 |
} |
| 787 |
return ret; |
| 788 |
break; |
| 789 |
} |
| 790 |
case 0x3: |
| 791 |
return (((uint8_t)mregs[sel].lcr_dlab << 7) | |
| 792 |
((uint8_t)mregs[sel].lcr_break << 6) | |
| 793 |
((uint8_t)mregs[sel].lcr_stick << 5) | |
| 794 |
((uint8_t)mregs[sel].lcr_eps << 4) | |
| 795 |
((uint8_t)mregs[sel].lcr_pen << 3) | |
| 796 |
((uint8_t)mregs[sel].lcr_stb << 2) | |
| 797 |
((mregs[sel].lcr_word_length_bits - 5) & 0x3)); |
| 798 |
break; |
| 799 |
case 0x4: |
| 800 |
return (((uint8_t)mregs[sel].mcr_afe << 5) | |
| 801 |
((uint8_t)mregs[sel].mcr_loop << 4) | |
| 802 |
((uint8_t)mregs[sel].mcr_out2 << 3) | |
| 803 |
((uint8_t)mregs[sel].mcr_out1 << 2) | |
| 804 |
((uint8_t)mregs[sel].mcr_rts << 1) | |
| 805 |
((uint8_t)mregs[sel].mcr_dtr)); |
| 806 |
break; |
| 807 |
case 0x5: { |
| 808 |
uint8_t ret = (((uint8_t)mregs[sel].lsr_eif << 7) | |
| 809 |
((uint8_t)(mregs[sel].obyte_bits_remain == 0 && mregs[sel].ofsz == 0) << 6) | |
| 810 |
((uint8_t)(mregs[sel].ofsz == 0) << 5) | |
| 811 |
((uint8_t)mregs[sel].lsr_bi << 4) | |
| 812 |
((uint8_t)mregs[sel].lsr_fe << 3) | |
| 813 |
((uint8_t)mregs[sel].lsr_pe << 2) | |
| 814 |
((uint8_t)mregs[sel].lsr_oe << 1) | |
| 815 |
((uint8_t)(mregs[sel].ifsz > 0))); |
| 816 |
if (!debugOn) { |
| 817 |
mregs[sel].lsr_oe = false; |
| 818 |
mregs[sel].lsr_pe = false; |
| 819 |
mregs[sel].lsr_fe = false; |
| 820 |
mregs[sel].lsr_bi = false; |
| 821 |
} |
| 822 |
return ret; |
| 823 |
break; |
| 824 |
} |
| 825 |
case 0x6: |
| 826 |
return (((uint8_t)mregs[sel].msr_dcd << 7) | |
| 827 |
((uint8_t)mregs[sel].msr_ri << 6) | |
| 828 |
((uint8_t)mregs[sel].msr_dsr << 5) | |
| 829 |
((uint8_t)mregs[sel].msr_cts << 4) | |
| 830 |
((uint8_t)mregs[sel].msr_ddcd << 3) | |
| 831 |
((uint8_t)mregs[sel].msr_teri << 2) | |
| 832 |
((uint8_t)mregs[sel].msr_ddsr << 1) | |
| 833 |
((uint8_t)mregs[sel].msr_dcts)); |
| 834 |
break; |
| 835 |
case 0x7: |
| 836 |
return mregs[sel].scratch; |
| 837 |
break; |
| 838 |
} |
| 839 |
return 0x00; |
| 840 |
} |
| 841 |
|
| 842 |
void midi_serial_calculate_clk(uint8_t sel) |
| 843 |
{ |
| 844 |
double uart_clks_per_cpu = (MIDI_UART_OSC_RATE_MHZ / MIDI_UART_PRIMARY_DIVIDER) / MHZ; |
| 845 |
if (mregs[sel].dl > 0) { |
| 846 |
uart_clks_per_cpu /= mregs[sel].dl; |
| 847 |
mregs[sel].clockdec = uart_clks_per_cpu * 0x1000000L; |
| 848 |
} else { |
| 849 |
mregs[sel].clockdec = 0; |
| 850 |
} |
| 851 |
} |
| 852 |
|
| 853 |
void midi_serial_write(uint8_t reg, uint8_t val) |
| 854 |
{ |
| 855 |
time_t now = time(NULL); |
| 856 |
|
| 857 |
|
| 858 |
uint8_t sel = (reg & 8) >> 3; |
| 859 |
switch (reg & 7) { |
| 860 |
case 0x0: |
| 861 |
if (mregs[sel].lcr_dlab) { |
| 862 |
mregs[sel].dll = val; |
| 863 |
midi_serial_calculate_clk(sel); |
| 864 |
} else { |
| 865 |
if (mregs[sel].lcr_word_length_bits != 8 || mregs[sel].lcr_stb || mregs[sel].lcr_pen) { |
| 866 |
if (mregs[sel].last_warning + 60 < now) { |
| 867 |
unsigned char par = 'N'; |
| 868 |
if (mregs[sel].lcr_pen) { |
| 869 |
switch ((uint8_t)(mregs[sel].lcr_eps << 1) | (uint8_t)mregs[sel].lcr_stick) { |
| 870 |
case 0: |
| 871 |
par = 'O'; |
| 872 |
break; |
| 873 |
case 1: |
| 874 |
par = 'M'; |
| 875 |
break; |
| 876 |
case 2: |
| 877 |
par = 'E'; |
| 878 |
break; |
| 879 |
case 3: |
| 880 |
par = 'S'; |
| 881 |
break; |
| 882 |
} |
| 883 |
} |
| 884 |
fprintf(stderr, "Serial MIDI: Warning: improper LCR %d%c%d for UART %d, must be set to 8N1.\n", mregs[sel].lcr_word_length_bits, par, 1+(uint8_t)mregs[sel].lcr_stb, sel); |
| 885 |
mregs[sel].last_warning = now; |
| 886 |
} |
| 887 |
} else if (mregs[sel].lcr_break && mregs[sel].last_warning + 60 < now) { |
| 888 |
fprintf(stderr, "Serial MIDI: Warning: break improperly set for UART %d.\n", sel); |
| 889 |
mregs[sel].last_warning = now; |
| 890 |
} else if (mregs[sel].dl != 32 && mregs[sel].last_warning + 60 < now) { |
| 891 |
fprintf(stderr, "Serial MIDI: Warning: improper divisor %d for UART %d, must be set to 32 for standard MIDI bitrate.\n", mregs[sel].dl, sel); |
| 892 |
mregs[sel].last_warning = now; |
| 893 |
} else { |
| 894 |
midi_serial_enqueue_obyte(sel, val); |
| 895 |
} |
| 896 |
} |
| 897 |
break; |
| 898 |
case 0x1: |
| 899 |
if (mregs[sel].lcr_dlab) { |
| 900 |
mregs[sel].dlm = val; |
| 901 |
midi_serial_calculate_clk(sel); |
| 902 |
} else { |
| 903 |
mregs[sel].ier_erbi = !!(val & 1); |
| 904 |
mregs[sel].ier_etbei = !!(val & 2); |
| 905 |
mregs[sel].ier_elsi = !!(val & 4); |
| 906 |
mregs[sel].ier_edssi = !!(val & 8); |
| 907 |
} |
| 908 |
break; |
| 909 |
case 0x2: |
| 910 |
if (val & 1) { |
| 911 |
mregs[sel].fcr_fifo_enable = true; |
| 912 |
switch ((val & 0xc0) >> 6) { |
| 913 |
case 0: |
| 914 |
mregs[sel].fcr_ififo_trigger_level_bytes = 1; |
| 915 |
break; |
| 916 |
case 1: |
| 917 |
mregs[sel].fcr_ififo_trigger_level_bytes = 4; |
| 918 |
break; |
| 919 |
case 2: |
| 920 |
mregs[sel].fcr_ififo_trigger_level_bytes = 8; |
| 921 |
break; |
| 922 |
case 3: |
| 923 |
mregs[sel].fcr_ififo_trigger_level_bytes = 14; |
| 924 |
break; |
| 925 |
} |
| 926 |
} else { |
| 927 |
mregs[sel].fcr_fifo_enable = false; |
| 928 |
mregs[sel].fcr_ififo_trigger_level_bytes = 1; |
| 929 |
} |
| 930 |
if (val & 2) { |
| 931 |
mregs[sel].ifsz = 0; |
| 932 |
} |
| 933 |
if (val & 4) { |
| 934 |
mregs[sel].ofsz = 0; |
| 935 |
} |
| 936 |
if (mregs[sel].thre_bits_remain == 0) { |
| 937 |
mregs[sel].thre_intr = true; |
| 938 |
} |
| 939 |
midi_serial_iir_check(sel); |
| 940 |
break; |
| 941 |
case 0x3: |
| 942 |
mregs[sel].lcr_word_length_bits = (val & 0x03)+5; |
| 943 |
mregs[sel].lcr_stb = !!(val & 0x04); |
| 944 |
mregs[sel].lcr_pen = !!(val & 0x08); |
| 945 |
mregs[sel].lcr_eps = !!(val & 0x10); |
| 946 |
mregs[sel].lcr_stick = !!(val & 0x20); |
| 947 |
mregs[sel].lcr_break = !!(val & 0x40); |
| 948 |
mregs[sel].lcr_dlab = !!(val & 0x80); |
| 949 |
if (mregs[sel].mfsz == 0) { |
| 950 |
mregs[sel].ibyte_bits_remain = 2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; |
| 951 |
} |
| 952 |
break; |
| 953 |
case 0x4: |
| 954 |
mregs[sel].mcr_dtr = !!(val & 0x01); |
| 955 |
mregs[sel].mcr_rts = !!(val & 0x02); |
| 956 |
mregs[sel].mcr_out1 = !!(val & 0x04); |
| 957 |
mregs[sel].mcr_out2 = !!(val & 0x08); |
| 958 |
mregs[sel].mcr_loop = !!(val & 0x10); |
| 959 |
mregs[sel].mcr_afe = !!(val & 0x20); |
| 960 |
|
| 961 |
if (mregs[sel].mcr_loop) { |
| 962 |
mregs[sel].msr_dcts |= mregs[sel].msr_cts ^ mregs[sel].mcr_dtr; |
| 963 |
mregs[sel].msr_cts = mregs[sel].mcr_dtr; |
| 964 |
|
| 965 |
mregs[sel].msr_ddsr |= mregs[sel].msr_dsr ^ mregs[sel].mcr_rts; |
| 966 |
mregs[sel].msr_dsr = mregs[sel].mcr_rts; |
| 967 |
|
| 968 |
if (mregs[sel].msr_ri) { |
| 969 |
mregs[sel].msr_teri |= mregs[sel].msr_ri ^ mregs[sel].mcr_out1; |
| 970 |
} |
| 971 |
mregs[sel].msr_ri = mregs[sel].mcr_out1; |
| 972 |
|
| 973 |
mregs[sel].msr_ddcd |= mregs[sel].msr_dcd ^ mregs[sel].mcr_out2; |
| 974 |
mregs[sel].msr_dcd = mregs[sel].mcr_out2; |
| 975 |
|
| 976 |
} else { |
| 977 |
|
| 978 |
if (mregs[sel ^ 1].msr_ri && !mregs[sel].mcr_dtr) { |
| 979 |
mregs[sel ^ 1].msr_teri = true; |
| 980 |
} |
| 981 |
mregs[sel ^ 1].msr_ri = mregs[sel].mcr_dtr; |
| 982 |
} |
| 983 |
|
| 984 |
break; |
| 985 |
case 0x7: |
| 986 |
mregs[sel].scratch = val; |
| 987 |
break; |
| 988 |
} |
| 989 |
} |
| 990 |
|
| 991 |
bool midi_serial_irq(void) |
| 992 |
{ |
| 993 |
bool uart0int = (mregs[0].iir & 1) == 0 && mregs[0].mcr_out2; |
| 994 |
bool uart1int = (mregs[1].iir & 1) == 0 && mregs[1].mcr_out2; |
| 995 |
return (uart0int | uart1int); |
| 996 |
} |