Skip to content

Commit

Permalink
added text scrolling for the Midi Fighter 64
Browse files Browse the repository at this point in the history
  • Loading branch information
FMMT666 committed Aug 29, 2020
1 parent 5f4fe33 commit b99eaa3
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 8 deletions.
71 changes: 63 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ What's hot, what's not?

Launchpad Pro - class "LaunchpadPro()" LEDs and buttons (digitally only (yet))

Launchpad Pro - class "LaunchpadProMk3()" EXPERIMENTAL++ as in "some issues, but ok"
Launchpad Pro Mk3 - class "LaunchpadProMk3()" EXPERIMENTAL++ as in "should be ok"

Launchpad Mini Mk3 - class "LaunchpadMiniMk3()" LEDs and buttons *** RENAMED 5/2020 ***

Expand All @@ -52,7 +52,7 @@ What's hot, what's not?

Launch Control XL - class "LaunchControlXL()" LEDs, buttons and potentiometers

LaunchKey (Mini) - class "LaunchKeyMini()" Buttons, keys and potentiometers (sliders for big KBs), no LEDs
LaunchKey (Mini) - class "LaunchKeyMini()" Buttons, keys and potentiometers/sliders, no LEDs

Dicer - class "Dicer()" LEDs and buttons

Expand All @@ -63,8 +63,8 @@ What's hot, what's not?
> You need to disable the Launchpad's "Transmit Clock" in the MIDI settings!
> See section "For Launchpad Pro Mk3 users"
>
> Also, every program shall end with either calling lp.Close() or calling
> lp.SetLedMode( 0 ), to switch back to the Live mode.
> The Pro Mk3 needs the latest Firmware to operate flawlessly. FW is only available
> via a Novation account- and product registration.
Please notice that the class "LaunchpadMk3()" was renamed to "LaunchpadMiniMk3()" in 5/2020.
This was necessary to avoid confusion with the device search string and the new "Pro-Mk3" Launchpad.
Expand Down Expand Up @@ -107,6 +107,8 @@ Successfully tested with Ubuntu 18.04-LTS+. Requires compiling your own PyGame t
- updated pressure event handling in the Pro, Pro Mk3 and X's ButtonStateXY() methods
- added a Pro Mk3 "reset to Live mode" demo file
- updated ButtonStateXY() for the Pro Mk3, incl "classic" and "Pro" mode
- added character and string scrolling for Midi Fighter 64
- added stupid Midi Fighter text scrolling demo


### CHANGES 2020/05/XX:
Expand Down Expand Up @@ -1145,9 +1147,11 @@ Functions requiring a color code have a "...ByCode" naming style.

### LED functions

LedCtrlRaw()
LedCtrlXY()
LedAllOn()
LedCtrlRaw( number, color)
LedCtrlXY( x, y, color )
LedAllOn( [color] )
LedCtrlChar( char, color, [offsx], [offsy], [coloroff] )
LedCtrlString( string, color, [coloroff], [direction], [waitms] )


### Button functions
Expand Down Expand Up @@ -2312,6 +2316,57 @@ There is no possibility to control the RGB LEDs individually.yle.
RETURN:


### LedCtrlChar( char, color, offsx = 0, offsy = 0, coloroff = 0 )

Displays character <char> with a color of <color> and a
lateral offset of <offsx> (-8..8) on the Midi Fighter.
<offsy> does not have yet any function.
The optional <coloroff> parameter specifies the background color.
Notice that it is not possible to set this to "black" or off as the
Midi Fighter doesn't support this.

Also notice that this method is not compatible with the Launchpad "RGB-calls",
because the Midi Fighter also lacks RGB support. For 500 bucks. Lol :-)

lp.LedCtrlChar( 'a', 5, offsx = xvar, coloroff = 0 )

PARAMS: <char> one field string to display; e.g.: 'A'
<color> color of the character; see table and image somewhere above
<offsx> x offset of the character on the main, 8x8 matrix (-8..8)
Negative is left and positive right.
<offsy> no function
<coloroff> color of the background; see table and image somewhere above
RETURN:

EXAMPLES:
# scroll a red 'A' from left to right
for x in range( -8, 9 ):
lp.LedCtrlChar( 'A', 3, 0, offsx = x )
time.wait( 100 ) # from PyGame (from pygame import time)


### LedCtrlString( string, color, coloroff = 0, direction = 0, waitms = 150 )

Scrolls <string> across the Midi Fighter's 8x8 matrix.
<color> specifies the color of the string and <coloroff> the background.
<direction> determines the direction of scrolling.
<waitms>, by default 150, delays the scrolling speed.

For future compatibility, it is highly recommended to use
<direction> and <waitms> as a named arguments, e.g.:

lp.LedCtrlString( "Hello", 3,1, direction = -1, waitms = 100 )

PARAMS: <string> a string to display; e.g.: 'Hello'
<color> color of the character; see color table
<coloroff> color of the background; see color table
<direction> -1 -> scroll right to left
0 -> do not scroll, just show the character
1 -> scroll left to right
<waitms> OPTIONAL: delay for scrolling speed, default 150
RETURN:


### LedAllOn( <colorcode> )

Quickly sets all LEDs to white or a given <colorcode>.
Expand Down Expand Up @@ -2947,5 +3002,5 @@ FMMT666(ASkr)
[20]: https://github.com/FMMT666/launchpad.py/issues/38#issuecomment-519698406
[21]: https://twitter.com/FMMT666/status/1242950069923520519
[22]: https://twitter.com/FMMT666/status/1242978460454326272
[23]: https://twitter.com/FMMT666/status/1298372859383906305
[23]: https://twitter.com/FMMT666/status/1299842680533463043
[24]: https://twitter.com/FMMT666/status/1299478117497688073
1 change: 1 addition & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
!launchpad_rgb-pulse.py
!launchpad_pressure.py
!launchpad_pro_mk3_reset.py
!midifighter_text.py
!midi_events.py
!buttons_raw.py
!buttons_xy.py
60 changes: 60 additions & 0 deletions examples/midifighter_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
#
# Quick and dirty text test.
# Works with Midi Figther 64
#
#
# FMMT666(ASkr) 7/2013..8/2020
# www.askrprojects.net
#

import sys
import random
from pygame import time


try:
import launchpad_py as launchpad
except ImportError:
try:
import launchpad
except ImportError:
sys.exit("error loading launchpad.py")


def main():

mode = None

if launchpad.MidiFighter64().Check( 0 ):
lp = launchpad.MidiFighter64()
if lp.Open( 0 ):
print("Midi Fighter 64")
mode = "F64"

if mode is None:
print("Did not find any devices, meh...")
return


lp.LedAllOn( 103 )
time.wait(500)

lp.LedCtrlString( '500BUCKS', 21, coloroff=103, direction=-1, waitms=10 )
for i in range(10):
lp.LedAllOn( random.randint(0,127) )
time.wait(50)
lp.LedCtrlString( 'LOL', 5, coloroff=21, direction=-0, waitms=50 )

time.wait(50)
lp.LedAllOn( 103 )

print("bye ...")

lp.Reset() # turn all LEDs off
lp.Close() # close the Launchpad (will quit with an error due to a PyGame bug)


if __name__ == '__main__':
main()

68 changes: 68 additions & 0 deletions launchpad_py/launchpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -2900,6 +2900,74 @@ def LedCtrlXY( self, x, y, color ):
self.midi.RawWrite( 146, number, color )


#-------------------------------------------------------------------------------------
#-- Displays the character <char> with color of <colorcode> and lateral offset
#-- <offsx> (-8..8) on the Midi Fighter. <offsy> does not have yet any function.
#-- <coloroff> specifies the background color.
#-- Notice that the call to this method is not compatible to the Launchpad variants,
#-- because the Midi Fighter lacks support for RGB.
#-------------------------------------------------------------------------------------
def LedCtrlChar( self, char, colorcode, offsx = 0, offsy = 0, coloroff = 0 ):
char = ord( char )
char = min( char, 255)
char = max( char, 0) * 8

if colorcode < 0 or colorcode > 127:
return

for y in range( 64, 35, -4 ):
for x in range(8):
number = y + x + offsx
if x + offsx > 3:
number += 28 # +32-4

if x + offsx < 8 and x + offsx >= 0:
if CHARTAB[char] & 0x80 >> x:
self.LedCtrlRaw( number, colorcode )
else:
# lol, shit; there is no color code for "off"
self.LedCtrlRaw( number, coloroff )
char += 1


#-------------------------------------------------------------------------------------
#-- Scroll <string>, with color specified by <colorcode>, as fast as we can.
#-- <direction> specifies: -1 to left, 0 no scroll, 1 to right
#-- Notice that the call to this method is not compatible to the Launchpad variants,
#-- because the Midi Fighter lacks support for RGB.
#-------------------------------------------------------------------------------------
def LedCtrlString( self, string, colorcode, coloroff=0, direction = None, waitms = 150 ):

limit = lambda n, mini, maxi: max(min(maxi, n), mini)

if direction == self.SCROLL_LEFT:
string += " " # just to avoid artifacts on full width characters
for n in range( (len(string) + 1) * 8 ):
if n <= len(string)*8:
self.LedCtrlChar( string[ limit( ( n //16)*2 , 0, len(string)-1 ) ], colorcode, 8- n %16, coloroff = coloroff )
if n > 7:
self.LedCtrlChar( string[ limit( (((n-8)//16)*2) + 1, 0, len(string)-1 ) ], colorcode, 8-(n-8)%16, coloroff = coloroff )
time.wait(waitms)
elif direction == self.SCROLL_RIGHT:
# TODO: Just a quick hack (screen is erased before scrolling begins).
# Characters at odd positions from the right (1, 3, 5), with pixels at the left,
# e.g. 'C' will have artifacts at the left (pixel repeated).
string = " " + string + " " # just to avoid artifacts on full width characters
# for n in range( (len(string) + 1) * 8 - 1, 0, -1 ):
for n in range( (len(string) + 1) * 8 - 7, 0, -1 ):
if n <= len(string)*8:
self.LedCtrlChar( string[ limit( ( n //16)*2 , 0, len(string)-1 ) ], colorcode, 8- n %16, coloroff = coloroff )
if n > 7:
self.LedCtrlChar( string[ limit( (((n-8)//16)*2) + 1, 0, len(string)-1 ) ], colorcode, 8-(n-8)%16, coloroff = coloroff )
time.wait(waitms)
else:
# TODO: not a good idea :)
for i in string:
for n in range(4): # pseudo repetitions to compensate the timing a bit
self.LedCtrlChar(i, colorcode)
time.wait(waitms)


#-------------------------------------------------------------------------------------
#-- Sets all LEDs to the same color, specified by <color>.
#-- If color is omitted, the LEDs are set to white (code 3)
Expand Down

0 comments on commit b99eaa3

Please sign in to comment.