Skip to content

Commit faec030

Browse files
committed
added some methods for the Midi Fighter 64
1 parent cdc3421 commit faec030

File tree

6 files changed

+206
-26
lines changed

6 files changed

+206
-26
lines changed

README.md

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Did we mention [Python 3][18] yet?
2323

2424
First [Mk3][21] and [X][22] Launchpad code snippets running now (4/2020).
2525

26-
Now with a bit of Midi Fighter 64 support (8/2020).
26+
Now with a bit of [Midi Fighter 64][23] support (8/2020).
2727

2828

2929
---
@@ -53,7 +53,7 @@ What's hot, what's not?
5353

5454
Dicer - class "Dicer()" LEDs and buttons
5555

56-
Midi Fighter 64 - class "MidiFighter64" EXPERIMENTAL; only raw buttons
56+
Midi Fighter 64 - class "MidiFighter64" EXPERIMENTAL; LEDs and buttons; growing
5757

5858

5959
Please notice that the class "LaunchpadMk3()" was renamed to "LaunchpadMiniMk3()" in 5/2020.
@@ -87,6 +87,7 @@ Successfully tested with Ubuntu 18.04-LTS+. Requires compiling your own PyGame t
8787
- changed ListAll() method to optionally accept a string to query specific devices only
8888
- added a general midi_events.py demo file for better debugging
8989
- added a class for the Midi Fighter 64, only (raw) buttons so far
90+
- added MF64 LedCtrlRaw(), ButtonStateXY(), LedAllOn()
9091

9192
### CHANGES 2020/05/XX:
9293

@@ -1100,12 +1101,22 @@ Functions requiring a color code have a "...ByCode" naming style.
11001101

11011102
### LED functions
11021103

1103-
TODO
1104+
LedCtrlRaw()
1105+
LedAllOn()
11041106

11051107

11061108
### Button functions
11071109

11081110
ButtonStateRaw()
1111+
ButtonStateXY()
1112+
1113+
1114+
### Color codes
1115+
1116+
The Midi Fighter 64 only supports a color table.
1117+
There is no possibility to control the RGB LEDs individually.yle.
1118+
1119+
![RGB color palette](/images/mf64_colorcodes.png)
11091120

11101121

11111122

@@ -2211,14 +2222,48 @@ Functions requiring a color code have a "...ByCode" naming style.
22112222
### ButtonStateRaw()
22122223

22132224
Returns the state of the buttons in RAW mode.
2225+
See table with button and LED numbers at the end of this document.
22142226

22152227
PARAMS:
22162228
RETURN: [ ] An empty list if no event occured, otherwise...
22172229
[ <button>, <value> ] ... a list with two fields:
2218-
<button> is the RAW button number (see tables at end of doc)
2230+
<button> is the RAW button number
2231+
<value> >0 = pressed; 0 = released
2232+
2233+
2234+
### ButtonStateXY()
2235+
2236+
Returns the state of the buttons in X/Y mode.
2237+
See table with coordinates at the end of this document.
2238+
2239+
PARAMS:
2240+
RETURN: [ ] An empty list if no event occured, otherwise...
2241+
[ <x> , <y>, <value> ] ... a list with three fields:
2242+
<x> 0..7; x coordinate of button
2243+
<y> 0..7; y coordinate of button
22192244
<value> >0 = pressed; 0 = released
22202245

22212246

2247+
### LedCtrlRaw( <button>, <colorcode> )
2248+
2249+
Controls an LED via its number <button> and <colorcode>.
2250+
See table with button number at the end of this document.
2251+
Color codes are somewhere above (see image).
2252+
2253+
PARAMS: <button> 36..99; number of the LED to control
2254+
<colorcode> 0..127; color code
2255+
RETURN:
2256+
2257+
2258+
### LedAllOn( <colorcode> )
2259+
2260+
Quickly sets all LEDs to white or a given <colorcode>.
2261+
Notice that it is not (yet) possible to turn the LEDs off.
2262+
The Midi Fighter's color table does not include "black" or off.
2263+
2264+
PARAMS: <colorcode> 0..127; color code
2265+
RETURN:
2266+
22222267

22232268

22242269
---
@@ -2673,7 +2718,7 @@ The mode keys return:
26732718

26742719

26752720
---
2676-
## (TODO) Button codes, Midi Fighter 64
2721+
## (TODO) Led and Button codes, Midi Fighter 64
26772722

26782723
### RAW Mode
26792724

@@ -2746,4 +2791,4 @@ FMMT666(ASkr)
27462791
[20]: https://github.com/FMMT666/launchpad.py/issues/38#issuecomment-519698406
27472792
[21]: https://twitter.com/FMMT666/status/1242950069923520519
27482793
[22]: https://twitter.com/FMMT666/status/1242978460454326272
2749-
2794+
[23]: https://twitter.com/FMMT666/status/1298372859383906305

examples/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
!launchpad_pressure.py
1111
!midi_events.py
1212
!buttons_raw.py
13+
!buttons_xy.py

examples/buttons_xy.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python
2+
#
3+
# Quick button test.
4+
# Works with these Launchpads: Mk1, Mk2, Mini Mk3, S/Mini, Pro
5+
# And these: Midi Figther 64
6+
#
7+
#
8+
# FMMT666(ASkr) 7/2013..8/2020
9+
# www.askrprojects.net
10+
#
11+
12+
import sys
13+
import time
14+
15+
16+
try:
17+
import launchpad_py as launchpad
18+
except ImportError:
19+
try:
20+
import launchpad
21+
except ImportError:
22+
sys.exit("error loading launchpad.py")
23+
24+
25+
def main():
26+
27+
mode = None
28+
29+
if launchpad.LaunchpadPro().Check( 0 ):
30+
lp = launchpad.LaunchpadPro()
31+
if lp.Open( 0 ):
32+
print("Launchpad Pro")
33+
mode = "Pro"
34+
35+
elif launchpad.LaunchpadMiniMk3().Check( 1 ):
36+
lp = launchpad.LaunchpadMiniMk3()
37+
if lp.Open( 1 ):
38+
print("Launchpad Mini Mk3")
39+
mode = "Pro"
40+
41+
elif launchpad.LaunchpadLPX().Check( 1 ):
42+
lp = launchpad.LaunchpadLPX()
43+
if lp.Open( 1 ):
44+
print("Launchpad X")
45+
mode = "Pro"
46+
47+
elif launchpad.LaunchpadMk2().Check( 0 ):
48+
lp = launchpad.LaunchpadMk2()
49+
if lp.Open( 0 ):
50+
print("Launchpad Mk2")
51+
mode = "Mk2"
52+
53+
# elif launchpad.LaunchControlXL().Check( 0 ):
54+
# lp = launchpad.LaunchControlXL()
55+
# if lp.Open( 0 ):
56+
# print("Launch Control XL")
57+
# mode = "XL"
58+
59+
# elif launchpad.LaunchKeyMini().Check( 0 ):
60+
# lp = launchpad.LaunchKeyMini()
61+
# if lp.Open( 0 ):
62+
# print("LaunchKey (Mini)")
63+
# mode = "LKM"
64+
65+
elif launchpad.Dicer().Check( 0 ):
66+
lp = launchpad.Dicer()
67+
if lp.Open( 0 ):
68+
print("Dicer")
69+
mode = "Dcr"
70+
71+
elif launchpad.MidiFighter64().Check( 0 ):
72+
lp = launchpad.MidiFighter64()
73+
if lp.Open( 0 ):
74+
print("Midi Fighter 64")
75+
mode = "F64"
76+
77+
else:
78+
if lp.Open():
79+
print("Launchpad Mk1/S/Mini")
80+
mode = "Mk1"
81+
82+
if mode is None:
83+
print("Did not find any Launchpads, meh...")
84+
return
85+
86+
print("QUIT: That's on the TODO list. For now, just hit CTRL-C ...")
87+
88+
while True:
89+
buts = lp.ButtonStateXY()
90+
if buts != []:
91+
print( buts[0], buts[1], buts[2])
92+
93+
print("bye ...")
94+
95+
lp.Reset() # turn all LEDs off
96+
lp.Close() # close the Launchpad (will quit with an error due to a PyGame bug)
97+
98+
99+
if __name__ == '__main__':
100+
main()
101+

examples/launchpad_pro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def main():
3737
print( " - PyGame " + str( pygame.ver ) )
3838

3939
# create an instance
40-
lp = launchpad.LaunchpadPro();
40+
lp = launchpad.LaunchpadPro()
4141

4242
# open the first Launchpad Pro
4343
if lp.Open( 0, "pad pro" ):

images/mf64_colorcodes.png

412 KB
Loading

launchpad_py/launchpad.py

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,7 +2742,7 @@ def ButtonStateRaw( self, returnPressure = False ):
27422742
class MidiFighter64( LaunchpadBase ):
27432743

27442744
#
2745-
# BUTTON NUMBERS IN RAW MODE
2745+
# LED AND BUTTON NUMBERS IN RAW MODE
27462746
#
27472747
# +---+---+---+---+---+---+---+---+
27482748
# | 64| | | 67| 96| | | 99|
@@ -2805,6 +2805,29 @@ def Check( self, number = 0, name = "Fighter 64" ):
28052805
return super( MidiFighter64, self ).Check( number = number, name = name )
28062806

28072807

2808+
#-------------------------------------------------------------------------------------
2809+
#-- Controls a grid LED by its <number> and a <color>.
2810+
#-- <number> 36..99
2811+
#-- <color> 0..127 from color table
2812+
#-------------------------------------------------------------------------------------
2813+
def LedCtrlRaw( self, number, color ):
2814+
2815+
if number < 36 or number > 99:
2816+
return
2817+
if color < 0 or color > 127:
2818+
return
2819+
2820+
self.midi.RawWrite( 146, number, color )
2821+
2822+
2823+
#-------------------------------------------------------------------------------------
2824+
#-- Sets all LEDs to the same color, specified by <color>.
2825+
#-- If color is omitted, the LEDs are set to white (code 3)
2826+
#-------------------------------------------------------------------------------------
2827+
def LedAllOn( self, color = 3 ):
2828+
for i in range(64):
2829+
self.LedCtrlRaw( i+36, color )
2830+
28082831

28092832
#-------------------------------------------------------------------------------------
28102833
#-- Returns the raw value of the last button change (pressed/unpressed) as a list
@@ -2851,29 +2874,39 @@ def ButtonStateRaw( self ):
28512874
#-- <velocity> the state of the button.
28522875
#-- >0 = button pressed; 0 = button released
28532876
#-------------------------------------------------------------------------------------
2854-
# TODO
2855-
# def ButtonStateXY( self ):
2856-
# if self.midi.ReadCheck():
2857-
# a = self.midi.ReadRaw()
2877+
def ButtonStateXY( self ):
2878+
if self.midi.ReadCheck():
2879+
a = self.midi.ReadRaw()
28582880

2859-
# # Mhh, I guess it's about time to think about adding MIDI channels, isn't it?
2860-
# # But for now, we just check ch 2 and 3:
2861-
# if a[0][0][0] == 145 or a[0][0][0] == 146:
2862-
# return [ a[0][0][1], a[0][0][2] ]
2863-
# else:
2864-
# if a[0][0][0] == 130 or a[0][0][0] == 129:
2865-
# return [ a[0][0][1], 0 ]
2866-
# else:
2867-
# return []
2868-
# else:
2869-
# return []
2881+
# whatever that is, does not belong here...
2882+
if a[0][0][1] < 36 or a[0][0][1] > 99:
2883+
return []
2884+
2885+
x = (a[0][0][1] - 36) % 4
2886+
if a[0][0][1] >= 68:
2887+
x += 4
2888+
y = 7 - ( (a[0][0][1] - 36) % 32 ) // 4
2889+
2890+
if a[0][0][0] == 145 or a[0][0][0] == 146:
2891+
return [ x, y, a[0][0][2] ]
2892+
else:
2893+
if a[0][0][0] == 130 or a[0][0][0] == 129:
2894+
return [ x, y, 0 ]
2895+
else:
2896+
return []
2897+
else:
2898+
return []
28702899

28712900

28722901
#-------------------------------------------------------------------------------------
28732902
#-- Reset the Midi Fighter
2874-
#-- Turn off all LEDs
2903+
#-- Well, at least turn off all its LEDs
28752904
#-------------------------------------------------------------------------------------
2876-
# TODO
28772905
def Reset( self ):
2906+
# TODO
2907+
# Nope, there's not color code for "off".
2908+
# Brightness can be set via channel 4, though it's not clear
2909+
# if that helps us here, as the manual files this under "animation settings".
2910+
# Also, setting the brightness to 0/off might cause additional trouble.
2911+
# self.LedAllOn( 0 )
28782912
pass
2879-

0 commit comments

Comments
 (0)