Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:44

0001 /*  midi.c
0002  *
0003  *  Milkymist MIDI driver for RTEMS
0004  *
0005  *  The license and distribution terms for this file may be
0006  *  found in the file LICENSE in this distribution or at
0007  *  http://www.rtems.org/license/LICENSE.
0008  *
0009  *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
0010  */
0011 
0012 #define RTEMS_STATUS_CHECKS_USE_PRINTK
0013 
0014 #include <stdlib.h>
0015 #include <sys/types.h>
0016 #include <rtems.h>
0017 #include <rtems/status-checks.h>
0018 #include <bsp.h>
0019 #include <bsp/irq-generic.h>
0020 #include <rtems/libio.h>
0021 #include "../include/system_conf.h"
0022 #include <bsp/milkymist_midi.h>
0023 
0024 #define DEVICE_NAME "/dev/midi"
0025 
0026 static rtems_id midi_q;
0027 static unsigned char *midi_p = NULL;
0028 static unsigned char midi_msg[3];
0029 
0030 static rtems_isr interrupt_handler(rtems_vector_number n)
0031 {
0032   unsigned char msg;
0033 
0034   while (MM_READ(MM_MIDI_STAT) & MIDI_STAT_RX_EVT) {
0035     msg = MM_READ(MM_MIDI_RXTX);
0036     MM_WRITE(MM_MIDI_STAT, MIDI_STAT_RX_EVT);
0037 
0038     if ((msg & 0xf8) == 0xf8)
0039       continue; /* ignore system real-time */
0040 
0041     if (msg & 0x80)
0042       midi_p = midi_msg; /* status byte */
0043 
0044     if (!midi_p)
0045       continue; /* ignore extra or unsynchronized data */
0046 
0047     *midi_p++ = msg;
0048 
0049     if (midi_p == midi_msg+3) {
0050       /* received a complete MIDI message */
0051       rtems_message_queue_send(midi_q, midi_msg, 3);
0052       midi_p = NULL;
0053     }
0054   }
0055   lm32_interrupt_ack(1 << MM_IRQ_MIDI);
0056 }
0057 
0058 rtems_device_driver midi_initialize(
0059   rtems_device_major_number major,
0060   rtems_device_minor_number minor,
0061   void *arg
0062 )
0063 {
0064   rtems_status_code sc;
0065   rtems_isr_entry dummy;
0066 
0067   sc = rtems_io_register_name(DEVICE_NAME, major, 0);
0068   RTEMS_CHECK_SC(sc, "create MIDI input device");
0069 
0070  sc = rtems_message_queue_create(
0071     rtems_build_name('M', 'I', 'D', 'I'),
0072     32,
0073     3,
0074     0,
0075     &midi_q
0076   );
0077   RTEMS_CHECK_SC(sc, "create MIDI queue");
0078 
0079   rtems_interrupt_catch(interrupt_handler, MM_IRQ_MIDI, &dummy);
0080   bsp_interrupt_vector_enable(MM_IRQ_MIDI);
0081   /* Only MIDI THRU mode is supported atm */
0082   MM_WRITE(MM_MIDI_CTRL, MIDI_CTRL_RX_INT|MIDI_CTRL_THRU);
0083 
0084   return RTEMS_SUCCESSFUL;
0085 }
0086 
0087 rtems_device_driver midi_open(
0088   rtems_device_major_number major,
0089   rtems_device_minor_number minor,
0090   void *arg
0091 )
0092 {
0093   uint32_t count;
0094 
0095   rtems_message_queue_flush(midi_q, &count);
0096   return RTEMS_SUCCESSFUL;
0097 }
0098 
0099 rtems_device_driver midi_read(
0100   rtems_device_major_number major,
0101   rtems_device_minor_number minor,
0102   void *arg
0103 )
0104 {
0105   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0106   rtems_status_code sc;
0107 
0108   sc = rtems_message_queue_receive(
0109     midi_q,
0110     rw_args->buffer,
0111     (size_t *)&rw_args->bytes_moved,
0112     RTEMS_WAIT,
0113     RTEMS_NO_TIMEOUT
0114   );
0115 
0116   if(sc == RTEMS_SUCCESSFUL)
0117     return RTEMS_SUCCESSFUL;
0118   else {
0119     rw_args->bytes_moved = 0;
0120     return RTEMS_UNSATISFIED;
0121   }
0122 }