Subversion Repositories svn.mios32

Rev

Rev 2531 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2531 tk 1
// $Id: seq_blm8x8.c 2532 2017-10-12 21:50:45Z tk $
2
/*
3
 * Button/LED Matrix Handler
4
 *
5
 * ==========================================================================
6
 *
7
 *  Copyright (C) 2017 Thorsten Klose (tk@midibox.org)
8
 *  Licensed for personal non-commercial use only.
9
 *  All other rights reserved.
10
 *
11
 * ==========================================================================
12
 */
13
 
14
/////////////////////////////////////////////////////////////////////////////
15
// Include files
16
/////////////////////////////////////////////////////////////////////////////
17
 
18
#include <mios32.h>
19
 
20
#include "seq_blm8x8.h"
2532 tk 21
#include "seq_hwcfg.h"
2531 tk 22
 
23
 
24
/////////////////////////////////////////////////////////////////////////////
25
// Global variables
26
/////////////////////////////////////////////////////////////////////////////
27
 
28
u8 seq_blm8x8_led_row[SEQ_BLM8X8_NUM][8];
29
 
30
 
31
/////////////////////////////////////////////////////////////////////////////
32
// Local variables
33
/////////////////////////////////////////////////////////////////////////////
34
 
35
static u8 seq_blm8x8_button_row[SEQ_BLM8X8_NUM][8];
36
static u8 seq_blm8x8_button_row_changed[SEQ_BLM8X8_NUM][8];
37
 
38
static u8 seq_blm8x8_current_row;
39
static u8 seq_blm8x8_debounce_ctr;
40
 
41
static seq_blm8x8_config_t seq_blm8x8_config[SEQ_BLM8X8_NUM];
42
 
43
/////////////////////////////////////////////////////////////////////////////
44
// Initialisation
45
/////////////////////////////////////////////////////////////////////////////
46
s32 SEQ_BLM8X8_Init(u32 mode)
47
{
48
  int blm;
49
 
50
  seq_blm8x8_config_t *config = (seq_blm8x8_config_t *)&seq_blm8x8_config[0];
51
  for(blm=0; blm<SEQ_BLM8X8_NUM; ++blm, ++config) {
52
    int i;
53
 
54
    for(i=0; i<8; ++i) {
55
      seq_blm8x8_led_row[blm][i] = 0x00;
56
      seq_blm8x8_button_row[blm][i] = 0xff;
57
      seq_blm8x8_button_row_changed[blm][i] = 0x00;
58
    }
59
 
60
    config->rowsel_dout_sr = 0;
61
    config->led_dout_sr = 0;
62
    config->button_din_sr = 0;
63
    config->rowsel_inv_mask = 0x00;
64
    config->col_inv_mask = 0x00;
65
    config->debounce_delay = 0;
66
  }
67
 
68
  seq_blm8x8_current_row = 0;
69
  seq_blm8x8_debounce_ctr = 0;
70
 
71
  return 0;
72
}
73
 
74
 
75
/////////////////////////////////////////////////////////////////////////////
76
// This function prepares the DOUT register to drive a row
77
// It should be called from the APP_SRIO_ServicePrepare
78
// IN: -
79
// OUT: returns -1 on errors
80
/////////////////////////////////////////////////////////////////////////////
81
s32 SEQ_BLM8X8_PrepareRow(void)
82
{
83
  // increment current row, wrap at 8
84
  if( ++seq_blm8x8_current_row >= 8 )
85
    seq_blm8x8_current_row = 0;
86
 
87
  u8 rowsel_value = ~(1 << seq_blm8x8_current_row);
88
 
89
  int blm;
90
  seq_blm8x8_config_t *config = (seq_blm8x8_config_t *)&seq_blm8x8_config[0];
91
  for(blm=0; blm<SEQ_BLM8X8_NUM; ++blm, ++config) {
92
    // cathode
93
    if( config->rowsel_dout_sr ) {
94
      MIOS32_DOUT_SRSet(config->rowsel_dout_sr - 1, rowsel_value ^ config->rowsel_inv_mask);
95
    }
96
 
97
    // anode
98
    if( config->led_dout_sr ) {
99
      MIOS32_DOUT_SRSet(config->led_dout_sr - 1, seq_blm8x8_led_row[blm][seq_blm8x8_current_row] ^ config->col_inv_mask);
100
    }
101
  }
102
 
103
  return 0;
104
}
105
 
106
/////////////////////////////////////////////////////////////////////////////
107
// This function gets the DIN values of the selected row
108
// It should be called from the APP_SRIO_ServiceFinish hook
109
// IN: -
110
// OUT: returns -1 on errors
111
/////////////////////////////////////////////////////////////////////////////
112
s32 SEQ_BLM8X8_GetRow(void)
113
{
114
  u8 scanned_row = seq_blm8x8_current_row ? (seq_blm8x8_current_row - 1) : (8 - 1);
115
 
116
  int blm;
117
  seq_blm8x8_config_t *config = (seq_blm8x8_config_t *)&seq_blm8x8_config[0];
118
 
119
  for(blm=0; blm<SEQ_BLM8X8_NUM; ++blm, ++config) {
120
 
121
    if( config->button_din_sr ) {
122
      u8 sr = config->button_din_sr - 1;
123
 
124
      // ensure that change won't be propagated to normal DIN handler
2532 tk 125
      u8 sr_value = MIOS32_DIN_SRGet(sr);
126
      if( blm == 2 && seq_hwcfg_blm8x8.dout_gp_mapping == 3 ) {
127
    // only first 4 bits are used by matrix
128
    MIOS32_DIN_SRChangedGetAndClear(sr, 0x0f);
129
    sr_value |= 0xf0;
130
      } else {
131
    MIOS32_DIN_SRChangedGetAndClear(sr, 0xff);
132
      }
2531 tk 133
 
134
      // cheap debounce handling. ignore any changes if debounce_ctr > 0
135
      if( !seq_blm8x8_debounce_ctr ) {
136
    // *** set change notification and new value. should not be interrupted ***
137
    MIOS32_IRQ_Disable();
138
 
139
    // if a second change happens before the last change was notified (clear
140
    // changed flags), the change flag will be unset (two changes -> original value)
141
    if( seq_blm8x8_button_row_changed[blm][scanned_row] ^= (sr_value ^ seq_blm8x8_button_row[blm][scanned_row]) ) {
142
      seq_blm8x8_debounce_ctr = config->debounce_delay; // restart debounce delay
143
    }
144
 
145
    // copy new values to seq_led_matrix_button_rows
146
    seq_blm8x8_button_row[blm][scanned_row] = sr_value;
147
    MIOS32_IRQ_Enable();
148
    // *** end atomic block ***
149
      } else {
150
    --seq_blm8x8_debounce_ctr; // decrement debounce control
151
      }
152
    }
153
  }
154
 
155
  return 0;
156
}
157
 
158
/////////////////////////////////////////////////////////////////////////////
159
// This function should be called from a task to check for button changes
160
// periodically. Events (change from 0->1 or from 1->0) will be notified
161
// via the given callback function <notify_hook> with following parameters:
162
//   <notifcation-hook>(u32 btn, u32 value)
163
// IN: -
164
// OUT: returns -1 on errors
165
/////////////////////////////////////////////////////////////////////////////
166
s32 SEQ_BLM8X8_ButtonHandler(void *_notify_hook)
167
{
168
  void (*notify_hook)(u8 blm, u32 pin, u32 value) = _notify_hook;
169
 
170
  // no hook?
171
  if( _notify_hook == NULL )
172
    return -2;
173
 
174
  int blm;
175
  for(blm=0; blm<SEQ_BLM8X8_NUM; ++blm) {
176
    int row;
177
 
178
    u8 *button_row = (u8 *)&seq_blm8x8_button_row[blm][0];
179
    u8 *button_row_changed = (u8 *)&seq_blm8x8_button_row_changed[blm][0];
180
 
181
    for(row=0; row<8; ++row, ++button_row, ++button_row_changed) {
182
      // *** fetch changed / values, reset changed. should not be interrupted ***
183
      MIOS32_IRQ_Disable();
184
      u8 changed = *button_row_changed;
185
      u8 values = *button_row;
186
      *button_row_changed = 0;
187
      MIOS32_IRQ_Enable();
188
      // *** end atomic block ***
189
 
190
      // check if any changes in this row
191
      if( !changed )
192
    continue;
193
 
194
      // ..walk pins and notify changes
195
      int pin;
196
      u8 pin_mask = 0x01;
197
      for(pin=0; pin < 8; ++pin, pin_mask <<= 1) {
198
        if( changed & pin_mask )
199
          notify_hook(blm, row*8 + pin, (values & pin_mask) ? 1 : 0);
200
      }
201
    }
202
  }
203
 
204
  return 0;
205
}
206
 
207
 
208
/////////////////////////////////////////////////////////////////////////////
209
// returns a button's state
210
// IN: button number
211
// OUT: button value (0 or 1), returns < 0 if button not available
212
/////////////////////////////////////////////////////////////////////////////
213
s32 SEQ_BLM8X8_ButtonGet(u8 blm, u32 button)
214
{
215
  if( blm >= SEQ_BLM8X8_NUM )
216
    return -1;
217
 
218
  if( button >= 64 )
219
    return -2;
220
 
221
  return (seq_blm8x8_button_row[blm][button/8] & (1 << (button % 8))) ? 1 : 0;
222
}
223
 
224
/////////////////////////////////////////////////////////////////////////////
225
// returns the buttons serial-register value for a row / SR
226
// IN: button row in <row>, row-SR in <sr>
227
// OUT: serial register value (0 if register not available)
228
/////////////////////////////////////////////////////////////////////////////
229
u8 SEQ_BLM8X8_ButtonSRGet(u8 blm, u8 row)
230
{
231
  if( blm >= SEQ_BLM8X8_NUM )
232
    return -1;
233
 
234
  if( row >= 8 )
235
    return -2;
236
 
237
  return seq_blm8x8_button_row[blm][row];
238
}
239
 
240
 
241
/////////////////////////////////////////////////////////////////////////////
242
// sets a LED's value
243
// IN: LED number in <led>, LED value in <value>
244
// OUT: returns < 0 if LED not available
245
/////////////////////////////////////////////////////////////////////////////
246
s32 SEQ_BLM8X8_LEDSet(u8 blm, u8 led, u8 value)
247
{
248
  if( blm >= SEQ_BLM8X8_NUM )
249
    return -1;
250
 
251
  if( led >= 64 )
252
    return -2;
253
 
254
  if( value ) {
255
    seq_blm8x8_led_row[blm][led/8] |= (1 << (led % 8));
256
  } else {
257
    seq_blm8x8_led_row[blm][led/8] &= ~(1 << (led % 8));
258
  }
259
 
260
  return 0; // no error
261
}
262
 
263
/////////////////////////////////////////////////////////////////////////////
264
// returns the status of a LED
265
// IN: LED number in <led>
266
// OUT: returns LED state value or < 0 if pin not available
267
/////////////////////////////////////////////////////////////////////////////
268
s32 SEQ_BLM8X8_LEDGet(u8 blm, u8 led)
269
{
270
  if( blm >= SEQ_BLM8X8_NUM )
271
    return -1;
272
 
273
  if( led >= 64 )
274
    return -2;
275
 
276
  return (seq_blm8x8_led_row[blm][led/8] & (1 << (led % 8))) ? 1 : 0;
277
}
278
 
279
/////////////////////////////////////////////////////////////////////////////
280
// returns the LED serial-register value for a row / SR
281
// IN: LED row in <row>, row-SR in <sr>
282
// OUT: serial register value (0 if register not available)
283
/////////////////////////////////////////////////////////////////////////////
284
u8 SEQ_BLM8X8_LEDSRGet(u8 blm, u8 row)
285
{
286
  if( blm >= SEQ_BLM8X8_NUM )
287
    return -1;
288
 
289
  if( row >= 8 )
290
    return -2;
291
 
292
  return seq_blm8x8_led_row[blm][row];
293
}
294
 
295
 
296
/////////////////////////////////////////////////////////////////////////////
297
// sets the LED serial-register value for a row / sr
298
// IN: LED row in <row>, row-SR in <sr>
299
// OUT: < 0 on error (SR not available), 0 on success
300
/////////////////////////////////////////////////////////////////////////////
301
s32 SEQ_BLM8X8_LEDSRSet(u8 blm, u8 row, u8 sr_value)
302
{
303
  if( blm >= SEQ_BLM8X8_NUM )
304
    return -1;
305
 
306
  if( row >= 8 )
307
    return -2;
308
 
309
  seq_blm8x8_led_row[blm][row] = sr_value;
310
 
311
  return 0; // no error
312
}
313
 
314
/////////////////////////////////////////////////////////////////////////////
315
// sets the seq_blm8x8 soft configurations
316
// IN: config, struct with members:
317
//    .rowsel_dout_sr
318
//    .led_dout_sr
319
//    .button_din_sr
320
//    .rowsel_inv_mask
321
//    .col_inv_mask
322
//    .debounce_delay
323
// OUT: returns < 0 on error, 0 on success
324
/////////////////////////////////////////////////////////////////////////////
325
s32 SEQ_BLM8X8_ConfigSet(u8 blm, seq_blm8x8_config_t config)
326
{
327
  if( blm >= SEQ_BLM8X8_NUM )
328
    return -1;
329
 
330
  seq_blm8x8_config[blm] = config;
331
 
332
  return 0; // no error
333
}
334
 
335
/////////////////////////////////////////////////////////////////////////////
336
// gets the seq_blm8x8 soft configurations
337
// IN: -
338
// OUT: struct with members:
339
//    .rowsel_dout_sr
340
//    .led_dout_sr
341
//    .button_din_sr
342
//    .rowsel_inv_mask
343
//    .col_inv_mask
344
//    .debounce_delay
345
/////////////////////////////////////////////////////////////////////////////
346
seq_blm8x8_config_t SEQ_BLM8X8_ConfigGet(u8 blm)
347
{
348
  if( blm >= SEQ_BLM8X8_NUM )
349
    blm = 0;
350
 
351
  return seq_blm8x8_config[blm];
352
}