Pisound: MIDI communication fixes for scaled down CPU.
authorGiedrius <giedrius@blokas.io>
Tue, 7 Jan 2020 09:04:21 +0000 (11:04 +0200)
committerPhil Elwell <pelwell@users.noreply.github.com>
Tue, 7 Jan 2020 09:23:48 +0000 (09:23 +0000)
* Increased maximum SPI communication speed to avoid running too slow
  when the CPU is scaled down and losing MIDI data.

* Keep track of buffer usage in millibytes for higher precision.

Signed-off-by: Giedrius Trainavičius <giedrius@blokas.io>
sound/soc/bcm/pisound.c

index 2d73cf9..3c06f5a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Pisound Linux kernel module.
- * Copyright (C) 2016-2019  Vilniaus Blokas UAB, https://blokas.io/pisound
+ * Copyright (C) 2016-2020  Vilniaus Blokas UAB, https://blokas.io/pisound
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -326,7 +326,7 @@ static void spi_transfer(const uint8_t *txbuf, uint8_t *rxbuf, int len)
        transfer.tx_buf = txbuf;
        transfer.rx_buf = rxbuf;
        transfer.len = len;
-       transfer.speed_hz = 100000;
+       transfer.speed_hz = 150000;
        transfer.delay_usecs = 10;
        spi_message_add_tail(&transfer, &msg);
 
@@ -403,9 +403,9 @@ static struct spi_device *pisnd_spi_find_device(void)
 static void pisnd_work_handler(struct work_struct *work)
 {
        enum { TRANSFER_SIZE = 4 };
-       enum { PISOUND_OUTPUT_BUFFER_SIZE = 128 };
-       enum { MIDI_BYTES_PER_SECOND = 3125 };
-       int out_buffer_used = 0;
+       enum { PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES = 127 * 1000 };
+       enum { MIDI_MILLIBYTES_PER_JIFFIE = (3125 * 1000) / HZ };
+       int out_buffer_used_millibytes = 0;
        unsigned long now;
        uint8_t val;
        uint8_t txbuf[TRANSFER_SIZE];
@@ -445,7 +445,9 @@ static void pisnd_work_handler(struct work_struct *work)
                        had_data = false;
                        memset(txbuf, 0, sizeof(txbuf));
                        for (i = 0; i < sizeof(txbuf) &&
-                               out_buffer_used < PISOUND_OUTPUT_BUFFER_SIZE;
+                               ((out_buffer_used_millibytes+1000 <
+                               PISOUND_OUTPUT_BUFFER_SIZE_MILLIBYTES) ||
+                               g_ledFlashDurationChanged);
                                i += 2) {
 
                                val = 0;
@@ -458,7 +460,7 @@ static void pisnd_work_handler(struct work_struct *work)
                                } else if (kfifo_get(&spi_fifo_out, &val)) {
                                        txbuf[i+0] = 0x0f;
                                        txbuf[i+1] = val;
-                                       ++out_buffer_used;
+                                       out_buffer_used_millibytes += 1000;
                                }
                        }
 
@@ -469,12 +471,14 @@ static void pisnd_work_handler(struct work_struct *work)
                         * rate.
                         */
                        now = jiffies;
-                       out_buffer_used -=
-                               (MIDI_BYTES_PER_SECOND / HZ) /
-                               (now - last_transfer_at);
-                       if (out_buffer_used < 0)
-                               out_buffer_used = 0;
-                       last_transfer_at = now;
+                       if (now != last_transfer_at) {
+                               out_buffer_used_millibytes -=
+                                       (now - last_transfer_at) *
+                                       MIDI_MILLIBYTES_PER_JIFFIE;
+                               if (out_buffer_used_millibytes < 0)
+                                       out_buffer_used_millibytes = 0;
+                               last_transfer_at = now;
+                       }
 
                        for (i = 0; i < sizeof(rxbuf); i += 2) {
                                if (rxbuf[i]) {
@@ -489,6 +493,7 @@ static void pisnd_work_handler(struct work_struct *work)
                        || !kfifo_is_empty(&spi_fifo_out)
                        || pisnd_spi_has_more()
                        || g_ledFlashDurationChanged
+                       || out_buffer_used_millibytes != 0
                        );
 
                if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback)