1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 8f06522..7320f8b 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -240,3 +240,4 @@ test_touchscreen.c
 #endif
 test_viewports.c
 #endif
+test_fps.c
diff --git a/firmware/target/arm/as3525/dbop-as3525.c b/firmware/target/arm/as3525/dbop-as3525.c
index 66202b7..5e7b7bd 100644
--- a/firmware/target/arm/as3525/dbop-as3525.c
+++ b/firmware/target/arm/as3525/dbop-as3525.c
@@ -21,6 +21,7 @@

 #include "config.h"
 #include <inttypes.h>
+#include "kernel.h"
 #include "as3525.h"
 #include "dbop-as3525.h"

@@ -30,6 +31,51 @@
 #define DBOP_PRECHARGE 0xF0FF
 #endif

+static struct wakeup dbop_wakeup;
+static struct semaphore dbop_sem;
+static struct event_queue dbop_ev;
+
+static char dbop_thread_name[] = "dbop";
+static long dbop_thread_stack[(DEFAULT_STACK_SIZE+0x200) / sizeof(long)];
+
+struct dbop_ctx {
+    const int16_t *ptr;
+    int count;
+};
+
+static void dbop_write_data_ex(const int16_t *p, int count);
+static void dbop_thread(void)
+{
+    struct queue_event ev;
+    struct dbop_ctx c;
+    while(1)
+    {
+        queue_wait(&dbop_ev, &ev);
+        c = *(struct dbop_ctx*)ev.data;
+        dbop_write_data_ex(c.ptr, c.count);
+        semaphore_release(&dbop_sem);
+    }
+}
+
+void dbop_init(void)
+{
+    wakeup_init(&dbop_wakeup);
+    semaphore_init(&dbop_sem, 1, 0);
+    queue_init(&dbop_ev, true);
+
+    create_thread(dbop_thread, dbop_thread_stack, sizeof(dbop_thread_stack),
+                       0, dbop_thread_name IF_PRIO(, PRIORITY_REALTIME)
+                       IF_COP(, CPU));
+}
+
+
+void INT_DBOP(void)
+{
+    DBOP_CTRL &= ~(1<<11);
+    wakeup_signal(&dbop_wakeup);
+}
+
+
 #if CONFIG_CPU == AS3525
 /* doesn't work with the new ams sansas so far and is not needed */
 static short int dbop_input_value = 0;
@@ -142,9 +188,9 @@ static inline void dbop_set_mode(int mode)
     while(delay--) asm volatile("nop");
 }

-void dbop_write_data(const int16_t* p_bytes, int count)
+
+static void dbop_write_data_ex(const int16_t* p_bytes, int count)
 {
-    
     const int32_t *data;
     if ((intptr_t)p_bytes & 0x3 || count == 1)
     {   /* need to do a single 16bit write beforehand if the address is
@@ -166,7 +212,11 @@ void dbop_write_data(const int16_t* p_bytes, int count)
         count -= 2;

         /* Wait if push fifo is full */
-        while ((DBOP_STAT & (1<<6)) != 0);
+        if (DBOP_STAT & (1<<6))
+        {
+            DBOP_CTRL |= 1<<11|1<<7; /* enable almost-empty-irq */
+            wakeup_wait(&dbop_wakeup, TIMEOUT_BLOCK);
+        }
     }
     /* While push fifo is not empty */
     while ((DBOP_STAT & (1<<10)) == 0);
@@ -176,3 +226,21 @@ void dbop_write_data(const int16_t* p_bytes, int count)
     if (count > 0)
         dbop_write_data((int16_t*)data, 1);
 }
+
+void dbop_write_data(const int16_t* p_bytes, int count)
+{
+    static struct dbop_ctx c;
+    
+    semaphore_wait(&dbop_sem);
+    if (count == 1)
+    { /* don*t bother with the thread for small transfers */
+        dbop_set_mode(16);
+        DBOP_DOUT16 = *p_bytes;
+        semaphore_release(&dbop_sem);
+        return;
+    }
+    c.ptr = p_bytes;
+    c.count = count;
+    /* async transfer from here */
+    queue_post(&dbop_ev, 0, (intptr_t)(&c));
+}
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index dbbe1a1..730ca32 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -124,6 +124,7 @@ struct vec_int_src vec_int_srcs[] =
 #ifdef HAVE_RECORDING
     { INT_SRC_I2SIN, INT_I2SIN, },
 #endif
+    { INT_SRC_DBOP, INT_DBOP },
 };

 static void setup_vic(void)
@@ -365,6 +366,9 @@ void system_init(void)

     ascodec_init();

+    void dbop_init(void);
+    dbop_init();
+
 #ifndef BOOTLOADER
     /* setup isr for microsd monitoring and for scrollwheel irq */
 #if defined(HAVE_MULTIDRIVE) || (defined(HAVE_SCROLLWHEEL) && CONFIG_CPU != AS3525)