diff --git a/Changelog b/Changelog index df362bab3..52538da78 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,187 @@ +MCL 4.50 24/07/2023 + +Please install Machinedrum OS X.09 & Monomachine OS X.01 before using MCL 4.50. + +- Performance Page + Performance Controllers + A new Performance Page has been added featuring 8 Scenes (1->8) that are shared + between 4 user programmable Performance Controllers (A,B,C,D). + + Each Controller can be assigned two scenes. Press either [LEFT] or [RIGHT] and then + a corresponding Scene Trig to assign the left-most and right-most Scenes to the Controller. + + Rotating a Performance Controller will morph between values across the assigned scenes. + [ Func ] + Rotate for Controller hard pan. + + Each scene can have up to 16 "Scene Locks". + + A Scene lock can be any MD parameter, or any external MIDI CC parameter. + + To assign a lock to a scene, hold the corresponding Scene Trig and rotate the desired + parameter on the MD or external MIDI. + + Controllers A,B,C,D can be controlled externally by any MD parameter, or any MIDI CC. + + A parameter "LEARN" feature can be enable by setting Dest to "--" and Para to "LER". + + Performance Controller Names can be customized from the Performance Page's "Shift" menu. + + A new slot "PF", has been added to the Grid Y, slot 12. + + Performance Controllers and their shared Scene data can be saved or loaded to this slot. + + Mixer Page, Mute Sets and Performance Controller Locks are also stored in the PF. + +- Mixer Page: + + The [Scale] button can be used to toggle between the MD or Ext MIDI tracks. + + [Trig] + [Classic/Extended] is now Track Parameter Reset. + + [Trig] + [YES] or [YES] + [Trig] to toggle mutes. + + [Trig] + [NO] to solo tracks. + + [Func] + [YES] to flip mutes. + + [Trig] + [Global] record sequencer mutes. + [Trig] + [Kit] clear track's sequencer mutes. + [Global + Kit] clear all track's sequencer mutes. + + The 4 Encoders of the Mixer Page are now Performance Controllers (A,B,C,D). + + The Mixer Page now features 4 "Mute Sets" assigned to the MD's Arrow Keys. + + To load a Mute Set, hold down an Arrow Key and press [YES] + To edit a Mute Set, hold down an Arrow Key and toggle Trig Keys. + + Each Mute Set also includes Performance Controller Locks. + + To set a Performance Controller lock, hold down an [Arrow] key followed by [Exit/No] and + rotate the respective encoder. + +- Chromatic Page: + + [Scale] button can be used to toggle between devices. + + When the MIDI device is active, the MD's [Trig] keys can now be used to play External MIDI. + + Sequencer menu option, TRANSPOSE renamed to KEY. Now show's note A,A#,B,B#,C etc.. + + Oct and Fine Tune values are now device independent. + +- Sequencer: + + The MD's kit parameters are no longer updated when parameter locks or + LFO data is sent from MCL. + + Improved track expansion. When a Track's length is increased, the existing + pattern will be copied and filled across the new length. + + Step menu has been deprecated. + + Step mutes are now shown when editing the Pattern Mask. + + [ Trig ] + [ No ] to toggle step mutes + + Exiting Step Edit by pressing [ Record ] will now take you back to the last MCL Page. + +- Piano Roll + + A number of bug fixes related to missing notes, or unpredictable note + length. + + Quantization record could lead to incorrect note length. + + Zoom is now cursor relative. + + Added "CC REC" option to enable/disable recording of automation data. + + The MD's scale menu can be used to set the speed and length of Ext MIDI tracks (up to 64 steps). + + Program Change automation is now oneshot, and only a single change is permitted per parameter. + + Various GUI improvements. + +- Arpeggiator + + Improved ARP Latch mode, Latch is reset upon next note when all keys are + released. + + More ARP Speeds are available. + + Arpeggiator can play on beat, or freely depending on "QUANT" Sequencer Menu option. + +- LFO + + The LFO performance has been improved. + + The assignable Destinations now include External MIDI CCs. + + Parameter Learn is supported: set Dest to "--" and Param to "LEARN". + + An additional LFO sub page has been added to modify the LFO Offset for MIDI CC parameters. + +- Grid Page + + [ Scale ] button to toggle between Grids X and Y. + + Slots selection can now extend across both Grids allowing Clear/Copy/Paste commands to apply to + both Grids simultaneously. This also includes slot parameter updates. + + Insert Rows option has been deprecated. + + Added a throttle to the [YES] key to prevent accidental double tap. + + Empty tracks can now have customizable Length and Loop values adjustable via slot menu. + +- Sound Browser + + The functionality to Save and Load MD Sounds is now separated from Sample + Management. + + The dedicated Sound Browser is accessible from the Step Sequencer Track Menu. + +- Sample Browser + + GUI has been improved significantly to allow ease of navigation. + + .WAV and .SYX formats are detected automatically. + + File names increased to 32 characters. 256 files can be listed per directory. + +- Save: + + Sequencer mutes are stored with MD tracks. Saving MD track will cause the mute state to be applied + to the active sequence and stored. where a mute is present, the trig and lock mask will be removed. + +- Group Select + + The Group Select menu has been updated. + + Accessible by entering Load/Save page and holding [YES] + + The Selectable Groups are now: + - MD, MIDI, PERFORMANCE, ROUTE, TEMPO. + + The MD FX slot is now always loaded with MD group. + + LFO and Performance Slots (PF) are loaded with the PERFORMANCE group. + +- Transitions + Slot Loading: + + MDFX data is now cached ahead of time and loaded immediately on transition. + +- Func + Ext + + The MD's undokit is now synced per track. Previously all tracks were synced to the undokit + leading to unexpected behaviour when performing [ Func + Ext ]. + + The MD's LEV values are no longer reset by [ Func + Ext ] + +- Page Select + + Page Select layout has changed to accommodate the Performance Page. + MCL 4.43 13/04/2023 - Fixes @@ -52,7 +236,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl - Fixes - Grid Page: Allow length adustment across multiple slots when slot speeds are the + Grid Page: Allow length adjustment across multiple slots when slot speeds are the same. Program Change Advanced mode did not work over USB MIDI @@ -71,7 +255,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl GUI input from MD's trig keys would sometimes be unreliable. - Changes: - Improved overall framerate and responsiveness of MCL particulary on the Grid Page. + Improved overall framerate and responsiveness of MCL particularly on the Grid Page. Overhauled the method in which MD tracks are loaded such that there are no dropped notes during transitions. @@ -110,7 +294,7 @@ Perform the USB DFU firmware procedure to upgrade the USB microcontroller for cl Loop points are now stored in saved .wav file(s) when receiving looped SDS samples. - MCL Sequencer now supports triggering and recording from a dedicated MIDI channel via an external drump pad. See MD MIDI -> TRIG CHAN. + MCL Sequencer now supports triggering and recording from a dedicated MIDI channel via an external drum pad. See MD MIDI -> TRIG CHAN. - USB MIDI: @@ -165,7 +349,7 @@ Please install Machinedrum OS X.06 before using MCL 4.11 Project rename was broken in 4.10 - Kit and sequencer params weren't updated during a paramater change on linked/poly tracks. + Kit and sequencer params weren't updated during a parameter change on linked/poly tracks. This could cause incorrect value reset on sequencer stop. Piano Roll track menu would incorrectly show "clear track message" in certain circumstances. @@ -326,13 +510,13 @@ MCL 4.00 21/08/2021 MCL 4.00 is an significant achieviement. It builds upon the foundations of the 3.XX firmware, whilst improving stability, performance and workflow across several key areas. The Machinedrum and MCL integration is now closer than ever. -In short, MCL 4.0 achieves the original vision of the project, a seemless +In short, MCL 4.0 achieves the original vision of the project, a seamless enhancement of the Elektron Machinedrum. It is recommended that you read the updated user documentation in which many of the changes listed below, are explained in greater detail. -- Enhanced GUI / Machinedrum GUI convergance. +- Enhanced GUI / Machinedrum GUI convergence. Version X.05 of the MD firmware introduces a third editing mode beyond Classic and Extended entitled Enhanced Mode. @@ -344,12 +528,12 @@ many of the changes listed below, are explained in greater detail. Enhanced mode enables the Machinedrum's GUI to be fully integrated in to the MCL workflow All MD sequencer editing commands now apply to the MCL sequencer. - See the MCL 4.0 user documenation for a summary of commands. + See the MCL 4.0 user documentation for a summary of commands. - Changes: Chain Mode renamed to Load Mode. - Grids A/B are now relabelled to X/Y. - Grid rows are no longer labelled numerically and instead represented by the corresponding + Grids A/B are now relabeled to X/Y. + Grid rows are no longer labeled numerically and instead represented by the corresponding Bank + Pattern. @@ -802,7 +986,7 @@ MCL 3.00 20/12/2020 on the MC the MD's LEDs will illuminate according to the pattern sequence on the MC. The MD's cursor (indicating current sequence position) will also be - illimunated during playblack. The cursor is synced to the MD's current pattern speed + length. + illuminated during playback. The cursor is synced to the MD's current pattern speed + length. When using the Trig Interface to select tracks, the LEDs will illuminate appropriately. @@ -1146,7 +1330,7 @@ General: - Fix: SeqExtPage bad character glitch - Fix: SeqParam page showing param values offset by 1. - Fix: SeqParam page not allowing selection of all 24 params -- Fix: reolution bug causing glitched track length for A4/Ext tracks +- Fix: resolution bug causing glitched track length for A4/Ext tracks - Fix: Grid copy + paste was broken. Would not copy sequencer data correctly. - Diversion track for MDExploit no longer fixed to track 16, will be calculated dynamically diff --git a/art/animations/analog_frames/pixil-frame-0.png b/art/animations/analog_frames/pixil-frame-0.png new file mode 100644 index 000000000..8df0c738b Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-0.png differ diff --git a/art/animations/analog_frames/pixil-frame-1.png b/art/animations/analog_frames/pixil-frame-1.png new file mode 100644 index 000000000..f0be27264 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-1.png differ diff --git a/art/animations/analog_frames/pixil-frame-2.png b/art/animations/analog_frames/pixil-frame-2.png new file mode 100644 index 000000000..25c890cf3 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-2.png differ diff --git a/art/animations/analog_frames/pixil-frame-3.png b/art/animations/analog_frames/pixil-frame-3.png new file mode 100644 index 000000000..5cbd00451 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-3.png differ diff --git a/art/animations/analog_frames/pixil-frame-4.png b/art/animations/analog_frames/pixil-frame-4.png new file mode 100644 index 000000000..3ed601cd3 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-4.png differ diff --git a/art/animations/analog_frames/pixil-frame-5.png b/art/animations/analog_frames/pixil-frame-5.png new file mode 100644 index 000000000..24598a397 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-5.png differ diff --git a/art/animations/analog_frames/pixil-frame-6.png b/art/animations/analog_frames/pixil-frame-6.png new file mode 100644 index 000000000..5d9b00f16 Binary files /dev/null and b/art/animations/analog_frames/pixil-frame-6.png differ diff --git a/art/animations/analog_logo_7frames.pixil b/art/animations/analog_logo_7frames.pixil new file mode 100644 index 000000000..96d4b1ed4 --- /dev/null +++ b/art/animations/analog_logo_7frames.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":18,"height":9,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFRJREFUKFPdkdsKACAIQ+f/f7RhMJimRK/1lJcOazMADjnuqdRRuptZrhUUkLoQ212/9gK7JehAVRF8gx2g7msB+wBEvxjJs0dTOs+pUcFk9qSU7xb4/GAB19w9sAAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"q1ptki","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFRJREFUKFPdkdsKACAIQ+f/f7RhMJimRK/1lJcOazMADjnuqdRRuptZrhUUkLoQ212/9gK7JehAVRF8gx2g7msB+wBEvxjJs0dTOs+pUcFk9qSU7xb4/GAB19w9sAAAAABJRU5ErkJggg==","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFBJREFUKFPdkcEKADAIQvX/P7rhIVhNgrHbOoq9SAkg0CbikIqDZF+BlLIliDPuuvMUUDfn2QRPMAtyrwn2AUjZ7O9dZ5SA59aypSlsedyhBVEgYAErhum4AAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"0kz1nn","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFBJREFUKFPdkcEKADAIQvX/P7rhIVhNgrHbOoq9SAkg0CbikIqDZF+BlLIliDPuuvMUUDfn2QRPMAtyrwn2AUjZ7O9dZ5SA59aypSlsedyhBVEgYAErhum4AAAAAElFTkSuQmCC","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEZJREFUKFNjZGBg+M+AA/z/jynFyMiIVTVIFKtBIEOwacIljtUgZMXIroIZjM0wvAbh8towMAgUPRSFEcwAimMNllBISUcAwAxIAdGY1/8AAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"y5ddtt","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEZJREFUKFNjZGBg+M+AA/z/jynFyMiIVTVIFKtBIEOwacIljtUgZMXIroIZjM0wvAbh8towMAgUPRSFEcwAimMNllBISUcAwAxIAdGY1/8AAAAASUVORK5CYII=","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEpJREFUKFNjZGBg+M+AB/z/j5BmZGTEqRIkg9MgkCHImtH5yKbiNAhZEy42SQahew2Xqwi6aPAZBAoHisII3QBsfKICG6aI2HQEAGy0SAHtO+EoAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"8830lm","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEpJREFUKFNjZGBg+M+AB/z/j5BmZGTEqRIkg9MgkCHImtH5yKbiNAhZEy42SQahew2Xqwi6aPAZBAoHisII3QBsfKICG6aI2HQEAGy0SAHtO+EoAAAAAElFTkSuQmCC","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAERJREFUKFNjZGBg+M9AAPz//5+BkZERryqQLF6DYIYQMgyvQeia8RlGlEHEuGqIGgSLLrLDCGQAMeEDUkcw+pENw5eQAIbMQgEfHdanAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"7gj56k","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAERJREFUKFNjZGBg+M9AAPz//5+BkZERryqQLF6DYIYQMgyvQeia8RlGlEHEuGqIGgSLLrLDCGQAMeEDUkcw+pENw5eQAIbMQgEfHdanAAAAAElFTkSuQmCC","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADVJREFUKFNjZGBg+M9ABcBIjEH///9nYGQEKcUNCBoEMgQG8Bk2ahAklCgKI5ABVIk1YpMYAMQyHgHDbiVrAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"g1d0p","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADVJREFUKFNjZGBg+M9ABcBIjEH///9nYGQEKcUNCBoEMgQG8Bk2ahAklCgKI5ABVIk1YpMYAMQyHgHDbiVrAAAAAElFTkSuQmCC","width":18,"height":9},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAACVJREFUKFNjZGBg+M9AAPz//5+BkZERryqQ7KhBo2GEL5EQk44AMwokARH8Wt8AAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ket8p","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"79wth","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAACVJREFUKFNjZGBg+M9AAPz//5+BkZERryqQ7KhBo2GEL5EQk44AMwokARH8Wt8AAAAASUVORK5CYII=","width":18,"height":9}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFRJREFUKFPdkdsKACAIQ+f/f7RhMJimRK/1lJcOazMADjnuqdRRuptZrhUUkLoQ212/9gK7JehAVRF8gx2g7msB+wBEvxjJs0dTOs+pUcFk9qSU7xb4/GAB19w9sAAAAABJRU5ErkJggg==","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689146310193,"updated_at":1689146310193,"isExternal":true,"id":1689137183549} \ No newline at end of file diff --git a/art/animations/machinedrum_8frames.pixil b/art/animations/machinedrum_8frames.pixil new file mode 100644 index 000000000..1097de755 --- /dev/null +++ b/art/animations/machinedrum_8frames.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":18,"height":9,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGBJREFUKFO9klEOwCAMQuH+h65pM412aLcf/dJInwQkAMO0zJZj3JCcJbHPOleMSQX5DdpBFOjlhkQ4OkE+g0pKyki5iceyIw92J5YhP0WMsH24t6NAVZtLa73jq6D8txqOskT7jpktrwAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":true,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"nju6s","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGBJREFUKFO9klEOwCAMQuH+h65pM412aLcf/dJInwQkAMO0zJZj3JCcJbHPOleMSQX5DdpBFOjlhkQ4OkE+g0pKyki5iceyIw92J5YhP0WMsH24t6NAVZtLa73jq6D8txqOskT7jpktrwAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":0},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGJJREFUKFO9ksEKACAIQ/X/P9pQUKaodapT6XqOFRORECyRdLQOM6PE9qrDuiriZgfZQNgL0ATpQFWrzgy0QZ5BV0rJqHNjw6ojtTmJPWRM3gNPGXmxA91eM72aT/oKqn/rAJu9RQGbzh3nAAAAAElFTkSuQmCC","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"1wmie","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGJJREFUKFO9ksEKACAIQ/X/P9pQUKaodapT6XqOFRORECyRdLQOM6PE9qrDuiriZgfZQNgL0ATpQFWrzgy0QZ5BV0rJqHNjw6ojtTmJPWRM3gNPGXmxA91eM72aT/oKqn/rAJu9RQGbzh3nAAAAAElFTkSuQmCC","width":18,"height":9,"data_id":1},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGFJREFUKFO9kTEOACAIA+H/j8ZAgikVdNNJ03pAURExgWNWnqGoKlrizj537J8dZAIxbIMmyA2UMO84QDdIB3I/j6tPCmWERRF2dOTiESSEPWklo6zQmV/bLFvLHX8FcdgLXxJE+zv+xTMAAAAASUVORK5CYII=","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"crmhnm","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGFJREFUKFO9kTEOACAIA+H/j8ZAgikVdNNJ03pAURExgWNWnqGoKlrizj537J8dZAIxbIMmyA2UMO84QDdIB3I/j6tPCmWERRF2dOTiESSEPWklo6zQmV/bLFvLHX8FcdgLXxJE+zv+xTMAAAAASUVORK5CYII=","width":18,"height":9,"data_id":2},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGlJREFUKFOVkdsOwCAIQ+n/fzSGLWjlonFPLq3HUiAiKvSprl8ALG1n9plgznkzip+hgbWgCuIRIixBgD/RCdKlihXgSrmM52lTIhOq6D6maVVvs2w2VKATPG2NX+VdVyljd9v6X0BxvAFfNkT7NlON0AAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"61sqmj","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGlJREFUKFOVkdsOwCAIQ+n/fzSGLWjlonFPLq3HUiAiKvSprl8ALG1n9plgznkzip+hgbWgCuIRIixBgD/RCdKlihXgSrmM52lTIhOq6D6maVVvs2w2VKATPG2NX+VdVyljd9v6X0BxvAFfNkT7NlON0AAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":3},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGpJREFUKFOVkVEOwDAIQuH+h3ZxaQ1a7TL/1PpKgAAMUmYGkjGp/V74XMsvYqJLhaWL1YyguvD3E+yAkHgVdZCtooO1oCtl0apnyZvl56HIj7ofayBVcZit6XSgrzRTamO0onIK4DdoSvMBtAVK+/JTyosAAAAASUVORK5CYII=","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"degv7p","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGpJREFUKFOVkVEOwDAIQuH+h3ZxaQ1a7TL/1PpKgAAMUmYGkjGp/V74XMsvYqJLhaWL1YyguvD3E+yAkHgVdZCtooO1oCtl0apnyZvl56HIj7ofayBVcZit6XSgrzRTamO0onIK4DdoSvMBtAVK+/JTyosAAAAASUVORK5CYII=","width":18,"height":9,"data_id":4},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFOVkVEOwCAIQ9v7H5qlZiSuggv+iW15IAEE7ER8SyRdgkNTBcm1C0dBadxNVc2b6C6PmOM2it6cqNLzSHm3UY3T0SwqJ1JAN9JvUAqSolv0bQWLaPL9XZNxkNMnxAN3UEr7sZlg1AAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"ayuc3i","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFOVkVEOwCAIQ9v7H5qlZiSuggv+iW15IAEE7ER8SyRdgkNTBcm1C0dBadxNVc2b6C6PmOM2it6cqNLzSHm3UY3T0SwqJ1JAN9JvUAqSolv0bQWLaPL9XZNxkNMnxAN3UEr7sZlg1AAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":5},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFO1klEOwCAIQ9v7H5oFMgxidcuS+aVSnhUgAENZZtMxIiSrJPZd54qRqSC/ghY3JCZHyrJyJEF239Y6KGEWaRcLRxncwd48Mr52gjnoqZtLjXqfHfAZlMmn+eqzdQEcrkf7AP6TYwAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"z3vg5","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFO1klEOwCAIQ9v7H5oFMgxidcuS+aVSnhUgAENZZtMxIiSrJPZd54qRqSC/ghY3JCZHyrJyJEF239Y6KGEWaRcLRxncwd48Mr52gjnoqZtLjXqfHfAZlMmn+eqzdQEcrkf7AP6TYwAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":6},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAF9JREFUKFO1kVEOwCAIQ9v7H5oF4hbEKvFjfmksj1IIwJCO2fSMH5JZEveqc8VXqSDXoB1EgRY3JMLRCXIFUjPnUHJGyk00qxl50U4sQx6LmECvCwXqtvkvqI7Qjev6B9/NQfvCqiYfAAAAAElFTkSuQmCC","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"9txj14","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":"0","unqid":"fgf24j","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAF9JREFUKFO1kVEOwCAIQ9v7H5oF4hbEKvFjfmksj1IIwJCO2fSMH5JZEveqc8VXqSDXoB1EgRY3JMLRCXIFUjPnUHJGyk00qxl50U4sQx6LmECvCwXqtvkvqI7Qjev6B9/NQfvCqiYfAAAAAElFTkSuQmCC","width":18,"height":9,"data_id":7}],"currentFrame":7,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAF9JREFUKFO1kVEOwCAIQ9v7H5oF4hbEKvFjfmksj1IIwJCO2fSMH5JZEveqc8VXqSDXoB1EgRY3JMLRCXIFUjPnUHJGyk00qxl50U4sQx6LmECvCwXqtvkvqI7Qjev6B9/NQfvCqiYfAAAAAElFTkSuQmCC","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689212959896,"updated_at":1689212959896,"isExternal":true,"id":1689137183549,"edit":{"status":true,"unqid":"0ed9deef5af474e"}} \ No newline at end of file diff --git a/art/animations/machinedrum_frames/pixil-frame-0.png b/art/animations/machinedrum_frames/pixil-frame-0.png new file mode 100644 index 000000000..bc49a05ef Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-0.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-1.png b/art/animations/machinedrum_frames/pixil-frame-1.png new file mode 100644 index 000000000..78cb6fbc3 Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-1.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-2.png b/art/animations/machinedrum_frames/pixil-frame-2.png new file mode 100644 index 000000000..9e16985c9 Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-2.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-3.png b/art/animations/machinedrum_frames/pixil-frame-3.png new file mode 100644 index 000000000..24bb54a0f Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-3.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-4.png b/art/animations/machinedrum_frames/pixil-frame-4.png new file mode 100644 index 000000000..d779f5ec6 Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-4.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-5.png b/art/animations/machinedrum_frames/pixil-frame-5.png new file mode 100644 index 000000000..dff15a02d Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-5.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-6.png b/art/animations/machinedrum_frames/pixil-frame-6.png new file mode 100644 index 000000000..bb9b889f7 Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-6.png differ diff --git a/art/animations/machinedrum_frames/pixil-frame-7.png b/art/animations/machinedrum_frames/pixil-frame-7.png new file mode 100644 index 000000000..74f1248b2 Binary files /dev/null and b/art/animations/machinedrum_frames/pixil-frame-7.png differ diff --git a/art/animations/metronome_10frames_fixed.pixil b/art/animations/metronome_10frames_fixed.pixil new file mode 100644 index 000000000..04be5051e --- /dev/null +++ b/art/animations/metronome_10frames_fixed.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":"17","height":"15","colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHZJREFUOE/Nk8EOwCAIQ9f//2gWDhCsRUx2mSeD8mxLhJnZ83Hh/xAAi8nOtd9r7QTEm32vIFGXkAoIORXE5yMkXytqRsh24dCcKnnEE0RmUyEqC85Ehbxk0kE4VFaTkBuAmpTXRoj6Vmxpg9z8xdZOlXoCqem8iASV1yhMPaMAAAAASUVORK5CYII=","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"j9rwej","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHZJREFUOE/Nk8EOwCAIQ9f//2gWDhCsRUx2mSeD8mxLhJnZ83Hh/xAAi8nOtd9r7QTEm32vIFGXkAoIORXE5yMkXytqRsh24dCcKnnEE0RmUyEqC85Ehbxk0kE4VFaTkBuAmpTXRoj6Vmxpg9z8xdZOlXoCqem8iASV1yhMPaMAAAAASUVORK5CYII=","width":"17","height":"15","data_id":0},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHhJREFUOE/Fk0EOACEIA+X/j8aQiIFaV4yH9ailmWoVVdX2uORXExFpHmJLYqK4MPWViQ2ngWEeTSmJUyThwKdn7GKj0CnYsMddSFCMUVgjyiZlkp3wRJNInk0qBvMiQ9Fsb5J8ZcavFeNRk8pfXNqLPcG6oyl74g7l4pjU7RJtZQAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"nsa03f","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHhJREFUOE/Fk0EOACEIA+X/j8aQiIFaV4yH9ailmWoVVdX2uORXExFpHmJLYqK4MPWViQ2ngWEeTSmJUyThwKdn7GKj0CnYsMddSFCMUVgjyiZlkp3wRJNInk0qBvMiQ9Fsb5J8ZcavFeNRk8pfXNqLPcG6oyl74g7l4pjU7RJtZQAAAABJRU5ErkJggg==","width":"17","height":"15","data_id":1},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHdJREFUOE+tk0EOwCAIBN3/P5qGAwlsXSltPRodYFxhZrY+LryBAFi59hjCAB9CQvxwXl459thAC4nLY8iuoupCjpMvhIMRhA//BvGWsxuOVREr7adctE+shJZgUdCK2CddxBgysSf7Nwcq9pzQ059sE9vBdp/+AlI2mNRGRHc6AAAAAElFTkSuQmCC","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"z05t0b","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHdJREFUOE+tk0EOwCAIBN3/P5qGAwlsXSltPRodYFxhZrY+LryBAFi59hjCAB9CQvxwXl459thAC4nLY8iuoupCjpMvhIMRhA//BvGWsxuOVREr7adctE+shJZgUdCK2CddxBgysSf7Nwcq9pzQ059sE9vBdp/+AlI2mNRGRHc6AAAAAElFTkSuQmCC","width":"17","height":"15","data_id":2},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAG5JREFUOE+lk0ESwCAIA+X/j6bDwQ7FxEbh5oElkGju7qNZdgIxs4FmypAARB1BZlPd9AoSTTsVMQSug5rYPSRIXosZuSipKvJbdqcNUW6B1HzWaUOYjXBySe6r5C8LOXQVvECUv1itphYzGMrKAz7Cj9RAg+JtAAAAAElFTkSuQmCC","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"fnw8f","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAG5JREFUOE+lk0ESwCAIA+X/j6bDwQ7FxEbh5oElkGju7qNZdgIxs4FmypAARB1BZlPd9AoSTTsVMQSug5rYPSRIXosZuSipKvJbdqcNUW6B1HzWaUOYjXBySe6r5C8LOXQVvECUv1itphYzGMrKAz7Cj9RAg+JtAAAAAElFTkSuQmCC","width":"17","height":"15","data_id":3},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAG9JREFUOE+9k1EOwCAIQ+39D83CB4urBRI181vKK1CYmY3mARjVN/wi4hT+tkiiOJweiXjx1kzYQmdJDnYuCoqKZhFRFDGPTOi+iPLO3RXNh+RYJNuA7EwxeEm6Nc7xWixGdvhCq0zy9abbyUTU+T8jr5XUXPp5kgAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"6erafs","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAG9JREFUOE+9k1EOwCAIQ+39D83CB4urBRI181vKK1CYmY3mARjVN/wi4hT+tkiiOJweiXjx1kzYQmdJDnYuCoqKZhFRFDGPTOi+iPLO3RXNh+RYJNuA7EwxeEm6Nc7xWixGdvhCq0zy9abbyUTU+T8jr5XUXPp5kgAAAABJRU5ErkJggg==","width":"17","height":"15","data_id":4},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHBJREFUOE+9k0EKwDAIBLP/f7TFg8WaXSUE6jU4jlFhZrZEAFjN85uFXyBebrKRJt5Kjg40Qjx5+hsKyRZh0IFaSLY4goQFM1CgzeQaUgE+nVqd2XxMriEMwEyoXay9grCz2lqsEHWM3fbK6SgYW/8HU6+V1KGJUsgAAAAASUVORK5CYII=","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"bk1t6p","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHBJREFUOE+9k0EKwDAIBLP/f7TFg8WaXSUE6jU4jlFhZrZEAFjN85uFXyBebrKRJt5Kjg40Qjx5+hsKyRZh0IFaSLY4goQFM1CgzeQaUgE+nVqd2XxMriEMwEyoXay9grCz2lqsEHWM3fbK6SgYW/8HU6+V1KGJUsgAAAAASUVORK5CYII=","width":"17","height":"15","data_id":5},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHVJREFUOE+l01EKwDAIA9B6/0M7HDgkTZyl+9ugb8aqubuvy8cYYmbrxJZIFDeFWqSm7ECKxOGIlNX8xRvH6aBRnIhyhGCM2mAFbZVUJHuTTR0hCCDC3t9vddiuEQbIP8NEf5UohK0V9mZDJruI0ytvR2Fs/B/mno/UdDC2UQAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"i5vjp","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHVJREFUOE+l01EKwDAIA9B6/0M7HDgkTZyl+9ugb8aqubuvy8cYYmbrxJZIFDeFWqSm7ECKxOGIlNX8xRvH6aBRnIhyhGCM2mAFbZVUJHuTTR0hCCDC3t9vddiuEQbIP8NEf5UohK0V9mZDJruI0ytvR2Fs/B/mno/UdDC2UQAAAABJRU5ErkJggg==","width":"17","height":"15","data_id":6},{"name":"","speed":50,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHZJREFUOE+lk1EOwCAIQ+X+h2bho4urRdDxY2LgWZpq7u7jZ9kMMbNxw/xAQtANSELUdjuFJSSGK3ULBCvFOb++A5UQDB9BohnFq2Sg1BPlRQsCFfBCDck7Dltl6BbCKuBLR83rSQZRwWPwAun8RU5vmViGqvg/ECKS1P+7ZS8AAAAASUVORK5CYII=","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"8idwwm","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHZJREFUOE+lk1EOwCAIQ+X+h2bho4urRdDxY2LgWZpq7u7jZ9kMMbNxw/xAQtANSELUdjuFJSSGK3ULBCvFOb++A5UQDB9BohnFq2Sg1BPlRQsCFfBCDck7Dltl6BbCKuBLR83rSQZRwWPwAun8RU5vmViGqvg/ECKS1P+7ZS8AAAAASUVORK5CYII=","width":"17","height":"15","data_id":7},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHhJREFUOE+tk1EOwCAMQu39D92lHyyIXVN1fk0TntChubuPy2W/QsxsnJp6nSgk9ryqC6Y4EIZAv7chcMDCKm462MzFFoRngVhw9AVanCiEh9uCcIwQZ6L0jMt2DVEAYnTcTGULYae1SzERRxtavUm9qPw7GShz+gD2MZLUy4ceUQAAAABJRU5ErkJggg==","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"7yh45j","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHhJREFUOE+tk1EOwCAMQu39D92lHyyIXVN1fk0TntChubuPy2W/QsxsnJp6nSgk9ryqC6Y4EIZAv7chcMDCKm462MzFFoRngVhw9AVanCiEh9uCcIwQZ6L0jMt2DVEAYnTcTGULYae1SzERRxtavUm9qPw7GShz+gD2MZLUy4ceUQAAAABJRU5ErkJggg==","width":"17","height":"15","data_id":8},{"name":"","speed":"100","layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHpJREFUOE/Nk1EOwCAIQ+H+h2ZhCUtXQEj2M/9UeFKKamYmH5f+ByIiZTGq+hJ5Un3L8QQOCoifV/f4wtMTTvIgBJ9AIySSV5AoD3vBUjpQshhl8fisIJtmliagv1xF51pyMiCdjA2odGf6SgxOkAnA8+P71p0OVo3/BTPpktTooufjAAAAAElFTkSuQmCC","edit":true,"name":"Background","opacity":"1","active":true,"unqid":"n5f9zd","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"jsztf7","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHpJREFUOE/Nk1EOwCAIQ+H+h2ZhCUtXQEj2M/9UeFKKamYmH5f+ByIiZTGq+hJ5Un3L8QQOCoifV/f4wtMTTvIgBJ9AIySSV5AoD3vBUjpQshhl8fisIJtmliagv1xF51pyMiCdjA2odGf6SgxOkAnA8+P71p0OVo3/BTPpktTooufjAAAAAElFTkSuQmCC","width":"17","height":"15","data_id":9}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABEA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAPCAYAAAACsSQRAAAAAXNSR0IArs4c6QAAAHZJREFUOE/Nk8EOwCAIQ9f//2gWDhCsRUx2mSeD8mxLhJnZ83Hh/xAAi8nOtd9r7QTEm32vIFGXkAoIORXE5yMkXytqRsh24dCcKnnEE0RmUyEqC85Ehbxk0kE4VFaTkBuAmpTXRoj6Vmxpg9z8xdZOlXoCqem8iASV1yhMPaMAAAAASUVORK5CYII=","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689226136902,"updated_at":1689226136902,"isExternal":true,"id":1689225698685,"edit":{"status":true,"unqid":"0ed9deef5af474e"}} \ No newline at end of file diff --git a/art/animations/metronome_frames/pixil-frame-0.png b/art/animations/metronome_frames/pixil-frame-0.png new file mode 100644 index 000000000..03848729b Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-0.png differ diff --git a/art/animations/metronome_frames/pixil-frame-1.png b/art/animations/metronome_frames/pixil-frame-1.png new file mode 100644 index 000000000..d03c6a879 Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-1.png differ diff --git a/art/animations/metronome_frames/pixil-frame-2.png b/art/animations/metronome_frames/pixil-frame-2.png new file mode 100644 index 000000000..2b9d7241a Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-2.png differ diff --git a/art/animations/metronome_frames/pixil-frame-3.png b/art/animations/metronome_frames/pixil-frame-3.png new file mode 100644 index 000000000..0426ee5ae Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-3.png differ diff --git a/art/animations/metronome_frames/pixil-frame-4.png b/art/animations/metronome_frames/pixil-frame-4.png new file mode 100644 index 000000000..3dc5b1167 Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-4.png differ diff --git a/art/animations/metronome_frames/pixil-frame-5.png b/art/animations/metronome_frames/pixil-frame-5.png new file mode 100644 index 000000000..f9b267c17 Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-5.png differ diff --git a/art/animations/metronome_frames/pixil-frame-6.png b/art/animations/metronome_frames/pixil-frame-6.png new file mode 100644 index 000000000..a5fc6b105 Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-6.png differ diff --git a/art/animations/metronome_frames/pixil-frame-7.png b/art/animations/metronome_frames/pixil-frame-7.png new file mode 100644 index 000000000..08df5581d Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-7.png differ diff --git a/art/animations/metronome_frames/pixil-frame-8.png b/art/animations/metronome_frames/pixil-frame-8.png new file mode 100644 index 000000000..9023d2f01 Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-8.png differ diff --git a/art/animations/metronome_frames/pixil-frame-9.png b/art/animations/metronome_frames/pixil-frame-9.png new file mode 100644 index 000000000..234ecd2be Binary files /dev/null and b/art/animations/metronome_frames/pixil-frame-9.png differ diff --git a/art/animations/midi_frames/pixil-frame-0.png b/art/animations/midi_frames/pixil-frame-0.png new file mode 100644 index 000000000..80145e1b7 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-0.png differ diff --git a/art/animations/midi_frames/pixil-frame-1.png b/art/animations/midi_frames/pixil-frame-1.png new file mode 100644 index 000000000..65bd2a828 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-1.png differ diff --git a/art/animations/midi_frames/pixil-frame-2.png b/art/animations/midi_frames/pixil-frame-2.png new file mode 100644 index 000000000..8103a38ed Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-2.png differ diff --git a/art/animations/midi_frames/pixil-frame-3.png b/art/animations/midi_frames/pixil-frame-3.png new file mode 100644 index 000000000..dd4ea8f22 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-3.png differ diff --git a/art/animations/midi_frames/pixil-frame-4.png b/art/animations/midi_frames/pixil-frame-4.png new file mode 100644 index 000000000..a2e175343 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-4.png differ diff --git a/art/animations/midi_frames/pixil-frame-5.png b/art/animations/midi_frames/pixil-frame-5.png new file mode 100644 index 000000000..ed945a0c4 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-5.png differ diff --git a/art/animations/midi_frames/pixil-frame-6.png b/art/animations/midi_frames/pixil-frame-6.png new file mode 100644 index 000000000..b67e29f50 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-6.png differ diff --git a/art/animations/midi_frames/pixil-frame-7.png b/art/animations/midi_frames/pixil-frame-7.png new file mode 100644 index 000000000..291a821c1 Binary files /dev/null and b/art/animations/midi_frames/pixil-frame-7.png differ diff --git a/art/animations/midi_logo_eightframes.pixil b/art/animations/midi_logo_eightframes.pixil new file mode 100644 index 000000000..a1ce5e2d8 --- /dev/null +++ b/art/animations/midi_logo_eightframes.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":18,"height":9,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFVJREFUKFOtkVEKACAIQ+f9D20YDNQSjOyncu2xVAAoBpYQpBp5IiYBVrcz9VxnhgCi4bbT4MGEmtYGZQDvz4lGQfsLqXdHot/BlVPrgMtmd8z+jQct/8FpAT6TxVYAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"kbdcqu","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFVJREFUKFOtkVEKACAIQ+f9D20YDNQSjOyncu2xVAAoBpYQpBp5IiYBVrcz9VxnhgCi4bbT4MGEmtYGZQDvz4lGQfsLqXdHot/BlVPrgMtmd8z+jQct/8FpAT6TxVYAAAAASUVORK5CYII=","width":18,"height":9,"old_width":18,"old_height":9,"data_id":0},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFNJREFUKFOtkdsKACAIQ+f/f7ShMDAlSLSXLmuHtQSAYmGIgVQrS8QkF2Fr3snnzOCgbKAxzjREMKGmfYMygPt2olWQPyF1VxJNP+7qqAt7lj0BHQvEaQFrAbvaAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"j8ffnb","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFNJREFUKFOtkdsKACAIQ+f/f7ShMDAlSLSXLmuHtQSAYmGIgVQrS8QkF2Fr3snnzOCgbKAxzjREMKGmfYMygPt2olWQPyF1VxJNP+7qqAt7lj0BHQvEaQFrAbvaAAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":1},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFpJREFUKFO9kVEKwDAIQ5P7H9oRIZB1LWwI86fU6ku0BFBVBZKYBEURRLAMgy3i9zXvHtloRwoDd6cbEpxTNEhFa8Hb+83R7yCPn8IPR5Mfa4Hc0VfYcdkT0AV/fm8Bf+brsgAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"70eltd","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFpJREFUKFO9kVEKwDAIQ5P7H9oRIZB1LWwI86fU6ku0BFBVBZKYBEURRLAMgy3i9zXvHtloRwoDd6cbEpxTNEhFa8Hb+83R7yCPn8IPR5Mfa4Hc0VfYcdkT0AV/fm8Bf+brsgAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":2},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFRJREFUKFPNksEKACAMQvP/P9rwYMhoENGhXYKGLzcDSQIYJIfO25KSEguUZagfcL/eW4PqKIU7p7W/QOkohR3wL5DGaHfk0W7SyqTb1E7A+V2egSYQ+XUBccrkqAAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ve0t0r","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFRJREFUKFPNksEKACAMQvP/P9rwYMhoENGhXYKGLzcDSQIYJIfO25KSEguUZagfcL/eW4PqKIU7p7W/QOkohR3wL5DGaHfk0W7SyqTb1E7A+V2egSYQ+XUBccrkqAAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":3},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFtJREFUKFOtkVEKwDAIQ5P7HzrDQYaWWdrS/lgMeWgkAOHCo0FS5ZEhAdGPv/Wx7xkKyIa/akMGGxoaJWkGGI0tKK92AtxercvIE34ZnRzOkDej7mor4BL2LdADmTNyAevBIfMAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"16a56g","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFtJREFUKFOtkVEKwDAIQ5P7HzrDQYaWWdrS/lgMeWgkAOHCo0FS5ZEhAdGPv/Wx7xkKyIa/akMGGxoaJWkGGI0tKK92AtxercvIE34ZnRzOkDej7mor4BL2LdADmTNyAevBIfMAAAAASUVORK5CYII=","width":18,"height":9,"old_width":18,"old_height":9,"data_id":4},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFZJREFUKFOtktEKACAIA+f/f7RhcFBikFQv5YbHskyS68MyQO47zywsKfQ442edDBuIhmqnYQUDDe8alAHU7UQnEHor0bzCMjvqCXt9tTJR9xcch/0CGuN7cf4GMzmmAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"025038","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFZJREFUKFOtktEKACAIA+f/f7RhcFBikFQv5YbHskyS68MyQO47zywsKfQ442edDBuIhmqnYQUDDe8alAHU7UQnEHor0bzCMjvqCXt9tTJR9xcch/0CGuN7cf4GMzmmAAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":5},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFxJREFUKFOtkVEKACAIQ+f9D20YDbQULOqncu2xVAAoPiwhSDXyREwCrG5n6nudGQKIhmynwYMJNa0N2gG8XyfKQDPJ+vZVIhp9745EL4MLKaupdcBlsztm/8aDBgXtcfvvfWOBAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"dti0k","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFxJREFUKFOtkVEKACAIQ+f9D20YDbQULOqncu2xVAAoPiwhSDXyREwCrG5n6nudGQKIhmynwYMJNa0N2gG8XyfKQDPJ+vZVIhp9745EL4MLKaupdcBlsztm/8aDBgXtcfvvfWOBAAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":6},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFNJREFUKFO1klEKACAIQ7f7H9owGKRUGFU/lsuHuQjA8GBRILPII10CPO976TmvHgJIBbOoghEsqGtlUAbk8zXo+Gm7GfXuvrtW+RGjKUv7qyDda+OHcf6gIEwbAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6n9cfn","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"98g6y","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFNJREFUKFO1klEKACAIQ7f7H9owGKRUGFU/lsuHuQjA8GBRILPII10CPO976TmvHgJIBbOoghEsqGtlUAbk8zXo+Gm7GfXuvrtW+RGjKUv7qyDda+OHcf6gIEwbAAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":7}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAFVJREFUKFOtkVEKACAIQ+f9D20YDNQSjOyncu2xVAAoBpYQpBp5IiYBVrcz9VxnhgCi4bbT4MGEmtYGZQDvz4lGQfsLqXdHot/BlVPrgMtmd8z+jQct/8FpAT6TxVYAAAAASUVORK5CYII=","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689138244114,"updated_at":1689138244114,"isExternal":true,"id":1689137183549} \ No newline at end of file diff --git a/art/animations/mono_logo_10frames.pixil b/art/animations/mono_logo_10frames.pixil new file mode 100644 index 000000000..e43dcb1d1 --- /dev/null +++ b/art/animations/mono_logo_10frames.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":18,"height":9,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEdJREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn1waPQZCI+Q+PBXSnE+LDwwiXQegpgmByoJZBAFMWYvuZmVdBAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}},{"id":1,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAD1JREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn10aQQegpgmBygEU/QYUE0hUAdvJi+xfD9LEAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"mgxcch","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAD1JREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn10aQQegpgmBygEU/QYUE0hUAdvJi+xfD9LEAAAAASUVORK5CYII=","width":18,"height":9,"old_width":18,"old_height":9,"data_id":0},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEhJREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn1yg2CBSeyGGNbiMhPtxrNDcIPUUQTA64XESqQQAA2lb7npMgwQAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"3xf9dw","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEhJREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn1yg2CBSeyGGNbiMhPtxrNDcIPUUQTA64XESqQQAA2lb7npMgwQAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":1},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEVJREFUKFNjZGBg+M8AIv6DKThgZGQEs9HFYQpg8nA+1Q2CmQxzAbqLcPExXDRqEDwWccYaehihpAUGBgaCyQEW/ZQaBAB8Yk37LPumjwAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ket1e","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEVJREFUKFNjZGBg+M8AIv6DKThgZGQEs9HFYQpg8nA+1Q2CmQxzAbqLcPExXDRqEDwWccYaehihpAUGBgaCyQEW/ZQaBAB8Yk37LPumjwAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":2},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEZJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsF5FsELqNhPiwgMIII0IaifYa1Q1CTxHoYYQhjx79hNINLnkAeXtB+6I+RywAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"5w67xg","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAEZJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsF5FsELqNhPiwgMIII0IaifYa1Q1CTxHoYYQhjx79hNINLnkAeXtB+6I+RywAAAAASUVORK5CYII=","width":18,"height":9,"old_width":18,"old_height":9,"data_id":3},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADZJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsF40ahBn/6NGOHkboOnBGP6kGAQCnXTj7EHwGSgAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"tcqk7h","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADZJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsF40ahBn/6NGOHkboOnBGP6kGAQCnXTj7EHwGSgAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":4},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADlJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsFw0eg9DjgWyv0dwgdAsIRj8uF6GLAwCBhCz7SSsCeQAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"8xm4gk","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADlJREFUKFNjZGBg+M+AB/z/j12akZERRReIR1+DYC6AuZBsFw0eg9DjgWyv0dwgdAsIRj8uF6GLAwCBhCz7SSsCeQAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":5},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADhJREFUKFNjZGBg+M9ABPj/H1UZIyMjii4Qj74GwayHuYxsF40aRET8Q5WgJwOYTqKjHz2w0a0GAB0qI/uWOxc0AAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"usjmjk","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAADhJREFUKFNjZGBg+M9ABPj/H1UZIyMjii4Qj74GwayHuYxsF40aRET8Q5WgJwOYTqKjHz2w0a0GAB0qI/uWOxc0AAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":6},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAC1JREFUKFNjZGBg+M9ABcA4ahDBUCQ5jP7/h8QNIyNIKwIMvEHofiXbRegGAQDpLhT7M6jn9wAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ow2one","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAC1JREFUKFNjZGBg+M9ABcA4ahDBUCQ5jP7/h8QNIyNIKwIMvEHofiXbRegGAQDpLhT7M6jn9wAAAABJRU5ErkJggg==","width":18,"height":9,"old_width":18,"old_height":9,"data_id":7},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAACNJREFUKFNjZGBg+M9ABcA4ahDBUBxGYfT/P2qqIdtr6AYBAOhDDvvoB8KqAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ebwg2h","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAACNJREFUKFNjZGBg+M9ABcA4ahDBUBxGYfT/P2qqIdtr6AYBAOhDDvvoB8KqAAAAAElFTkSuQmCC","width":18,"height":9,"old_width":18,"old_height":9,"data_id":8},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAABxJREFUKFNjZGBg+M9ABcA4ahDBUBwNI4JBxAAAtGkJASOfDk8AAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"0sxxvb","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"g2e2i","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAABxJREFUKFNjZGBg+M9ABcA4ahDBUBwNI4JBxAAAtGkJASOfDk8AAAAASUVORK5CYII=","width":18,"height":9,"old_width":18,"old_height":9,"data_id":9}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAD1JREFUKFNj/P///38GLICRkREsikOaASYP08pIdYPQXUAsH8NFxGqEeRWn10aQQegpgmBygEU/QYUE0hUAdvJi+xfD9LEAAAAASUVORK5CYII=","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689143914895,"updated_at":1689143914895,"isExternal":true,"id":1689137183549} \ No newline at end of file diff --git a/art/animations/monomachine_frames/pixil-frame-0.png b/art/animations/monomachine_frames/pixil-frame-0.png new file mode 100644 index 000000000..984f7db3c Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-0.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-1.png b/art/animations/monomachine_frames/pixil-frame-1.png new file mode 100644 index 000000000..7f35f2130 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-1.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-2.png b/art/animations/monomachine_frames/pixil-frame-2.png new file mode 100644 index 000000000..2399481c3 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-2.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-3.png b/art/animations/monomachine_frames/pixil-frame-3.png new file mode 100644 index 000000000..f09061211 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-3.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-4.png b/art/animations/monomachine_frames/pixil-frame-4.png new file mode 100644 index 000000000..01e62bb57 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-4.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-5.png b/art/animations/monomachine_frames/pixil-frame-5.png new file mode 100644 index 000000000..8919ca927 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-5.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-6.png b/art/animations/monomachine_frames/pixil-frame-6.png new file mode 100644 index 000000000..4eacad642 Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-6.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-7.png b/art/animations/monomachine_frames/pixil-frame-7.png new file mode 100644 index 000000000..4662b6a7d Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-7.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-8.png b/art/animations/monomachine_frames/pixil-frame-8.png new file mode 100644 index 000000000..7910901ad Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-8.png differ diff --git a/art/animations/monomachine_frames/pixil-frame-9.png b/art/animations/monomachine_frames/pixil-frame-9.png new file mode 100644 index 000000000..485dcc2de Binary files /dev/null and b/art/animations/monomachine_frames/pixil-frame-9.png differ diff --git a/art/animations/perf_frames/pixil-frame-0.png b/art/animations/perf_frames/pixil-frame-0.png new file mode 100644 index 000000000..f5f64ddab Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-0.png differ diff --git a/art/animations/perf_frames/pixil-frame-1.png b/art/animations/perf_frames/pixil-frame-1.png new file mode 100644 index 000000000..62dc5f417 Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-1.png differ diff --git a/art/animations/perf_frames/pixil-frame-2.png b/art/animations/perf_frames/pixil-frame-2.png new file mode 100644 index 000000000..c1f52421c Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-2.png differ diff --git a/art/animations/perf_frames/pixil-frame-3.png b/art/animations/perf_frames/pixil-frame-3.png new file mode 100644 index 000000000..be08d9fa1 Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-3.png differ diff --git a/art/animations/perf_frames/pixil-frame-4.png b/art/animations/perf_frames/pixil-frame-4.png new file mode 100644 index 000000000..d0c9a1c91 Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-4.png differ diff --git a/art/animations/perf_frames/pixil-frame-5.png b/art/animations/perf_frames/pixil-frame-5.png new file mode 100644 index 000000000..b894e25d4 Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-5.png differ diff --git a/art/animations/perf_frames/pixil-frame-6.png b/art/animations/perf_frames/pixil-frame-6.png new file mode 100644 index 000000000..d53a20694 Binary files /dev/null and b/art/animations/perf_frames/pixil-frame-6.png differ diff --git a/art/animations/perf_logo_7frames.pixil b/art/animations/perf_logo_7frames.pixil new file mode 100644 index 000000000..f065e605c --- /dev/null +++ b/art/animations/perf_logo_7frames.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":18,"height":9,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGdJREFUKFOVklEOwDAIQvH+h3bBhMaZkdn+NeILhQaAhDmZ71FEOCk4KTWXunDenUbkAm0gWuhaOaaBIGVa/nLjQNwt/RYkuH2yQNOyy8uClBGt34bdC6inneRHvX/1d3enfvtBloMHW7No9Y0ilNkAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"yg9ad","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGdJREFUKFOVklEOwDAIQvH+h3bBhMaZkdn+NeILhQaAhDmZ71FEOCk4KTWXunDenUbkAm0gWuhaOaaBIGVa/nLjQNwt/RYkuH2yQNOyy8uClBGt34bdC6inneRHvX/1d3enfvtBloMHW7No9Y0ilNkAAAAASUVORK5CYII=","width":18,"height":9,"data_id":0},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGZJREFUKFOlUtEOACEI0v//aBtuNHNxV6u3EoggN7MwsSLWkbsrqGGSaJAqsO8VhsopdCJCQsXSMQw4VLrlLzddCNw8exFaXFJod9MuWemWGYF0G3YtIJ82k2/1/tVf3c365Qc5HAwF0Wj1x5aZGwAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"zqwzgw","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGZJREFUKFOlUtEOACEI0v//aBtuNHNxV6u3EoggN7MwsSLWkbsrqGGSaJAqsO8VhsopdCJCQsXSMQw4VLrlLzddCNw8exFaXFJod9MuWemWGYF0G3YtIJ82k2/1/tVf3c365Qc5HAwF0Wj1x5aZGwAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":1},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGdJREFUKFONkkEOACEIA+n/H82mJDUssaonlToUEBGRYVbmPwTASYORUvNRF86z04hcoBukx+eeIBoAKdPyyc0OWnevIJVgkwjk7M/uWpB6pFqvmcfkBK7SVuc3ou7o1Ms1fvtBHgMfx+Bo9RGfzeMAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"46e5g","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGdJREFUKFONkkEOACEIA+n/H82mJDUssaonlToUEBGRYVbmPwTASYORUvNRF86z04hcoBukx+eeIBoAKdPyyc0OWnevIJVgkwjk7M/uWpB6pFqvmcfkBK7SVuc3ou7o1Ms1fvtBHgMfx+Bo9RGfzeMAAAAASUVORK5CYII=","width":18,"height":9,"data_id":2},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGhJREFUKFOlUlsOwDAI0vsf2gYTGmtkj3R/HYgU6mYWJr6IE3J3RTUgycZQJfaz4lA5hZ5E6IpLKrdiDpVueXLDzV0Is/nvRugQp9C0aUpWZseMMPQ37FpAXm0n3+p9q7+62/XLB/IRWC+kZfXRSdqZAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"skq0mk","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGhJREFUKFOlUlsOwDAI0vsf2gYTGmtkj3R/HYgU6mYWJr6IE3J3RTUgycZQJfaz4lA5hZ5E6IpLKrdiDpVueXLDzV0Is/nvRugQp9C0aUpWZseMMPQ37FpAXm0n3+p9q7+62/XLB/IRWC+kZfXRSdqZAAAAAElFTkSuQmCC","width":18,"height":9,"data_id":3},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGZJREFUKFOFktEKQDEIQvP/P7pLgZcWWXsb2sHcYGZu4ri/EgBltVDSHUPV2O/KQ3KCNsilBSgCICg9MoevVI9vA02FSDhB1TCZCZUgdsRdz4H2cgRnR3/zg6mup7rMENs/kp9mED734Gj1xk2DogAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ek1ec","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGZJREFUKFOFktEKQDEIQvP/P7pLgZcWWXsb2sHcYGZu4ri/EgBltVDSHUPV2O/KQ3KCNsilBSgCICg9MoevVI9vA02FSDhB1TCZCZUgdsRdz4H2cgRnR3/zg6mup7rMENs/kp9mED734Gj1xk2DogAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":4},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFOlklEKACAIQ939D20oLFQYFfUXzvHYhJm5iefeRwCU1GKS6liqwvlXGjqn0Y0JF6qWxAGAcJnIFJ+omu7HqFHSaCKrYCUlMwr317BrAZnRTn7Ue6q/0u365YFcDhZN0Wj1DtM6FgAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"lj3m08","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGNJREFUKFOlklEKACAIQ939D20oLFQYFfUXzvHYhJm5iefeRwCU1GKS6liqwvlXGjqn0Y0JF6qWxAGAcJnIFJ+omu7HqFHSaCKrYCUlMwr317BrAZnRTn7Ue6q/0u365YFcDhZN0Wj1DtM6FgAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":5},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGlJREFUKFOVklEKwDAIQ/X+h3YkELFSN7e/YXwkpm5mYcMXcY7cfZIaJlRjqQr7/6QRmaANRAtVK8cw4KB0yzc3Ewi71L+BNvEyskDdslxuYlOjG4H899i1AEbLy7d6v+qvbrP+8YEsBw+Ls2j1fJqYcgAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"6siagi","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"ir17on","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGlJREFUKFOVklEKwDAIQ/X+h3YkELFSN7e/YXwkpm5mYcMXcY7cfZIaJlRjqQr7/6QRmaANRAtVK8cw4KB0yzc3Ewi71L+BNvEyskDdslxuYlOjG4H899i1AEbLy7d6v+qvbrP+8YEsBw+Ls2j1fJqYcgAAAABJRU5ErkJggg==","width":18,"height":9,"data_id":6}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAABIA/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAJCAYAAAA/33wPAAAAAXNSR0IArs4c6QAAAGdJREFUKFOVklEOwDAIQvH+h3bBhMaZkdn+NeILhQaAhDmZ71FEOCk4KTWXunDenUbkAm0gWuhaOaaBIGVa/nLjQNwt/RYkuH2yQNOyy8uClBGt34bdC6inneRHvX/1d3enfvtBloMHW7No9Y0ilNkAAAAASUVORK5CYII=","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689145159572,"updated_at":1689145159572,"isExternal":true,"id":1689137183549} \ No newline at end of file diff --git a/art/animations/route_frames/pixil-frame-0.png b/art/animations/route_frames/pixil-frame-0.png new file mode 100644 index 000000000..ea8bb89d4 Binary files /dev/null and b/art/animations/route_frames/pixil-frame-0.png differ diff --git a/art/animations/route_frames/pixil-frame-1.png b/art/animations/route_frames/pixil-frame-1.png new file mode 100644 index 000000000..f797f9360 Binary files /dev/null and b/art/animations/route_frames/pixil-frame-1.png differ diff --git a/art/animations/route_frames/pixil-frame-2.png b/art/animations/route_frames/pixil-frame-2.png new file mode 100644 index 000000000..75ad78a49 Binary files /dev/null and b/art/animations/route_frames/pixil-frame-2.png differ diff --git a/art/animations/route_frames/pixil-frame-3.png b/art/animations/route_frames/pixil-frame-3.png new file mode 100644 index 000000000..433959e82 Binary files /dev/null and b/art/animations/route_frames/pixil-frame-3.png differ diff --git a/art/animations/route_frames/pixil-frame-4.png b/art/animations/route_frames/pixil-frame-4.png new file mode 100644 index 000000000..36bdf1aef Binary files /dev/null and b/art/animations/route_frames/pixil-frame-4.png differ diff --git a/art/animations/route_logo_5frames.pixil b/art/animations/route_logo_5frames.pixil new file mode 100644 index 000000000..a8fb02798 --- /dev/null +++ b/art/animations/route_logo_5frames.pixil @@ -0,0 +1 @@ +{"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":14,"height":10,"colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"],"Black and White":["FFFFFF","000000","FFFFFE","000001","ff0000","ffffff"]},"colorSelected":"Black and White","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFhJREFUKFOlUEkKACEMS/7/6A4NRooLqOMpmLZZCCDQXkSH+iFpChPnxaslEnlSMl6sKqOTyjFGqTadQxtKEaR4a1P5n63WVnuFB+CfYmZ0YxW77RX3rPgBW0VF/jZ+qx4AAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ypohn8","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"87flea","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFhJREFUKFOlUEkKACEMS/7/6A4NRooLqOMpmLZZCCDQXkSH+iFpChPnxaslEnlSMl6sKqOTyjFGqTadQxtKEaR4a1P5n63WVnuFB+CfYmZ0YxW77RX3rPgBW0VF/jZ+qx4AAAAASUVORK5CYII=","width":14,"height":10},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFVJREFUKFOdUEEOACAIgv8/2mbLZpqu5VEEAQIQPIzIeUZPTCAVBm77TaxInsglpLtE9GAUs0R6QylQE6iczI+dzS+rXdltRiOao1SOAj5TLOiGfX8cWQlF/hR2qeEAAAAASUVORK5CYII=","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ypohn8","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"vmsyfu","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFVJREFUKFOdUEEOACAIgv8/2mbLZpqu5VEEAQIQPIzIeUZPTCAVBm77TaxInsglpLtE9GAUs0R6QylQE6iczI+dzS+rXdltRiOao1SOAj5TLOiGfX8cWQlF/hR2qeEAAAAASUVORK5CYII=","width":14,"height":10},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFZJREFUKFOdkFEKACAIQ7f7H9qwMFZpRH6F7G0zAjA8jNkq4wt4QCQWMBN4mdiTLh8zwQzadxPSxMxV0xTqiVbYaq2yanXb7bOPGzUpwK9Eh8JM39+JDVOgP/7j87QEAAAAAElFTkSuQmCC","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ypohn8","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"4ek7ta","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFZJREFUKFOdkFEKACAIQ7f7H9qwMFZpRH6F7G0zAjA8jNkq4wt4QCQWMBN4mdiTLh8zwQzadxPSxMxV0xTqiVbYaq2yanXb7bOPGzUpwK9Eh8JM39+JDVOgP/7j87QEAAAAAElFTkSuQmCC","width":14,"height":10},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFdJREFUKFOdkFEOwCAIQ9v7H5qFxS44BI1+GeortQRguDg8Bc1m/wlMIl0GVvMPrKAIchj5LIFR/JupCn9DK1QZVEnejV3Mq6iKJuP0x10xMbbubTndxgdSDz/+nvmQ9AAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ypohn8","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"0qrh4c","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFdJREFUKFOdkFEOwCAIQ9v7H5qFxS44BI1+GeortQRguDg8Bc1m/wlMIl0GVvMPrKAIchj5LIFR/JupCn9DK1QZVEnejV3Mq6iKJuP0x10xMbbubTndxgdSDz/+nvmQ9AAAAABJRU5ErkJggg==","width":14,"height":10},{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAEhJREFUKFO9jkkOACAIA9v/PxqDikGMB4ix1y5TAhAUxCdFkR1O6u7Q4RkxVSKxrlrRUyLNe5SImmkNXSyo14nZm7pdv/qd2AD1UTn+z8LM9wAAAABJRU5ErkJggg==","edit":false,"name":"Background","opacity":"1","active":true,"unqid":"ypohn8","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"hprcnf","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAEhJREFUKFO9jkkOACAIA9v/PxqDikGMB4ix1y5TAhAUxCdFkR1O6u7Q4RkxVSKxrlrRUyLNe5SImmkNXSyo14nZm7pdv/qd2AD1UTn+z8LM9wAAAABJRU5ErkJggg==","width":14,"height":10}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,iVBORw0KGgoAAAANSUhEUgAAAA4A/sfR5H8Fkddasdmnacvx//8745jkhasdASD945kjknhj/AAAKCAYAAACE2W/HAAAAAXNSR0IArs4c6QAAAFhJREFUKFOlUEkKACEMS/7/6A4NRooLqOMpmLZZCCDQXkSH+iFpChPnxaslEnlSMl6sKqOTyjFGqTadQxtKEaR4a1P5n63WVnuFB+CfYmZ0YxW77RX3rPgBW0VF/jZ+qx4AAAAASUVORK5CYII=","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1689144504355,"updated_at":1689144504355,"isExternal":true,"id":1689137183549} \ No newline at end of file diff --git a/art/sprites/analog_logo_medium.png b/art/sprites/analog_logo_medium.png new file mode 100644 index 000000000..ac67241d7 Binary files /dev/null and b/art/sprites/analog_logo_medium.png differ diff --git a/art/sprites/analog_logo_small.png b/art/sprites/analog_logo_small.png new file mode 100644 index 000000000..a8008f9de Binary files /dev/null and b/art/sprites/analog_logo_small.png differ diff --git a/art/sprites/chromatic.png b/art/sprites/chromatic.png index bd7c660fe..136475f4d 100644 Binary files a/art/sprites/chromatic.png and b/art/sprites/chromatic.png differ diff --git a/art/sprites/fx_logo_small.png b/art/sprites/fx_logo_small.png new file mode 100644 index 000000000..2a6825497 Binary files /dev/null and b/art/sprites/fx_logo_small.png differ diff --git a/art/sprites/md_logo_medium.png b/art/sprites/md_logo_medium.png new file mode 100644 index 000000000..4eb2093de Binary files /dev/null and b/art/sprites/md_logo_medium.png differ diff --git a/art/sprites/md_logo_medium_thick.png b/art/sprites/md_logo_medium_thick.png new file mode 100644 index 000000000..94dc86f9e Binary files /dev/null and b/art/sprites/md_logo_medium_thick.png differ diff --git a/art/sprites/md_logo_small.png b/art/sprites/md_logo_small.png new file mode 100644 index 000000000..95648eb58 Binary files /dev/null and b/art/sprites/md_logo_small.png differ diff --git a/art/sprites/metronome_larger.png b/art/sprites/metronome_larger.png new file mode 100644 index 000000000..1ed30efa7 Binary files /dev/null and b/art/sprites/metronome_larger.png differ diff --git a/art/sprites/metronome_logo_medium.png b/art/sprites/metronome_logo_medium.png new file mode 100644 index 000000000..65542565b Binary files /dev/null and b/art/sprites/metronome_logo_medium.png differ diff --git a/art/sprites/metronome_logo_small.png b/art/sprites/metronome_logo_small.png new file mode 100644 index 000000000..65542565b Binary files /dev/null and b/art/sprites/metronome_logo_small.png differ diff --git a/art/sprites/midi_logo_medium.png b/art/sprites/midi_logo_medium.png new file mode 100644 index 000000000..0a4b43cf3 Binary files /dev/null and b/art/sprites/midi_logo_medium.png differ diff --git a/art/sprites/mnm_logo_medium.png b/art/sprites/mnm_logo_medium.png new file mode 100644 index 000000000..91c7f53c1 Binary files /dev/null and b/art/sprites/mnm_logo_medium.png differ diff --git a/art/sprites/mnm_logo_small.png b/art/sprites/mnm_logo_small.png new file mode 100644 index 000000000..e7b13420f Binary files /dev/null and b/art/sprites/mnm_logo_small.png differ diff --git a/art/sprites/perf.png b/art/sprites/perf.png new file mode 100644 index 000000000..c053853be Binary files /dev/null and b/art/sprites/perf.png differ diff --git a/art/sprites/perf_logo_medium.png b/art/sprites/perf_logo_medium.png new file mode 100644 index 000000000..5f111d396 Binary files /dev/null and b/art/sprites/perf_logo_medium.png differ diff --git a/art/sprites/perf_logo_small.png b/art/sprites/perf_logo_small.png new file mode 100644 index 000000000..d6aa45813 Binary files /dev/null and b/art/sprites/perf_logo_small.png differ diff --git a/art/sprites/route_icon.png b/art/sprites/route_icon.png index 5167e2dd0..56753ad09 100644 Binary files a/art/sprites/route_icon.png and b/art/sprites/route_icon.png differ diff --git a/art/sprites/route_logo_medium.png b/art/sprites/route_logo_medium.png new file mode 100644 index 000000000..2788cdddb Binary files /dev/null and b/art/sprites/route_logo_medium.png differ diff --git a/art/sprites/sample_icon.png b/art/sprites/sample_icon.png new file mode 100644 index 000000000..1f02b14bd Binary files /dev/null and b/art/sprites/sample_icon.png differ diff --git a/art/sprites/step.png b/art/sprites/step.png index 0a1fa7d81..f7af20372 100644 Binary files a/art/sprites/step.png and b/art/sprites/step.png differ diff --git a/avr-gcc-version.md b/avr-gcc-version.md index cfbbefb17..42634f034 100644 --- a/avr-gcc-version.md +++ b/avr-gcc-version.md @@ -41,3 +41,7 @@ FEATURE_FLAGS = -ffunction-sections -fdata-sections -flto -fno-split-wide-types text data bss dec hex filename 218312 6030 42415 266757 41205 main.elf ``` + +There is some discussion that 8.2+ produces more optimized code for interrupts by +introducing pseduo-instructions. +https://sourceware.org/bugzilla/show_bug.cgi?id=21683#c4 diff --git a/avr/cores/megacommand/A4/A4.cpp b/avr/cores/megacommand/A4/A4.cpp index a40c90f55..1885f7ba6 100644 --- a/avr/cores/megacommand/A4/A4.cpp +++ b/avr/cores/megacommand/A4/A4.cpp @@ -1,4 +1,4 @@ -#include "MCL_impl.h" +#include "A4.h" #include "ResourceManager.h" uint8_t a4_sysex_hdr[5] = {0x00, 0x20, 0x3c, 0x06, 0x00}; @@ -40,17 +40,18 @@ const ElektronSysexProtocol a4_protocol = { A4Class::A4Class() : ElektronDevice(&Midi2, "A4", DEVICE_A4, a4_protocol) {} -void A4Class::init_grid_devices() { +void A4Class::init_grid_devices(uint8_t device_idx) { uint8_t grid_idx = 1; + GridDeviceTrack gdt; for (uint8_t i = 0; i < NUM_EXT_TRACKS; i++) { uint8_t track_type = EXT_TRACK_TYPE; if (i < NUM_A4_SOUND_TRACKS) { track_type = A4_TRACK_TYPE; } - - add_track_to_grid(grid_idx, i, &(mcl_seq.ext_tracks[i]), track_type); + gdt.init(track_type, GROUP_DEV, device_idx, &(mcl_seq.ext_tracks[i])); + add_track_to_grid(grid_idx, i, &gdt); } } @@ -110,6 +111,13 @@ bool A4Class::probe() { } // Caller is responsible to make sure icons_device is loaded in RM +MCLGIF* A4Class::gif() { + return R.icons_logo->analog_gif; +} +uint8_t* A4Class::gif_data() { + return R.icons_logo->analog_gif_data; ; +} + uint8_t* A4Class::icon() { return R.icons_device->icon_a4; } @@ -220,9 +228,9 @@ bool A4Class::getBlockingSettingsX(uint8_t settings, uint16_t timeout) { return connected; } - -void A4Class::muteTrack(uint8_t track, bool mute) { - MidiUart2.sendCC(track, 94, mute ? 1 : 0); +void A4Class::muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) { + if (uart_ == nullptr) { uart_ = uart; } + uart->sendCC(track, 94, mute ? 1 : 0); } void A4Class::setLevel(uint8_t track, uint8_t value) { diff --git a/avr/cores/megacommand/A4/A4.h b/avr/cores/megacommand/A4/A4.h index 8faf64763..eefb5ab58 100644 --- a/avr/cores/megacommand/A4/A4.h +++ b/avr/cores/megacommand/A4/A4.h @@ -8,6 +8,7 @@ #include "A4Messages.h" #include "A4Params.h" #include "A4Sysex.h" +#include "A4Track.h" /** * \addtogroup a4_a4 @@ -36,8 +37,10 @@ class A4Class : public ElektronDevice { A4Class(); virtual bool probe(); - virtual void init_grid_devices(); + virtual void init_grid_devices(uint8_t device_idx); virtual uint8_t* icon(); + virtual MCLGIF* gif(); + virtual uint8_t* gif_data(); virtual uint16_t sendKitParams(uint8_t* masks); @@ -89,7 +92,7 @@ class A4Class : public ElektronDevice { bool getBlockingSoundX(uint8_t pattern, uint16_t timeout = 3000); bool getBlockingSettingsX(uint8_t global, uint16_t timeout = 3000); - void muteTrack(uint8_t track, bool mute = true); + void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr); void unmuteTrack(uint8_t track) { muteTrack(track, false); } void setLevel(uint8_t track, uint8_t value); diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp index 219bf665c..94e4f8a54 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.cpp @@ -561,20 +561,38 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], // Draw a RAM-resident 1-bit image at the specified (x,y) position, // using the specified foreground color (unset bits are transparent). void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, - int16_t h, uint16_t color) { + int16_t h, uint16_t color, bool flip_vert, bool flip_horiz) { int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte uint8_t byte = 0; startWrite(); - for (int16_t j = 0; j < h; j++, y++) { + for (int16_t j = 0; j < h; j++) { for (int16_t i = 0; i < w; i++) { if (i & 7) byte <<= 1; else byte = bitmap[j * byteWidth + i / 8]; + uint8_t x_r, y_r; + if (flip_vert) { + x_r = x + w - i - 1; + } + + else { + x_r = x + i; + } + + if (flip_horiz) { + y_r = y + h - j - 1; + } + + else { + y_r = y + j; + } + + if (byte & 0x80) - writePixel(x + i, y, color); + writePixel(x_r, y_r, color); } } endWrite(); @@ -584,19 +602,36 @@ void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, // using the specified foreground (for set bits) and background (unset // bits) colors. void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, - int16_t h, uint16_t color, uint16_t bg) { + int16_t h, uint16_t color, uint16_t bg, bool flip_vert, bool flip_horiz) { int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte uint8_t byte = 0; startWrite(); - for (int16_t j = 0; j < h; j++, y++) { + for (int16_t j = 0; j < h; j++) { for (int16_t i = 0; i < w; i++) { if (i & 7) byte <<= 1; else byte = bitmap[j * byteWidth + i / 8]; - writePixel(x + i, y, (byte & 0x80) ? color : bg); + uint8_t x_r, y_r; + if (flip_vert) { + x_r = x + w - i - 1; + } + + else { + x_r = x + i; + } + + if (flip_horiz) { + y_r = y + h - j - 1; + } + + else { + y_r = y + j; + } + + writePixel(x_r, y_r, (byte & 0x80) ? color : bg); } } endWrite(); @@ -963,6 +998,14 @@ void Adafruit_GFX::setRotation(uint8_t x) { } } +void Adafruit_GFX::draw_textbox(const char *text1, const char *text2) { + char str1[16]; + char str2[16]; + strcpy_P(str1, text1); + strcpy_P(str1, text2); + draw_textbox(str1, str2); +} + void Adafruit_GFX::draw_textbox(char *text, char *text2) { auto oldfont = getFont(); setFont(); diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h index 6c8522370..3dff2ad1f 100755 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Adafruit_GFX.h @@ -34,8 +34,8 @@ class Adafruit_GFX : public Print { // optimized code. Otherwise 'generic' versions are used. virtual void setRotation(uint8_t r); virtual void invertDisplay(boolean i); - virtual void draw_textbox(char *text, char *text2); - + void draw_textbox(char *text, char *text2); + void draw_textbox(const char *text1, const char *text2); // BASIC DRAW API // These MAY be overridden by the subclass to provide device-specific // optimized code. Otherwise 'generic' versions are used. @@ -72,9 +72,9 @@ class Adafruit_GFX : public Print { drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg, bool flip_vert = false, bool flip_horiz = false), drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, - int16_t w, int16_t h, uint16_t color), + int16_t w, int16_t h, uint16_t color, bool flip_vert = false, bool flip_horiz = false), drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, - int16_t w, int16_t h, uint16_t color, uint16_t bg), + int16_t w, int16_t h, uint16_t color, uint16_t bg, bool flip_vert = false, bool flip_horiz = false), drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color), drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], diff --git a/avr/cores/megacommand/Adafruit-GFX-Library/Fonts/Elektrothic.c b/avr/cores/megacommand/Adafruit-GFX-Library/Fonts/Elektrothic.c index 565579f11..38fd3690a 100644 --- a/avr/cores/megacommand/Adafruit-GFX-Library/Fonts/Elektrothic.c +++ b/avr/cores/megacommand/Adafruit-GFX-Library/Fonts/Elektrothic.c @@ -2,27 +2,35 @@ #include "../gfxfont.h" const uint8_t ElektrothicBitmaps[] PROGMEM = { - 0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE, 0xFD, 0xB6, 0xDB, 0xFB, 0xF0, 0xCF, - 0x73, 0x0F, 0xFF, 0xFB, 0xF0, 0xCE, 0x38, 0x3F, 0xFE, 0xCF, 0x3C, 0xFF, - 0x7C, 0x30, 0xC3, 0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFF, 0x7F, 0xFC, 0x3E, - 0xFF, 0x3F, 0xDF, 0xFF, 0xF0, 0xC7, 0x39, 0xCE, 0x30, 0x7B, 0xFC, 0xDE, - 0xFF, 0x3F, 0xDE, 0x7B, 0xFC, 0xFF, 0x7C, 0x3F, 0xFE, 0xCF, 0x37, 0x8C, - 0x31, 0xEC, 0xF3, 0xCF, 0x3C, 0xFF, 0x7C, 0x3F, 0xFE}; + 0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE, 0xFD, 0xB6, 0xDB, 0xFB, 0xF0, 0xCF, + 0x73, 0x0F, 0xFF, 0xFB, 0xF0, 0xCE, 0x38, 0x3F, 0xFE, 0xCF, 0x3C, 0xFF, + 0x7C, 0x30, 0xC3, 0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFF, 0x7F, 0xFC, 0x3E, + 0xFF, 0x3F, 0xDF, 0xFF, 0xF0, 0xC7, 0x39, 0xCE, 0x30, 0x7B, 0xFC, 0xDE, + 0xFF, 0x3F, 0xDE, 0x7B, 0xFC, 0xFF, 0x7C, 0x3F, 0xFE, 0xCF, 0x37, 0x8C, + 0x31, 0xEC, 0xF3, 0xCF, 0x3C, 0xFF, 0x7C, 0x3F, 0xFE, 0x31, 0xEF, 0xF3, + 0xFF, 0xFC, 0xF3, 0xFB, 0xFC, 0xFF, 0xFF, 0x3F, 0xFE, 0x7F, 0xF1, 0x8C, + 0x63, 0xEF, 0xF3, 0xEC, 0xF3, 0xCF, 0x3F, 0xBC +}; const GFXglyph ElektrothicGlyphs[] PROGMEM = { - {0, 6, 8, 7, 0, -8}, // 0x0 'non-printable' - {6, 3, 8, 4, 0, -8}, // 0x1 'non-printable' - {9, 6, 8, 7, 0, -8}, // 0x2 'non-printable' - {15, 6, 8, 7, 0, -8}, // 0x3 'non-printable' - {21, 6, 8, 7, 0, -8}, // 0x4 'non-printable' - {27, 6, 8, 7, 0, -8}, // 0x5 'non-printable' - {33, 6, 8, 7, 0, -8}, // 0x6 'non-printable' - {39, 6, 8, 7, 0, -8}, // 0x7 'non-printable' - {45, 6, 8, 7, 0, -8}, // 0x8 'non-printable' - {51, 6, 8, 7, 0, -8}, // 0x9 'non-printable' - {57, 6, 8, 7, 0, -8}, // 0xA 'non-printable' - {63, 6, 8, 7, 0, -8} // 0xB 'non-printable' + { 0, 6, 8, 7, 0, -8 }, // 0x30 '0' + { 6, 3, 8, 4, 0, -8 }, // 0x31 '1' + { 9, 6, 8, 7, 0, -8 }, // 0x32 '2' + { 15, 6, 8, 7, 0, -8 }, // 0x33 '3' + { 21, 6, 8, 7, 0, -8 }, // 0x34 '4' + { 27, 6, 8, 7, 0, -8 }, // 0x35 '5' + { 33, 6, 8, 7, 0, -8 }, // 0x36 '6' + { 39, 6, 8, 7, 0, -8 }, // 0x37 '7' + { 45, 6, 8, 7, 0, -8 }, // 0x38 '8' + { 51, 6, 8, 7, 0, -8 }, // 0x39 '9' + { 57, 6, 8, 7, 0, -8 }, // 0x3A ':' + { 63, 6, 8, 7, 0, -8 }, // 0x3B ';' + { 69, 6, 8, 7, 0, -8 }, // 0x3C '<' + { 75, 6, 8, 7, 0, -8 }, // 0x3D '=' + { 81, 5, 8, 6, 0, -8 }, // 0x3E '>' + { 86, 6, 8, 7, 0, -8 } // 0x3F '?' }; const GFXfont Elektrothic PROGMEM = { - (uint8_t *)ElektrothicBitmaps, (GFXglyph *)ElektrothicGlyphs, '0', ';', 15}; + (uint8_t *)ElektrothicBitmaps, (GFXglyph *)ElektrothicGlyphs, 0x30, 0x3F, 15}; + diff --git a/avr/cores/megacommand/Arduino.h b/avr/cores/megacommand/Arduino.h index b1861b2e9..40a093072 100644 --- a/avr/cores/megacommand/Arduino.h +++ b/avr/cores/megacommand/Arduino.h @@ -86,7 +86,7 @@ void yield(void); #define max(a,b) ((a)>(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define round(x) ((x)>=0?(long)((x)+0.5f):(long)((x)-0.5f)) #define radians(deg) ((deg)*DEG_TO_RAD) #define degrees(rad) ((rad)*RAD_TO_DEG) #define sq(x) ((x)*(x)) diff --git a/avr/cores/megacommand/CommonTools/RingBuffer.h b/avr/cores/megacommand/CommonTools/RingBuffer.h index e331b05cf..897408741 100644 --- a/avr/cores/megacommand/CommonTools/RingBuffer.h +++ b/avr/cores/megacommand/CommonTools/RingBuffer.h @@ -116,7 +116,7 @@ void CRingBuffer::get_h_isr(C *dst, T n) volatile { #ifdef CHECKING if (isFull() && check) { overflow++; - return false; + return; } #endif @@ -151,7 +151,7 @@ void CRingBuffer::put_h_isr(C *src, T n) volatile { #ifdef CHECKING if (isFull() && check) { overflow++; - return false; + return; } #endif @@ -185,7 +185,7 @@ void CRingBuffer::put_h_isr(C c) volatile { #ifdef CHECKING if (isFull() && check) { overflow++; - return false; + return; } #endif @@ -235,8 +235,10 @@ void CRingBuffer::putp(C *c) volatile { template C CRingBuffer::get_h_isr() volatile { C ret; + #ifdef CHECKING if (isEmpty_isr()) - return ret; + return; + #endif if constexpr (N == 0) { ret = get_bank1(ptr + rd); diff --git a/avr/cores/megacommand/CommonTools/helpers.h b/avr/cores/megacommand/CommonTools/helpers.h index d3cea4021..9c203aeae 100644 --- a/avr/cores/megacommand/CommonTools/helpers.h +++ b/avr/cores/megacommand/CommonTools/helpers.h @@ -84,6 +84,13 @@ extern const uint32_t _bvmasks32[]; #define IS_BIT_SET16(target, bit) IS_BIT_SET_RADDR(target, bit) #define IS_BIT_CLEAR16(target, bit) IS_BIT_CLEAR_RADDR(target, bit) +/** 24-bit macros. **/ +#define SET_BIT24(target, bit) SET_BIT_RADDR(target, bit) +#define CLEAR_BIT24(target, bit) CLEAR_BIT_RADDR(target, bit) +#define TOGGLE_BIT24(target, bit) TOGGLE_BIT_RADDR(target, bit) +#define IS_BIT_SET24(target, bit) IS_BIT_SET_RADDR(target, bit) +#define IS_BIT_CLEAR24(target, bit) IS_BIT_CLEAR_RADDR(target, bit) + /** 32-bit macros. **/ #define SET_BIT32(target, bit) SET_BIT_RADDR(target, bit) #define CLEAR_BIT32(target, bit) CLEAR_BIT_RADDR(target, bit) diff --git a/avr/cores/megacommand/Elektron/Elektron.cpp b/avr/cores/megacommand/Elektron/Elektron.cpp index b371c0f70..a6217ce9a 100644 --- a/avr/cores/megacommand/Elektron/Elektron.cpp +++ b/avr/cores/megacommand/Elektron/Elektron.cpp @@ -1,7 +1,21 @@ #include "Elektron.h" +#include "Project.h" +#include "ResourceManager.h" #define SYSEX_RETRIES 1 +void MidiDevice::add_track_to_grid(uint8_t grid_idx, uint8_t track_idx, GridDeviceTrack *gdt) { + proj.grids[grid_idx].add_track(track_idx, gdt); +} + +void MidiDevice::cleanup(uint8_t device_idx) { + for (uint8_t n = 0; n < NUM_GRIDS; n++) { + proj.grids[n].cleanup(device_idx); + } +} +uint8_t *MidiDevice::gif_data() { return R.icons_logo->midi_gif_data; } +MCLGIF *MidiDevice::gif() { return R.icons_logo->midi_gif; } + uint16_t ElektronDevice::sendRequest(uint8_t *data, uint8_t len, bool send, MidiUartParent *uart_) { if (uart_ == nullptr) { uart_ = uart; } @@ -96,6 +110,7 @@ bool ElektronDevice::get_fw_caps() { } void ElektronDevice::activate_encoder_interface(uint8_t *params) { + encoder_interface = true; uint8_t data[3 + 4 + 24] = {0x70, 0x36, 0x01}; uint8_t mod7 = 0; @@ -119,6 +134,7 @@ void ElektronDevice::activate_encoder_interface(uint8_t *params) { void ElektronDevice::deactivate_encoder_interface() { uint8_t data[3] = {0x70, 0x36, 0x00}; sendRequest(data, sizeof(data)); + encoder_interface = false; //waitBlocking(); } @@ -158,7 +174,7 @@ void ElektronDevice::set_rec_mode(uint8_t mode) { } void ElektronDevice::set_key_repeat(uint8_t mode) { - uint8_t data[3] = {0x70, 0x4D, mode}; + uint8_t data[3] = {0x70, 0x4E, mode}; sendRequest(data, sizeof(data)); // waitBlocking(); } @@ -172,7 +188,7 @@ void ElektronDevice::popup_text(uint8_t action_string, uint8_t persistent) { void ElektronDevice::popup_text(char *str, uint8_t persistent) { uint8_t data[67] = {0x70, 0x3B, persistent}; uint8_t len = strlen(str); - strcpy(data + 3, str); + strcpy((char*) (data + 3), str); sendRequest(data, 3 + len + 1); // waitBlocking(); } @@ -190,7 +206,9 @@ void ElektronDevice::draw_close_bank() { void ElektronDevice::draw_microtiming(uint8_t speed, uint8_t timing) { - uint8_t data[6] = {0x70, 0x3C, 0x20, speed, timing >> 7, timing & 0x7F}; + uint8_t a = timing >> 7; + uint8_t b = timing & 0x7F; + uint8_t data[6] = {0x70, 0x3C, 0x20, speed, a, b}; sendRequest(data, 6); // waitBlocking(); } @@ -232,10 +250,14 @@ void ElektronDevice::deactivate_track_select() { } void ElektronDevice::undokit_sync() { - uint8_t data[2] = {0x70, 0x42}; + uint8_t data[2] = { 0x70, 0x42 }; sendRequest(data, sizeof(data)); } +void ElektronDevice::reset_dsp_params() { + uint8_t data[2] = { 0x70, 0x43 }; + sendRequest(data, sizeof(data)); +} void ElektronDevice::set_trigleds(uint16_t bitmask, TrigLEDMode mode, @@ -433,7 +455,7 @@ void ElektronDevice::setKitName(const char *name, MidiUartParent *uart_) { } uint8_t ElektronDevice::setTempo(float tempo, bool send) { - uint16_t qtempo = round(tempo * 24.0); + uint16_t qtempo = round(tempo * 24.0f); uint8_t data[3] = {sysex_protocol.tempo_set_id, (uint8_t)(qtempo >> 7), (uint8_t)(qtempo & 0x7F)}; return sendRequest(data, countof(data), send); @@ -471,4 +493,5 @@ const char *getMachineNameShort(uint8_t machine, uint8_t type, } } } + return nullptr; } diff --git a/avr/cores/megacommand/Elektron/Elektron.h b/avr/cores/megacommand/Elektron/Elektron.h index 034b7e875..aa6c4d076 100644 --- a/avr/cores/megacommand/Elektron/Elektron.h +++ b/avr/cores/megacommand/Elektron/Elektron.h @@ -8,6 +8,8 @@ #include "MidiID.h" #include "MidiSysex.h" #include "MCLMemory.h" +#include "MidiDeviceGrid.h" +#include "MCLGfx.h" /** Store the name of a monomachine machine. **/ typedef struct mnm_machine_name_s { @@ -132,49 +134,9 @@ typedef void (SysexCallback::*sysex_status_callback_ptr_t)(uint8_t type, /// forward declaration class ElektronDevice; -class SeqTrack; /// Base class for MIDI-compatible devices /// Defines basic device description data and driver interfaces. -class GridDeviceTrack { -public: - uint8_t slot_number; - uint8_t track_type; - uint8_t group_type; - uint8_t mem_slot_idx; - SeqTrack *seq_track; - uint8_t get_slot_number() { return slot_number; } - SeqTrack *get_seq_track() { return seq_track; } -}; - -#define GROUP_DEV 0 -#define GROUP_AUX 1 -#define GROUP_TEMPO 2 - -class GridDevice { -public: - uint8_t num_tracks; - uint8_t get_num_tracks() { return num_tracks; } - - GridDeviceTrack tracks[GRID_WIDTH]; - - GridDevice() { init(); } - - void init() { num_tracks = 0; } - - void add_track(uint8_t track_idx, uint8_t slot_number, SeqTrack *seq_track, uint8_t track_type, uint8_t group_type = GROUP_DEV, uint8_t mem_slot_idx = 255) { - tracks[track_idx].slot_number = slot_number; - tracks[track_idx].seq_track = seq_track; - tracks[track_idx].track_type = track_type; - tracks[track_idx].mem_slot_idx = mem_slot_idx; - if (mem_slot_idx == 255) { - tracks[track_idx].mem_slot_idx = track_idx; - } - tracks[track_idx].group_type = group_type; - num_tracks++; - } -}; - class MidiDevice { public: bool connected; @@ -184,7 +146,6 @@ class MidiDevice { const uint8_t id; // Device identifier const bool isElektronDevice; uint8_t track_type; - GridDevice grid_devices[NUM_GRIDS]; MidiDevice(MidiClass* _midi, const char* _name, const uint8_t _id, const bool _isElektronDevice) : name(_name), id(_id), isElektronDevice(_isElektronDevice) @@ -195,30 +156,26 @@ class MidiDevice { connected = false; } - void cleanup() { - memset(grid_devices,0, sizeof(GridDevice) * NUM_GRIDS); - } - - void add_track_to_grid(uint8_t grid_idx, uint8_t track_idx, SeqTrack *seq_track, uint8_t track_type_, uint8_t group_type = GROUP_DEV, uint8_t mem_slot_idx = 255) { - auto *devp = &grid_devices[grid_idx]; - if (track_type == 0) { track_type = track_type_; } - devp->add_track(track_idx, track_idx + grid_idx * GRID_WIDTH, seq_track, track_type_, group_type, mem_slot_idx); - } + void add_track_to_grid(uint8_t grid_idx, uint8_t track_idx, GridDeviceTrack *gdt); + void cleanup(uint8_t device_idx); ElektronDevice* asElektronDevice() { if (!isElektronDevice) return nullptr; return (ElektronDevice*) this; } - virtual void init_grid_devices() {}; + virtual void init_grid_devices(uint8_t device_idx) {}; virtual void setup() { }; - virtual void disconnect() { cleanup(); connected = false; } + virtual void disconnect(uint8_t device_idx) { cleanup(device_idx); connected = false; } virtual bool probe() = 0; virtual uint8_t get_mute_cc() { return 255; } + virtual void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) {}; // 34x42 bitmap icon of the device virtual uint8_t *icon() { return nullptr; } + virtual MCLGIF *gif(); + virtual uint8_t *gif_data(); }; /// Base class for Elektron sysex listeners @@ -357,6 +314,7 @@ class ElektronSysexObject { #define FW_CAP_ENHANCED_GUI FW_CAP_HIGH(2) #define FW_CAP_ENHANCED_MIDI FW_CAP_HIGH(3) #define FW_CAP_MACHINE_CACHE FW_CAP_HIGH(4) +#define FW_CAP_UNDO_CACHE FW_CAP_HIGH(5) /// Base class for Elektron MidiDevice class ElektronDevice : public MidiDevice { @@ -380,7 +338,7 @@ class ElektronDevice : public MidiDevice { bool loadedKit; /** Set to true if the global was loaded (usually set by MDTask). **/ bool loadedGlobal; - + bool encoder_interface; ElektronDevice( MidiClass* _midi, const char* _name, const uint8_t _id, const ElektronSysexProtocol& protocol) @@ -392,6 +350,8 @@ class ElektronDevice : public MidiDevice { loadedKit = false; loadedGlobal = false; + + encoder_interface = false; } virtual bool getWorkSpaceKit() { @@ -434,6 +394,8 @@ class ElektronDevice : public MidiDevice { **/ virtual const char* getMachineName(uint8_t machine) { return nullptr; } + virtual void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) {}; + bool get_tempo(uint16_t &tempo); bool get_mute_state(uint16_t &mute_state); bool get_fw_caps(); @@ -469,6 +431,7 @@ class ElektronDevice : public MidiDevice { void set_key_repeat(uint8_t mode); void undokit_sync(); + void reset_dsp_params(); /** * Send a sysex request to the device. All the request calls * are wrapped in appropriate methods like requestKit, diff --git a/avr/cores/megacommand/Elektron/ElektronHelper.cpp b/avr/cores/megacommand/Elektron/ElektronHelper.cpp index 5c45e8e20..57b330f8a 100644 --- a/avr/cores/megacommand/Elektron/ElektronHelper.cpp +++ b/avr/cores/megacommand/Elektron/ElektronHelper.cpp @@ -114,7 +114,7 @@ void ElektronHelper::from64Bit(uint64_t num, uint8_t *b) { bool ElektronHelper::checkSysexChecksumAnalog(uint8_t *data, uint16_t len) { uint16_t cksum = 0; - for (int i = 0; i < len - 4; i++) { + for (uint16_t i = 0; i < len - 4; i++) { cksum += data[i]; } cksum &= 0x3FFF; @@ -133,7 +133,7 @@ bool ElektronHelper::checkSysexChecksumAnalog(uint8_t *data, uint16_t len) { bool ElektronHelper::checkSysexChecksumAnalog(MidiClass *midi, uint16_t offset, uint16_t len) { uint16_t cksum = 0; - for (int i = 0; i < len - 4; i++) { + for (uint16_t i = 0; i < len - 4; i++) { cksum += midi->midiSysex.getByte(i + offset); } cksum &= 0x3FFF; @@ -151,7 +151,7 @@ bool ElektronHelper::checkSysexChecksumAnalog(MidiClass *midi, uint16_t offset, void ElektronHelper::calculateSysexChecksumAnalog(uint8_t *data, uint16_t len) { data[0] = 0xF0; uint16_t checksum = 0; - for (int i = 9; i < len; i++) + for (uint16_t i = 9; i < len; i++) checksum += data[i]; data[len] = (uint8_t)((checksum >> 7) & 0x7F); data[len + 1] = (uint8_t)(checksum & 0x7F); @@ -165,7 +165,7 @@ void ElektronHelper::calculateSysexChecksumAnalog(uint8_t *data, uint16_t len) { /* check sysex */ bool ElektronHelper::checkSysexChecksum(uint8_t *data, uint16_t len) { uint16_t cksum = 0; - for (int i = 9 - 6; i < len - 4; i++) { + for (uint16_t i = 9 - 6; i < len - 4; i++) { cksum += data[i]; } cksum &= 0x3FFF; @@ -186,7 +186,7 @@ bool ElektronHelper::checkSysexChecksum(uint8_t *data, uint16_t len) { bool ElektronHelper::checkSysexChecksum(MidiClass *midi, uint16_t offset, uint16_t len) { uint16_t cksum = 0; - for (int i = 9 - 6; i < len - 4; i++) { + for (uint16_t i = 9 - 6; i < len - 4; i++) { cksum += midi->midiSysex.getByte(i + offset); } cksum &= 0x3FFF; @@ -207,7 +207,7 @@ bool ElektronHelper::checkSysexChecksum(MidiClass *midi, uint16_t offset, uint16 void ElektronHelper::calculateSysexChecksum(uint8_t *data, uint16_t len) { data[0] = 0xF0; uint16_t checksum = 0; - for (int i = 9; i < len; i++) + for (uint16_t i = 9; i < len; i++) checksum += data[i]; data[len] = (uint8_t)((checksum >> 7) & 0x7F); data[len + 1] = (uint8_t)(checksum & 0x7F); diff --git a/avr/cores/megacommand/GUI/Encoders.cpp b/avr/cores/megacommand/GUI/Encoders.cpp index 252a5cd40..87c3c0ab7 100644 --- a/avr/cores/megacommand/GUI/Encoders.cpp +++ b/avr/cores/megacommand/GUI/Encoders.cpp @@ -62,15 +62,7 @@ void EncoderParent::clear() { Encoder::Encoder(const char *_name, encoder_handle_t _handler) : EncoderParent(_handler) { - setName(_name); fastmode = true; - pressmode = false; -} - -void Encoder::setName(const char *_name) { - if (_name != NULL) - m_strncpy_fill(name, _name, 4); - name[3] = '\0'; } int Encoder::update_rotations(encoder_t *enc) { @@ -103,7 +95,7 @@ int Encoder::update_rotations(encoder_t *enc) { int Encoder::update(encoder_t *enc) { int inc = update_rotations(enc); - inc = inc + (pressmode ? 0 : (fastmode ? 4 * enc->button : enc->button)); + inc = inc + (fastmode ? 4 * enc->button : enc->button); cur += inc; return cur; diff --git a/avr/cores/megacommand/GUI/Encoders.h b/avr/cores/megacommand/GUI/Encoders.h index 0af1657c0..c87d2d8c4 100644 --- a/avr/cores/megacommand/GUI/Encoders.h +++ b/avr/cores/megacommand/GUI/Encoders.h @@ -105,30 +105,7 @@ class Encoder : public EncoderParent { /** Short name. **/ public: Encoder(const char *_name = NULL, encoder_handle_t _handler = NULL); - // } - //) : public EncoderParent(encoder_handle_t _handler); - char name[4]; - /** - * If this variable is set to true, and pressmode to false, an - * encoder-turn with the encoder pressed down will lead to an - * increment by 5 times the value (default true). - * - * This will work with the parent update() method, not if update() - * is overloaded. - **/ bool fastmode; - /** - * If this variable is set to true, turning the encoder while the - * button is pressed will have no effect on the encoder value. - * - * This will work with the parent update() method, not if update() - * is overloaded. - **/ - bool pressmode; - /** Returns the encoder name. **/ - virtual char *getName() { return name; } - /** Set the encoder name (max 3 characters). **/ - virtual void setName(const char *_name); /** * Updates the value of an encoder according to the movements of the * hardware (recorded in the encoder_t structure). The default diff --git a/avr/cores/megacommand/GUI/GUI.cpp b/avr/cores/megacommand/GUI/GUI.cpp index 01743f7e6..8cfc7a692 100644 --- a/avr/cores/megacommand/GUI/GUI.cpp +++ b/avr/cores/megacommand/GUI/GUI.cpp @@ -21,8 +21,6 @@ void GuiClass::setSketch(Sketch *_sketch) { if (sketch != NULL) { sketch->show(); } - if (currentPage() != NULL) - currentPage()->redisplayPage(); } void GuiClass::setPage(LightPage *page) { @@ -52,22 +50,14 @@ LightPage *GuiClass::currentPage() { return NULL; } -void GuiClass::redisplay() { - if (sketch != NULL) { - PageParent *page = sketch->currentPage(); - if (page != NULL) - page->redisplay = true; - } -} - void loop(); void GuiClass::loop() { uint8_t _midi_lock_tmp = MidiUartParent::handle_midi_lock; + MidiUartParent::handle_midi_lock = 1; while (!EventRB.isEmpty()) { - MidiUartParent::handle_midi_lock = 1; clock_minutes = 0; oled_display.screen_saver = false; gui_event_t event; @@ -88,7 +78,6 @@ void GuiClass::loop() { } } - MidiUartParent::handle_midi_lock = 1; for (int i = 0; i < tasks.size; i++) { if (tasks.arr[i] != NULL) { tasks.arr[i]->checkTask(); @@ -99,32 +88,22 @@ void GuiClass::loop() { if (sketch != NULL) { PageParent *page = sketch->currentPage(); if (page != NULL) { + + MidiUartParent::handle_midi_lock = 1; page->update(); + MidiUartParent::handle_midi_lock = 0; page->loop(); + page->finalize(); } } - if (sketch != NULL) { - sketch->loop(); - } -#ifndef HOST_MIDIDUINO - ::loop(); -#endif if (use_screen_saver && clock_minutes >= SCREEN_SAVER_TIME) { -#ifdef OLED_DISPLAY oled_display.screen_saver = true; -#endif } MidiUartParent::handle_midi_lock = 0; display(); - if (sketch != NULL) { - PageParent *page = sketch->currentPage(); - if (page != NULL) { - page->finalize(); - } - } MidiUartParent::handle_midi_lock = _midi_lock_tmp; } @@ -141,7 +120,6 @@ void GuiClass::display() { page = sketch->currentPage(); if (page != NULL) { page->display(); - page->redisplay = false; } } diff --git a/avr/cores/megacommand/GUI/GUI.h b/avr/cores/megacommand/GUI/GUI.h index 2337f2279..5bfb02fff 100644 --- a/avr/cores/megacommand/GUI/GUI.h +++ b/avr/cores/megacommand/GUI/GUI.h @@ -3,6 +3,8 @@ #ifndef GUI_H__ #define GUI_H__ +#define SHOW_VALUE_TIMEOUT 2000 + #include #include "Task.h" @@ -72,8 +74,7 @@ class GuiClass { * * If a sketch is already active, its hide() method is called. * After the sketch is switched, the show() method of the new sketch - * is called, and the currentPage() is redisplayed by calling - * redisplayPage(). + * is called **/ void setSketch(Sketch *_sketch); /** Returns a pointer to the current sketches currentPage(). **/ @@ -188,12 +189,6 @@ class GuiClass { void display(); - /** - * This method sets the redisplay flag of the active page to true so - * that it gets redisplayed on the next call to display(). - **/ - void redisplay(); - }; /** diff --git a/avr/cores/megacommand/GUI/LCDParent.h b/avr/cores/megacommand/GUI/LCDParent.h index 459431977..7d223bf53 100644 --- a/avr/cores/megacommand/GUI/LCDParent.h +++ b/avr/cores/megacommand/GUI/LCDParent.h @@ -37,16 +37,15 @@ class LCDParentClass { * \addtogroup lcd_parent * @{ **/ - protected: /** Toggle the enable line (left to child). **/ - virtual void enable() { } + virtual void enable() = 0; /** Send a nibble to the display (left to child). **/ - virtual void putnibble(uint8_t nibble) { } + virtual void putnibble(uint8_t nibble) = 0; /** Send a command byte to the display (left to child). **/ - virtual void putcommand(uint8_t command) { } + virtual void putcommand(uint8_t command) = 0; /** Send a data byte to the display (left to child). **/ - virtual void putdata(uint8_t data) { } + virtual void putdata(uint8_t data) = 0; public: #ifdef HOST_MIDIDUINO diff --git a/avr/cores/megacommand/GUI/Pages.cpp b/avr/cores/megacommand/GUI/Pages.cpp index 3b8528ff9..450605067 100644 --- a/avr/cores/megacommand/GUI/Pages.cpp +++ b/avr/cores/megacommand/GUI/Pages.cpp @@ -4,7 +4,7 @@ #include "Pages.h" #include "WProgram.h" #include "DiagnosticPage.h" - +#include "Encoders.h" /** * \addtogroup GUI * @@ -18,6 +18,8 @@ * GUI Pages **/ +uint16_t LightPage::encoders_used_clock[4]; + void Page::update() {} void PageContainer::pushPage(LightPage* page) { @@ -34,9 +36,7 @@ void PageContainer::pushPage(LightPage* page) { } pageStack.push(page); - page->init(); - page->redisplayPage(); page->show(); #ifdef ENABLE_DIAG_LOGGING // deactivate diagnostic page on pushPage @@ -44,12 +44,6 @@ void PageContainer::pushPage(LightPage* page) { #endif } -void PageParent::redisplayPage() { - redisplay = true; -} - -uint16_t LightPage::encoders_used_clock[GUI_NUM_ENCODERS]; - void LightPage::update() { encoder_t _encoders[GUI_NUM_ENCODERS]; @@ -69,12 +63,19 @@ void LightPage::update() { clock_minutes = 0; minuteclock = 0; encoders_used_clock[i] = slowclock; - redisplay = true; } } } } +void LightPage::init_encoders_used_clock(uint16_t timeout) { + for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { + encoders[i]->old = encoders[i]->cur; + ((LightPage *)this)->encoders_used_clock[i] = + slowclock + timeout + 1; + } +} + void LightPage::clear() { for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { if (encoders[i] != NULL) diff --git a/avr/cores/megacommand/GUI/Pages.h b/avr/cores/megacommand/GUI/Pages.h index 46366e022..003439e30 100644 --- a/avr/cores/megacommand/GUI/Pages.h +++ b/avr/cores/megacommand/GUI/Pages.h @@ -64,9 +64,6 @@ class PageParent { **/ public: - /** Set to true will cause the next call to display() to redisplay the page on - * the display. **/ - bool redisplay; /** Set to true when the setup() function has been called. **/ bool isSetup; @@ -119,11 +116,6 @@ class PageParent { **/ virtual void hide() {} - /** - * This method clears the display and sets the redisplay flag of the - * page to true. - **/ - void redisplayPage(); /** * The basic event handler of the page, called by the event handling * part of the GUI main loop when the page is active. Should return @@ -153,10 +145,10 @@ class PageParent { class LightPage : public PageParent { public: - uint8_t curpage; PageContainer *parent; Encoder *encoders[GUI_NUM_ENCODERS]; - static uint16_t encoders_used_clock[GUI_NUM_ENCODERS]; + + static uint16_t encoders_used_clock[4]; LightPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) { @@ -182,6 +174,8 @@ class LightPage : public PageParent { changed while locked, they will send out their new value. **/ void unlockEncoders() {} // TODO + + void init_encoders_used_clock(uint16_t timeout = SHOW_VALUE_TIMEOUT); }; class Page : public PageParent { @@ -189,11 +183,9 @@ class Page : public PageParent { /** The parent container of the page, usually the Sketch which contains it. * **/ PageContainer *parent; - bool redisplay; Page(const char *_name = NULL, const char *_shortName = NULL) : PageParent() { parent = NULL; - redisplay = false; isSetup = false; } @@ -268,18 +260,15 @@ class PageContainer { void popPage() { LightPage *lastpage = currentPage(); currentPage()->cleanup(); - LightPage *page; - pageStack.pop(&page); - if (page != NULL) { + LightPage *page = nullptr; + if (!pageStack.pop(&page)) { goto reset; } + if (page != nullptr) { page->parent = NULL; page->hide(); } - page = currentPage(); - if (page != NULL) { - page->redisplayPage(); - } - else { + if (page == nullptr) { + reset: if (lastpage == NULL) { return; } pageStack.reset(); pushPage(lastpage); diff --git a/avr/cores/megacommand/MCL/A4Track.cpp b/avr/cores/megacommand/MCL/A4Track.cpp index eaf26ec23..edd03c6c5 100644 --- a/avr/cores/megacommand/MCL/A4Track.cpp +++ b/avr/cores/megacommand/MCL/A4Track.cpp @@ -1,5 +1,4 @@ #include "MCL_impl.h" -//#include "MCLSd.h" #define A4_SOUND_LENGTH 0x19F @@ -70,6 +69,8 @@ bool A4Track::store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track, u // !! Note do not rely on editor code lint errors -- these are for 32bit/64bit x86 sizes! // Do compile with avr-gcc and observe the error messages +//__SIZE_PROBE size; +//__SIZE_PROBE perftrackdata; //__SIZE_PROBE mdseqtrackdata; //__SIZE_PROBE mdseqtrackdata; //__SIZE_PROBE sza4t; @@ -95,6 +96,6 @@ bool A4Track::store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track, u //__SIZE_PROBE addr_md; //__SIZE_PROBE addr_aux; //__SIZE_PROBE addr_a4; -//__SIZE_PROBE addr_file_start; -//__SIZE_PROBE addr_end; +//__SIZE_PROBE addr_file_start; +//__SIZE_PROBE addr_end; //__SIZE_PROBE addr_end; diff --git a/avr/cores/megacommand/MCL/ArpPage.cpp b/avr/cores/megacommand/MCL/ArpPage.cpp index eb48854c2..b9d6009f9 100644 --- a/avr/cores/megacommand/MCL/ArpPage.cpp +++ b/avr/cores/megacommand/MCL/ArpPage.cpp @@ -2,16 +2,16 @@ MCLEncoder arp_range(0, 4, ENCODER_RES_SEQ); MCLEncoder arp_mode(0, 17, ENCODER_RES_SEQ); -MCLEncoder arp_rate(0, 4, ENCODER_RES_SEQ); +MCLEncoder arp_rate(1, 16, ENCODER_RES_SEQ); MCLEncoder arp_enabled(0, 2, ENCODER_RES_SEQ); -void ArpPage::setup() {} +void ArpPage::setup() { +} void ArpPage::init() { - DEBUG_PRINT_FN(); oled_display.setFont(); - seq_ptc_page.display(); +// seq_ptc_page.display(); track_update(); trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); } @@ -28,7 +28,7 @@ void ArpPage::track_update(uint8_t n, bool re_render) { arp_track = &mcl_seq.ext_arp_tracks[n]; } - arp_rate.cur = arp_track->rate; + arp_rate.cur = arp_track->length; arp_rate.old = arp_rate.cur; arp_range.cur = arp_track->range; @@ -74,8 +74,7 @@ void ArpPage::loop() { } if (encoders[2]->hasChanged()) { - arp_track->set_length(1 << arp_rate.cur); - arp_track->rate = arp_rate.cur; + arp_track->set_length(arp_rate.cur); } } @@ -97,7 +96,7 @@ void ArpPage::display() { oled_display.setCursor(42, 10); oled_display.setTextColor(WHITE); - oled_display.print("ARPEGGIATOR: T"); + oled_display.print(F("ARPEGGIATOR: T")); if (seq_ptc_page.midi_device == &MD) { oled_display.print(last_md_track + 1); @@ -153,7 +152,7 @@ bool ArpPage::handleEvent(gui_event_t *event) { EVENT_PRESSED(event, Buttons.BUTTON4)) { GUI.ignoreNextEvent(event->source); exit: - GUI.popPage(); + mcl.popPage(); return true; } if (note_interface.is_event(event)) { diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp index 117a17aef..a516ff999 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.cpp @@ -19,7 +19,6 @@ void ArpSeqTrack::set_length(uint8_t length_) { } } - void ArpSeqTrack::seq(MidiUartParent *uart_) { MidiUartParent *uart_old = uart; uart = uart_; @@ -39,13 +38,14 @@ void ArpSeqTrack::seq(MidiUartParent *uart_) { if (mod12_counter == 0 && enabled && mute_state == SEQ_MUTE_OFF) { if (step_count == 0) { if (len > 0) { + uint8_t note = notes[idx] + oct * 12; switch (active) { case MD_ARP_TRACK_TYPE: - seq_ptc_page.trig_md(notes[idx] + oct * 12, track_number, fine_tune, uart); + seq_ptc_page.trig_md(note, track_number, fine_tune, uart); break; case EXT_ARP_TRACK_TYPE: - seq_ptc_page.note_on_ext(notes[idx] + oct * 12, 127, track_number, uart); - last_note_on = notes[idx] + oct * 12; + seq_ptc_page.note_on_ext(note, 127, track_number, uart); + last_note_on = note; break; } idx++; @@ -72,6 +72,8 @@ uint8_t ArpSeqTrack::get_next_note_up(int8_t cur) { void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_t range_, uint64_t *note_mask_) { DEBUG_PRINT_FN(); + uint8_t mute_state_old = mute_state; + mute_state = SEQ_MUTE_ON; fine_tune = fine_tune_; range = range_; @@ -82,9 +84,13 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ if (!enabled) { return; } + switch (active) { + case EXT_ARP_TRACK_TYPE: + seq_ptc_page.buffer_notesoff_ext(track_number); + break; + } memcpy(note_mask, note_mask_, sizeof(note_mask)); - uint8_t num_of_notes = 0; uint8_t note = 0; uint8_t b = 0; @@ -120,7 +126,7 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ for (uint8_t i = 0; i < num_of_notes; i++) { switch (mode) { case ARP_RND: - note = sort_up[random(0, num_of_notes)] + 12 * random(0,range); + note = sort_up[get_random(num_of_notes)] + 12 * random(range); break; case ARP_UP2: case ARP_UPP: @@ -277,7 +283,7 @@ void ArpSeqTrack::render(uint8_t mode_, uint8_t oct_, uint8_t fine_tune_, uint8_ if (idx >= len) { idx = len - 1; } - + mute_state = mute_state_old; } diff --git a/avr/cores/megacommand/MCL/ArpSeqTrack.h b/avr/cores/megacommand/MCL/ArpSeqTrack.h index 02095d0c1..61ca64988 100644 --- a/avr/cores/megacommand/MCL/ArpSeqTrack.h +++ b/avr/cores/megacommand/MCL/ArpSeqTrack.h @@ -40,8 +40,7 @@ class ArpSeqData { uint8_t enabled : 4; uint8_t range : 4; uint8_t oct : 4; - uint8_t rate : 4; - uint8_t mode; + uint8_t mode : 4; uint8_t fine_tune; uint64_t note_mask[2]; //input notes @@ -68,8 +67,7 @@ class ArpSeqTrack : public ArpSeqData, public SeqTrackBase { void init() { speed = SEQ_SPEED_2X; - rate = 1; - length = 1 << rate; //Arp rate is function of length + length = 1; enabled = false; range = 0; oct = 1; diff --git a/avr/cores/megacommand/MCL/AuxPages.cpp b/avr/cores/megacommand/MCL/AuxPages.cpp index 6ce9b0132..c7f84316c 100644 --- a/avr/cores/megacommand/MCL/AuxPages.cpp +++ b/avr/cores/megacommand/MCL/AuxPages.cpp @@ -1,20 +1,25 @@ #include "MCL_impl.h" -MCLEncoder mixer_param1(0, 127); -MCLEncoder mixer_param2(0, 127); -MCLEncoder mixer_param3(0, 127); -MCLEncoder mixer_param4(0, 127); +MCLEncoder mixer_param1; +MCLEncoder mixer_param2; +MCLEncoder mixer_param3; +MCLEncoder mixer_param4; MCLEncoder route_param1(2, 5); MCLExpEncoder route_param2(1, 64); -MCLEncoder fx_param1(0, 127); -MCLEncoder fx_param2(0, 127); -MCLEncoder fx_param3(0, 127); -MCLEncoder fx_param4(0, 127); +MCLEncoder fx_param1; +MCLEncoder fx_param2; +MCLEncoder fx_param3; +MCLEncoder fx_param4; -MixerPage mixer_page(&mixer_param1, &mixer_param2, &mixer_param3, - &mixer_param4); +PerfEncoder perf_param1(0,127); +PerfEncoder perf_param2(0,127); +PerfEncoder perf_param3(0,127); +PerfEncoder perf_param4(0,127); + +MixerPage mixer_page(&perf_param1, &perf_param2, &perf_param3, + &perf_param4); RoutePage route_page(&route_param1, &route_param2); fx_param_t fx_echo_params[8] = { @@ -46,3 +51,5 @@ FXPage fx_page_b(&fx_param1, &fx_param2, &fx_param3, &fx_param4, LFOPage lfo_page(&(mcl_seq.lfo_tracks[0]), &fx_param1, &fx_param2, &fx_param3, &fx_param4); +PerfPage perf_page(&perf_param1, &fx_param2, &fx_param3, &fx_param4); + diff --git a/avr/cores/megacommand/MCL/AuxPages.h b/avr/cores/megacommand/MCL/AuxPages.h index d6baba8bb..134768670 100644 --- a/avr/cores/megacommand/MCL/AuxPages.h +++ b/avr/cores/megacommand/MCL/AuxPages.h @@ -9,6 +9,7 @@ #include "RoutePage.h" #include "RAMPage.h" #include "FXPage.h" +#include "PerfPage.h" #include "MD.h" extern MCLEncoder mixer_param1; @@ -29,9 +30,15 @@ extern MCLEncoder fx_param2; extern MCLEncoder fx_param3; extern MCLEncoder fx_param4; +extern PerfEncoder perf_param1; +extern PerfEncoder perf_param2; +extern PerfEncoder perf_param3; +extern PerfEncoder perf_param4; + extern FXPage fx_page_a; extern FXPage fx_page_b; extern LFOPage lfo_page; +extern PerfPage perf_page; #endif /* AUXPAGES_H__ */ diff --git a/avr/cores/megacommand/MCL/ConvertProjectPage.cpp b/avr/cores/megacommand/MCL/ConvertProjectPage.cpp index 479f5778d..1cb3ac4bd 100644 --- a/avr/cores/megacommand/MCL/ConvertProjectPage.cpp +++ b/avr/cores/megacommand/MCL/ConvertProjectPage.cpp @@ -3,7 +3,6 @@ void ConvertProjectPage::init() { DEBUG_PRINT_FN(); - strcpy(match, ".mcl"); strcpy(title, "Project"); strcpy(lwd, "/"); SD.chdir("/"); @@ -24,7 +23,7 @@ void ConvertProjectPage::on_select(const char *entry) { DEBUG_DUMP(entry); file.close(); if (proj.convert_project(entry)) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } else { // gfx.alert("PROJECT ERROR", "NOT COMPATIBLE"); } diff --git a/avr/cores/megacommand/MCL/DSP.h b/avr/cores/megacommand/MCL/DSP.h index 7d4744935..d9ea762c2 100644 --- a/avr/cores/megacommand/MCL/DSP.h +++ b/avr/cores/megacommand/MCL/DSP.h @@ -3,7 +3,7 @@ #ifndef DSP_H__ #define DSP_H__ -#include "MCL.h" +#include "mcl.h" #include "math.h" #define FULL_SCALE 0xFFFF diff --git a/avr/cores/megacommand/MCL/DeviceTrack.cpp b/avr/cores/megacommand/MCL/DeviceTrack.cpp index 0b502c7d7..eca00204f 100644 --- a/avr/cores/megacommand/MCL/DeviceTrack.cpp +++ b/avr/cores/megacommand/MCL/DeviceTrack.cpp @@ -31,9 +31,12 @@ DeviceTrack *DeviceTrack::init_track_type(uint8_t track_type) { case MNM_TRACK_TYPE: ::new (this) MNMTrack; break; - case GRIDCHAIN_TRACK_TYPE: + case GRIDCHAIN_TRACK_TYPE: ::new (this) GridChainTrack; break; + case PERF_TRACK_TYPE: + ::new (this) PerfTrack; + break; } return this; } @@ -53,6 +56,9 @@ DeviceTrack *DeviceTrack::load_from_grid_512(uint8_t column, uint16_t row, Grid // virtual functions are ready + DEBUG_PRINTLN("device load from 512"); + DEBUG_PRINTLN(active != EMPTY_TRACK_TYPE); + DEBUG_PRINTLN(ptrack->get_track_size()); if (active != EMPTY_TRACK_TYPE) { if ( ptrack->get_track_size() < 512) { return ptrack; } size_t len = ptrack->get_track_size() - 512; @@ -89,7 +95,7 @@ DeviceTrack *DeviceTrack::load_from_grid(uint8_t column, uint16_t row) { // virtual functions are ready if (active != EMPTY_TRACK_TYPE) { - uint32_t len = ptrack->get_track_size(); + uint16_t len = ptrack->get_track_size(); if (!proj.read_grid(ptrack, len, column, row)) { DEBUG_PRINTLN(F("read failed")); @@ -108,8 +114,8 @@ DeviceTrack *DeviceTrack::load_from_grid(uint8_t column, uint16_t row) { bool DeviceTrackChunk::load_from_mem_chunk(uint8_t column, uint8_t chunk) { size_t chunk_size = sizeof(seq_data_chunk); - uint32_t offset = (uint32_t)seq_data_chunk - (uint32_t)this; - uint32_t pos = get_region() + get_track_size() * (uint32_t)(column) + offset + + uint16_t offset = (uint16_t)seq_data_chunk - (uint16_t)this; + uint16_t pos = get_region() + get_track_size() * (uint16_t)(column) + offset + chunk_size * chunk; volatile uint8_t *ptr = reinterpret_cast(pos); memcpy_bank1(seq_data_chunk, ptr, chunk_size); @@ -125,7 +131,7 @@ bool DeviceTrackChunk::load_chunk(volatile void *ptr, uint8_t chunk) { } bool DeviceTrackChunk::load_link_from_mem(uint8_t column) { - uint32_t pos = get_region() + get_track_size() * (uint32_t)(column) + (uint32_t) &this->link - (uint32_t) this; + uint16_t pos = get_region() + get_track_size() * (uint16_t)(column) + (uint16_t) &this->link - (uint16_t) this; volatile uint8_t *ptr = reinterpret_cast(pos); memcpy_bank1(&this->link, ptr, sizeof(GridTrack)); return true; diff --git a/avr/cores/megacommand/MCL/DeviceTrack.h b/avr/cores/megacommand/MCL/DeviceTrack.h index dbece9dea..88f81b280 100644 --- a/avr/cores/megacommand/MCL/DeviceTrack.h +++ b/avr/cores/megacommand/MCL/DeviceTrack.h @@ -18,6 +18,8 @@ class MDRouteTrack; class MDTempoTrack; class MDLFOTrack; class MNMTrack; +class PerfTrack; +class GridChainTrack; #define __IMPL_DYNAMIK_KAST(klass, pred, aktive) \ void _dynamik_kast_impl(DeviceTrack *p, klass **pp) { \ @@ -50,6 +52,8 @@ class DeviceTrack : public GridTrack { __IMPL_DYNAMIK_KAST(MDTempoTrack, MDTEMPO_TRACK_TYPE, MDTEMPO_TRACK_TYPE) __IMPL_DYNAMIK_KAST(MNMTrack, MNM_TRACK_TYPE, MNM_TRACK_TYPE) __IMPL_DYNAMIK_KAST(MDLFOTrack, MDLFO_TRACK_TYPE, MDLFO_TRACK_TYPE) + __IMPL_DYNAMIK_KAST(PerfTrack, PERF_TRACK_TYPE, PERF_TRACK_TYPE) + __IMPL_DYNAMIK_KAST(GridChainTrack, GRIDCHAIN_TRACK_TYPE, GRIDCHAIN_TRACK_TYPE) public: // bool get_track_from_sysex(int tracknumber, uint8_t column); @@ -103,7 +107,7 @@ class DeviceTrack : public GridTrack { } int memcmp_sound(uint8_t column) { - uint32_t pos = get_region() + get_track_size() * (uint32_t)(column) + ((uint32_t) get_sound_data_ptr() - (uint32_t) this); + uint16_t pos = get_region() + get_track_size() * (uint16_t)(column) + ((uint16_t) get_sound_data_ptr() - (uint16_t) this); volatile uint8_t *ptr = reinterpret_cast(pos); return memcmp_bank1(get_sound_data_ptr(), ptr, get_track_size()); } @@ -142,7 +146,7 @@ class DeviceTrackChunk : public DeviceTrack { virtual uint16_t get_seq_data_size() = 0; virtual uint8_t get_model() = 0; virtual uint16_t get_track_size() = 0; - virtual uint32_t get_region() = 0; + virtual uint16_t get_region() = 0; virtual uint8_t get_device_type() = 0; virtual void *get_sound_data_ptr() = 0; diff --git a/avr/cores/megacommand/MCL/DiagnosticPage.cpp b/avr/cores/megacommand/MCL/DiagnosticPage.cpp index f823ecb53..18d5862f0 100644 --- a/avr/cores/megacommand/MCL/DiagnosticPage.cpp +++ b/avr/cores/megacommand/MCL/DiagnosticPage.cpp @@ -15,7 +15,7 @@ void DiagnosticPage::draw_perfcounter() { auto clock = read_slowclock(); oled_display.setCursor(64, 7); - oled_display.print("GUI loop"); + oled_display.print(F("GUI loop")); oled_display.setCursor(97, 7); oled_display.print(clock_diff(last_clock, clock)); @@ -93,7 +93,7 @@ bool DiagnosticPage::handleEvent(gui_event_t *event) { EVENT_PRESSED(event, Buttons.ENCODER2) || EVENT_PRESSED(event, Buttons.ENCODER3) || EVENT_PRESSED(event, Buttons.ENCODER4)) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp index 656756582..6ba663195 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.cpp @@ -1,12 +1,19 @@ #include "MCL_impl.h" - -void ExtSeqTrack::set_speed(uint8_t _speed) { - uint8_t old_speed = speed; - float mult = get_speed_multiplier(_speed) / get_speed_multiplier(old_speed); - for (uint16_t i = 0; i < NUM_EXT_EVENTS; i++) { - events[i].micro_timing = round(mult * (float)events[i].micro_timing); +uint8_t ExtSeqTrack::epoch = 0; + +void ExtSeqTrack::set_speed(uint8_t new_speed, uint8_t old_speed, + bool timing_adjust) { + if (old_speed == 255) { + old_speed = speed; + } + if (timing_adjust) { + float mult = + get_speed_multiplier(new_speed) / get_speed_multiplier(old_speed); + for (uint16_t i = 0; i < event_count; i++) { + events[i].micro_timing = round(mult * (float)events[i].micro_timing); + } } - speed = _speed; + speed = new_speed; uint8_t timing_mid = get_timing_mid(); if (mod12_counter > timing_mid) { mod12_counter = mod12_counter - (mod12_counter / timing_mid) * timing_mid; @@ -14,19 +21,20 @@ void ExtSeqTrack::set_speed(uint8_t _speed) { } } -void ExtSeqTrack::set_length(uint8_t len) { +void ExtSeqTrack::set_length(uint8_t len, bool expand) { if (len == 0) { len = 1; } if (len > 128) { len = 16; } - + uint8_t old_length = length; length = len; uint8_t step = step_count; if (step >= length && length > 0) { step = step % length; } + uint16_t idx, end; locate(step, idx, end); USE_LOCK(); @@ -34,6 +42,32 @@ void ExtSeqTrack::set_length(uint8_t len) { step_count = step; cur_event_idx = idx; CLEAR_LOCK(); + + if (expand && old_length <= 16 && length >= 16) { + for (uint8_t n = old_length; n < length; n++) { + if (timing_buckets.get(n) != 0) { + expand = false; + return; + } + } + ext_event_t empty_events[8]; + uint8_t a = 0; + for (uint8_t n = old_length; n < 128; n++) { + uint16_t ev_idx, ev_end; + locate(a, ev_idx, ev_end); + memcpy(empty_events, &events[ev_idx], sizeof(empty_events)); + for (uint8_t m = 0; m < (ev_end - ev_idx); m++) { + add_event(n, &empty_events[m]); + } + velocities[n] = velocities[a]; + a++; + if (a == old_length) { + a = 0; + } + } + } else if (length < old_length) { + buffer_notesoff(); + } } void ExtSeqTrack::re_sync() { @@ -61,6 +95,7 @@ void ExtSeqTrack::remove_event(uint16_t index) { if (step < step_count) { cur_event_idx--; } + epoch++; --event_count; } @@ -87,6 +122,7 @@ uint16_t ExtSeqTrack::add_event(uint8_t step, ext_event_t *e) { cur_event_idx++; } ++event_count; + epoch++; return idx; } @@ -359,7 +395,8 @@ void ExtSeqTrack::init_notes_on() { } } -void ExtSeqTrack::add_notes_on(uint16_t x, uint8_t value, uint8_t velocity) { +void ExtSeqTrack::add_notes_on(uint8_t step, int8_t utiming, uint8_t value, + uint8_t velocity) { if (notes_on_count >= NUM_NOTES_ON) { return; } @@ -386,7 +423,8 @@ void ExtSeqTrack::add_notes_on(uint16_t x, uint8_t value, uint8_t velocity) { notes_on_count++; } notes_on[slot].value = value; - notes_on[slot].x = x; + notes_on[slot].step = step; + notes_on[slot].utiming = utiming; notes_on[slot].velocity = velocity; return; @@ -419,19 +457,24 @@ void ExtSeqTrack::add_note(uint16_t cur_x, uint16_t cur_w, uint8_t cur_y, uint8_t step = (cur_x / timing_mid); uint8_t start_utiming = timing_mid + cur_x - (step * timing_mid); + DEBUG_DUMP(step); + DEBUG_DUMP(start_utiming); + uint8_t end_step = ((cur_x + cur_w) / timing_mid); +again: uint8_t end_utiming = timing_mid + (cur_x + cur_w) - (end_step * timing_mid); + DEBUG_DUMP(end_step); + DEBUG_DUMP(end_utiming); if (end_step == step) { DEBUG_PRINTLN(F("ALERT start == end")); end_step = end_step + 1; - end_utiming -= timing_mid; + goto again; } if (end_step >= length) { end_step = end_step - length; } - uint16_t ev_idx; uint16_t note_idx = find_midi_note(step, cur_y, ev_idx, /*event_on*/ true); if (note_idx != 0xFFFF) { @@ -464,10 +507,10 @@ bool ExtSeqTrack::del_note(uint16_t cur_x, uint16_t cur_w, uint8_t cur_y) { uint16_t note_idx_off, note_idx_on; bool note_on_found = false; uint16_t ev_idx, ev_end; - uint16_t note_start, note_end; + int16_t note_start, note_end; bool ret = false; - for (int i = 0; i < length; i++) { + for (uint8_t i = 0; i < length; i++) { again: note_idx_on = find_midi_note(i, cur_y, ev_idx, /*event_on*/ true); @@ -501,10 +544,9 @@ bool ExtSeqTrack::del_note(uint16_t cur_x, uint16_t cur_w, uint8_t cur_y) { note_idx_off = find_midi_note(i, cur_y, ev_idx, /*event_on*/ false); if (note_idx_off != 0xFFFF) { - DEBUG_DUMP(F("Wrap")); // Remove wrap around notes auto &ev = events[note_idx_off]; - uint16_t note_end = i * timing_mid + ev.micro_timing - timing_mid; + int16_t note_end = i * timing_mid + ev.micro_timing - timing_mid; if (note_end > cur_x) { remove_event(note_idx_off); for (uint8_t j = length - 1; j > i; j--) { @@ -547,7 +589,10 @@ void ExtSeqTrack::handle_event(uint16_t index, uint8_t step) { // plock uint8_t param = locks_params[ev.lock_idx] - 1; if (param == PARAM_PRG) { - uart->sendProgramChange(channel, ev.event_value); + if (!pgm_oneshot) { + pgm_oneshot = true; + uart->sendProgramChange(channel, ev.event_value); + } } else { if (param == PARAM_PB) { uart->sendPitchBend(channel, ev.event_value << 7); @@ -589,7 +634,6 @@ void ExtSeqTrack::load_cache() { } t.load_link_from_mem(track_number); t.load_link_data((SeqTrack *)this); - } void ExtSeqTrack::seq(MidiUartParent *uart_) { @@ -628,7 +672,15 @@ void ExtSeqTrack::seq(MidiUartParent *uart_) { uint16_t ev_idx, ev_end; - if ((is_generic_midi || (!is_generic_midi && count_down == 0)) && (mute_state == SEQ_MUTE_OFF)) { + if (record_mutes) { + uint8_t u = 0; + uint8_t q = 0; + uint8_t s = get_quantized_step(u, q); + SET_BIT128_P(mute_mask, s); + } + + if ((is_generic_midi || (!is_generic_midi && count_down == 0)) && + (mute_state == SEQ_MUTE_OFF)) { // SEQ_MUTE_OFF)) { // the range we're interested in: // [current timing bucket, micro >= timing_mid ... next timing bucket, micro @@ -649,7 +701,7 @@ void ExtSeqTrack::seq(MidiUartParent *uart_) { // Locate NEXT uint8_t next_step = 0; - if (step_count == length) { + if (step_count == length - 1) { next_step = 0; ev_idx = 0; } else { @@ -676,6 +728,7 @@ void ExtSeqTrack::note_on(uint8_t note, uint8_t velocity, if (uart_ == nullptr) { uart_ = uart; } + mixer_page.ext_disp_levels[track_number] = 127; uart_->sendNoteOn(channel, note, velocity); SET_BIT128_P(note_buffer, note); } @@ -685,88 +738,32 @@ void ExtSeqTrack::note_off(uint8_t note, uint8_t velocity, if (uart_ == nullptr) { uart_ = uart; } - uart_->sendNoteOff(channel, note, velocity); + uart_->sendNoteOff(channel, note); CLEAR_BIT128_P(note_buffer, note); } void ExtSeqTrack::noteon_conditional(uint8_t condition, uint8_t note, uint8_t velocity) { - if (IS_BIT_SET128_P(oneshot_mask, step_count)) { + if (IS_BIT_SET128_P(oneshot_mask, step_count) || + IS_BIT_SET128_P(mute_mask, step_count)) { return; } if (condition > 64) { condition -= 64; } - switch (condition) { - case 0: - case 1: - note_on(note, velocity); - break; - case 2: - if (!IS_BIT_SET(iterations_8, 0)) { - note_on(note, velocity); - } - break; - case 3: - if ((iterations_6 == 3) || (iterations_6 == 6)) { - note_on(note, velocity); - } - break; - case 6: - if (iterations_6 == 6) { - note_on(note, velocity); - } - break; - case 4: - if ((iterations_8 == 4) || (iterations_8 == 8)) { - note_on(note, velocity); - } - break; - case 8: - if (iterations_8 == 8) { - note_on(note, velocity); - } - case 5: - if (iterations_5 == 5) { - note_on(note, velocity); - } - break; - case 7: - if (iterations_7 == 7) { - note_on(note, velocity); - } - break; - case 9: - if (get_random_byte() <= 13) { - note_on(note, velocity); - } - break; - case 10: - if (get_random_byte() <= 32) { - note_on(note, velocity); - } - break; - case 11: - if (get_random_byte() <= 64) { - note_on(note, velocity); - } - break; - case 12: - if (get_random_byte() <= 96) { - note_on(note, velocity); - } - break; - case 13: - if (get_random_byte() <= 115) { - note_on(note, velocity); - } - break; - case 14: + bool send_note = false; + if (condition == 14) { if (!IS_BIT_SET128_P(oneshot_mask, step_count)) { SET_BIT128_P(oneshot_mask, step_count); - note_on(note, velocity); + send_note = true; } + } else { + send_note = SeqTrack::conditional(condition); + } + + if (send_note) { + note_on(note, velocity); } } @@ -825,33 +822,12 @@ uint8_t ExtSeqTrack::find_lock_idx(uint8_t param_id) { void ExtSeqTrack::record_track_locks(uint8_t track_param, uint8_t value, bool slide) { - if (step_count >= length) { + if (!mcl_cfg.rec_automation || step_count >= length) { return; } - uint8_t timing_mid = get_timing_mid(); - - int8_t mod12 = mod12_counter - 1; - - uint8_t step = step_count; - - if ((step == 0) && (mod12 < 0)) { - mod12 += timing_mid; - step = length - 1; - } - - uint8_t utiming = mod12 + timing_mid; - - if (mcl_cfg.rec_quant) { - if (mod12 > timing_mid / 2) { - step++; - if (step == length) { - step = 0; - } - } - utiming = timing_mid; - } - + uint8_t utiming = 0; + uint8_t step = get_quantized_step(utiming); // clear all locks on step clear_track_locks(step, track_param, 255); set_track_locks(step, utiming, track_param, value, slide); @@ -871,19 +847,23 @@ bool ExtSeqTrack::del_track_locks(int16_t cur_x, uint8_t lock_idx, end = start_idx; bool ret = false; - uint8_t r = 2; + uint8_t r = 4; for (uint8_t n = step; n < min(length, step + 3); n++) { end += timing_buckets.get(n); for (; start_idx < end; start_idx++) { DEBUG_DUMP(start_idx); uint8_t i = start_idx; - if (!events[i].is_lock || events[i].lock_idx != lock_idx || - (events[i].event_value > value + r || - events[i].event_value < min(0, value - r))) + if (!events[i].is_lock || events[i].lock_idx != lock_idx) + //|| (events[i].event_value > value + r || + // events[i].event_value < min(0, value - r))) continue; int16_t event_x = n * timing_mid + events[i].micro_timing - timing_mid; if (event_x == cur_x || (event_x <= cur_x + r && event_x >= cur_x - r)) { + uint8_t param = locks_params[lock_idx] - 1; + if (param == PARAM_PRG) { + pgm_oneshot = 0; + } remove_event(i); ret = true; } @@ -892,9 +872,17 @@ bool ExtSeqTrack::del_track_locks(int16_t cur_x, uint8_t lock_idx, return ret; } +void ExtSeqTrack::clear_track_locks() { + for (uint8_t n = 0; n < NUM_LOCKS; n++) { + clear_track_locks(n); + } + pgm_oneshot = 0; +} + void ExtSeqTrack::clear_track_locks(uint8_t idx) { for (uint8_t n = 0; n < length; n++) { clear_track_locks_idx(n, idx, 255); + locks_slide_data[n].init(); } } @@ -982,6 +970,8 @@ bool ExtSeqTrack::set_track_locks(uint8_t step, uint8_t utiming, DEBUG_DUMP(F("adding lock")); DEBUG_DUMP(lock_idx); + constexpr uint8_t oneshot = 14; + e->is_lock = true; e->cond_id = 0; e->lock_idx = lock_idx; @@ -1009,6 +999,10 @@ bool ExtSeqTrack::set_track_step(uint8_t &step, uint8_t utiming, e.event_on = event_on; e.micro_timing = utiming; + DEBUG_PRINTLN("adding step"); + DEBUG_DUMP(event_on); + DEBUG_DUMP(step); + DEBUG_DUMP(utiming); if (add_event(step, &e) == 0xFFFF) { return false; } @@ -1018,54 +1012,79 @@ bool ExtSeqTrack::set_track_step(uint8_t &step, uint8_t utiming, return true; } -void ExtSeqTrack::record_track_noteoff(uint8_t note_num) { - - uint8_t condition = 0; - +void ExtSeqTrack::store_mute_state() { uint8_t timing_mid = get_timing_mid(); - - int8_t mod12 = mod12_counter - 1; - - uint8_t step = step_count; - - if ((step == 0) && (mod12 < 0)) { - mod12 += timing_mid; - step = length - 1; - } - - uint8_t utiming = mod12 + timing_mid; - - if (mcl_cfg.rec_quant) { - if (mod12 > timing_mid / 2) { - step++; - if (step == length) { - step = 0; + for (uint8_t n = 0; n < NUM_EXT_STEPS; n++) { + if (IS_BIT_SET128_P(mute_mask, n)) { + uint16_t ev_idx, ev_end; + loc: + locate(n, ev_idx, ev_end); + for (uint8_t m = ev_idx; m < ev_end; m++) { + if (!events[m].is_lock && events[m].event_on) { + if (del_note(n * timing_mid + events[m].micro_timing - timing_mid, + timing_mid, events[m].event_value)) { + goto loc; + } + } } } - utiming = timing_mid; } + clear_mutes(); +} + +void ExtSeqTrack::record_track_noteoff(uint8_t note_num) { + uint8_t condition = 0; + uint8_t timing_mid = get_timing_mid(); uint16_t ev_idx; uint8_t n = find_notes_on(note_num); if (n == 255) return; - ignore_step = step; - SET_BIT128_P(ignore_notes, note_num); + if (MidiClock.state == 2 && SeqPage::recording) { - uint16_t start_x = notes_on[n].x; - uint16_t end_x = step * timing_mid + utiming - timing_mid; + int8_t utiming = mod12_counter - 1; + uint8_t step = step_count; - if (end_x < start_x) { - del_note(0, end_x, note_num); - end_x += length * timing_mid; - } - uint16_t w = end_x - start_x; + ignore_step = step; + SET_BIT128_P(ignore_notes, note_num); - if (MidiClock.state == 2 && SeqPage::recording) { + uint16_t w = 0; + + int16_t start_x = notes_on[n].step * timing_mid + notes_on[n].utiming; + int16_t end_x = step * timing_mid + utiming; + int16_t roll_length = length * timing_mid; + bool wrap = false; + + if (mcl_cfg.rec_quant) { + if (end_x < start_x) { + end_x += roll_length; + wrap = true; + } + w = max(1, end_x - start_x); + + int8_t u = notes_on[n].utiming; + uint8_t s = notes_on[n].step; + if (u > timing_mid / 2) { + s++; + if (s == length) { + s = 0; + } + } + u = 0; + start_x = s * timing_mid + u; + end_x = start_x + w; + if (end_x > roll_length) { del_note(0, end_x - roll_length, note_num); } + } else { + if (end_x < start_x) { + del_note(0, end_x, note_num); + end_x += roll_length; + } + w = end_x - start_x; + } del_note(start_x, w, note_num); - add_note(start_x, w, note_num, notes_on[n].velocity); + add_note(start_x, w, note_num, notes_on[n].velocity, 0); } notes_on[n].value = 255; @@ -1077,32 +1096,20 @@ void ExtSeqTrack::record_track_noteon(uint8_t note_num, uint8_t velocity) { uint8_t condition = 0; uint8_t timing_mid = get_timing_mid(); - - int8_t mod12 = mod12_counter - 1; - + int8_t utiming = mod12_counter - 1; uint8_t step = step_count; - if ((step == 0) && (mod12 < 0)) { - mod12 += timing_mid; - step = length - 1; - } - - uint8_t utiming = mod12 + timing_mid; - - if (mcl_cfg.rec_quant) { - if (mod12 > timing_mid / 2) { - step++; - if (step == length) { - step = 0; - } - } - utiming = timing_mid; - } - ignore_step = step; SET_BIT128_P(ignore_notes, note_num); - add_notes_on(step * timing_mid + utiming - timing_mid, note_num, velocity); + add_notes_on(step, utiming, note_num, velocity); +} + +void ExtSeqTrack::clear_mute() { memset(mute_mask, 0, sizeof(mute_mask)); } + +void ExtSeqTrack::clear_mutes() { + memset(oneshot_mask, 0, sizeof(oneshot_mask)); + memset(mute_mask, 0, sizeof(mute_mask)); } void ExtSeqTrack::clear_ext_conditional() { @@ -1110,6 +1117,8 @@ void ExtSeqTrack::clear_ext_conditional() { events[x].cond_id = 0; events[x].micro_timing = 0; // XXX zero or mid? } + clear_mutes(); + memset(ignore_notes, 0, sizeof(ignore_notes)); } void ExtSeqTrack::clear_ext_notes() { @@ -1200,3 +1209,15 @@ void ExtSeqTrack::modify_track(uint8_t dir) { mute_state = old_mute_state; } + +void ExtSeqTrack::toggle_mute() { + if (mute_state == SEQ_MUTE_ON) { + mute_state = SEQ_MUTE_OFF; + } else { + mute_state = SEQ_MUTE_ON; + uint8_t mod12_counter_ = MidiClock.mod12_counter; + while (MidiClock.state == 2 && mod12_counter_ == MidiClock.mod12_counter) { + }; + buffer_notesoff(); + } +} diff --git a/avr/cores/megacommand/MCL/ExtSeqTrack.h b/avr/cores/megacommand/MCL/ExtSeqTrack.h index b7efdd18f..3975859f1 100644 --- a/avr/cores/megacommand/MCL/ExtSeqTrack.h +++ b/avr/cores/megacommand/MCL/ExtSeqTrack.h @@ -6,7 +6,7 @@ #include "MidiUartParent.h" //#include "MidiUart.h" #include "CommonTools/NibbleArray.h" -#include "MCL.h" +#include "mcl.h" #include "SeqTrack.h" #include "WProgram.h" @@ -94,7 +94,8 @@ struct ext_event_t { class NoteVector { public: - uint16_t x; + uint8_t step; + int8_t utiming; uint8_t value; uint8_t velocity; }; @@ -150,8 +151,11 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { uint64_t note_buffer[2] = { 0}; // 2 x 64 bit masks to store state of 128 notes. uint64_t oneshot_mask[2]; + uint64_t mute_mask[2]; uint64_t ignore_notes[2]; + bool pgm_oneshot; + static uint8_t epoch; NoteVector notes_on[NUM_NOTES_ON]; uint8_t notes_on_count; @@ -160,9 +164,10 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { ExtSeqTrack() : SeqSlideTrack() { active = EXT_TRACK_TYPE; } ALWAYS_INLINE() void reset() { - SeqTrack::reset(); + SeqSlideTrack::reset(); memset(oneshot_mask,0,sizeof(oneshot_mask)); memset(ignore_notes,0, sizeof(ignore_notes)); + pgm_oneshot = 0; } void seq(MidiUartParent *uart_); @@ -204,12 +209,16 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { // clear_track_locks: if value != 255, delete specific lock event of value. // otherwise delete all locks matching track_param of any value bool del_track_locks(int16_t cur_x, uint8_t lock_idx, uint8_t value); + void clear_mute(); + void clear_mutes(); + void clear_track_locks(); void clear_track_locks(uint8_t idx); bool clear_track_locks(uint8_t step, uint8_t track_param, uint8_t value = 255); bool clear_track_locks_idx(uint8_t step, uint8_t lock_idx, uint8_t value = 255); void clear_track(); - void set_length(uint8_t len); + void store_mute_state(); + void set_length(uint8_t len, bool expand = false); void re_sync(); void reset_params(); void handle_event(uint16_t index, uint8_t step); @@ -217,7 +226,7 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { uint16_t add_event(uint8_t step, ext_event_t *e); void init_notes_on(); - void add_notes_on(uint16_t x, uint8_t value, uint8_t velocity); + void add_notes_on(uint8_t step, int8_t utiming, uint8_t value, uint8_t velocity); uint8_t find_notes_on(uint8_t value); void remove_notes_on(uint8_t value); @@ -247,6 +256,7 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { ev_end += ev_idx; } + void toggle_mute(); void buffer_notesoff() { init_notes_on(); @@ -273,31 +283,14 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { } } void buffer_notesoff8(uint8_t *buf, uint8_t offset) { - if (IS_BIT_SET(*buf, 0)) { - uart->sendNoteOff(channel, offset, 0); - } - if (IS_BIT_SET(*buf, 1)) { - uart->sendNoteOff(channel, offset + 1, 0); - } - if (IS_BIT_SET(*buf, 2)) { - uart->sendNoteOff(channel, offset + 2, 0); - } - if (IS_BIT_SET(*buf, 3)) { - uart->sendNoteOff(channel, offset + 3, 0); - } - if (IS_BIT_SET(*buf, 4)) { - uart->sendNoteOff(channel, offset + 4, 0); - } - if (IS_BIT_SET(*buf, 5)) { - uart->sendNoteOff(channel, offset + 5, 0); - } - if (IS_BIT_SET(*buf, 6)) { - uart->sendNoteOff(channel, offset + 6, 0); - } - if (IS_BIT_SET(*buf, 7)) { - uart->sendNoteOff(channel, offset + 7, 0); + uint8_t count = 0; + while (*buf) { + if (*buf & 1) { + uart->sendNoteOff(channel, offset + count); + } + count++; + *buf >>= 1; } - *buf = 0; } void rotate_left() { modify_track(DIR_LEFT); } @@ -306,7 +299,7 @@ class ExtSeqTrack : public ExtSeqTrackData, public SeqSlideTrack { void modify_track(uint8_t dir); - void set_speed(uint8_t _speed); + void set_speed(uint8_t new_speed, uint8_t old_speed = 255, bool timing_adjust = true); }; #endif /* EXTSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/ExtTrack.cpp b/avr/cores/megacommand/MCL/ExtTrack.cpp index 285300b9e..7892b83d2 100644 --- a/avr/cores/megacommand/MCL/ExtTrack.cpp +++ b/avr/cores/megacommand/MCL/ExtTrack.cpp @@ -36,6 +36,8 @@ void ExtTrack::load_seq_data(SeqTrack *seq_track) { memcpy(ext_track->data(), &seq_data, sizeof(seq_data)); load_link_data(seq_track); + ext_track->clear_mutes(); + ext_track->pgm_oneshot = 0; ext_track->set_length(seq_track->length); seq_track->mute_state = old_mute; #endif @@ -52,7 +54,7 @@ bool ExtTrack::store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track, if (grid == nullptr) { DEBUG_PRINTLN("grid is nullptr"); } ExtSeqTrack *ext_track = (ExtSeqTrack *) seq_track; - + //ext_track->store_mute_state(); #ifdef EXT_TRACKS if (online) { get_track_from_sysex(column); diff --git a/avr/cores/megacommand/MCL/ExtTrack.h b/avr/cores/megacommand/MCL/ExtTrack.h index 78f5c51e5..840883470 100644 --- a/avr/cores/megacommand/MCL/ExtTrack.h +++ b/avr/cores/megacommand/MCL/ExtTrack.h @@ -5,6 +5,7 @@ #include "ExtSeqTrack.h" #include "GridTrack.h" #include "MCLMemory.h" +#include "MidiActivePeering.h" #define EMPTY_TRACK_TYPE 0 @@ -70,7 +71,7 @@ class ExtTrack : public DeviceTrack { virtual uint8_t get_model() { return EXT_TRACK_TYPE; } virtual uint16_t get_track_size() { return sizeof(ExtTrack); } - virtual uint32_t get_region() { return BANK1_A4_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_A4_TRACKS_START; } virtual uint16_t get_region_size() { return GRID2_TRACK_LEN; } virtual uint8_t get_device_type() { return EXT_TRACK_TYPE; } virtual uint8_t get_parent_model() { return midi_active_peering.get_device(UART2_PORT)->track_type; } @@ -116,7 +117,7 @@ class ExtTrackChunk : public DeviceTrack { virtual uint16_t get_seq_data_size() { return sizeof(ExtSeqTrackData); } virtual uint8_t get_model() { return EXT_TRACK_TYPE; } virtual uint16_t get_track_size() { return GRID2_TRACK_LEN; } - virtual uint32_t get_region() { return BANK1_A4_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_A4_TRACKS_START; } virtual uint8_t get_device_type() { return EXT_TRACK_TYPE; } virtual void *get_sound_data_ptr() { return nullptr; } @@ -129,7 +130,7 @@ class ExtTrackChunk : public DeviceTrackChunk { virtual uint16_t get_seq_data_size() { return sizeof(ExtSeqTrackData); } virtual uint8_t get_model() { return EXT_TRACK_TYPE; } virtual uint16_t get_track_size() { return GRID2_TRACK_LEN; } - virtual uint32_t get_region() { return BANK1_A4_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_A4_TRACKS_START; } virtual uint8_t get_device_type() { return EXT_TRACK_TYPE; } virtual void *get_sound_data_ptr() { return nullptr; } diff --git a/avr/cores/megacommand/MCL/FXPage.cpp b/avr/cores/megacommand/MCL/FXPage.cpp index fdefbc79f..b75a46c6e 100644 --- a/avr/cores/megacommand/MCL/FXPage.cpp +++ b/avr/cores/megacommand/MCL/FXPage.cpp @@ -3,7 +3,9 @@ #define FX_TYPE 0 #define FX_PARAM 1 -#define INTERPOLATE + +PageIndex FXPage::last_page = FX_PAGE_A; + void FXPage::setup() { DEBUG_PRINT_FN(); } void FXPage::init() { @@ -12,17 +14,19 @@ void FXPage::init() { oled_display.setFont(); trig_interface.off(); update_encoders(); - + MD.set_key_repeat(0); R.Clear(); R.use_icons_page(); R.use_machine_param_names(); + R.use_icons_knob(); + last_page = mcl.currentPage(); } void FXPage::update_encoders() { for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { ((MCLEncoder *)encoders[n])->max = 127; - uint8_t a = ((page_mode ? 1 : 0) * GUI_NUM_ENCODERS) + n; + uint8_t a = ((uint8_t)page_mode * GUI_NUM_ENCODERS) + n; uint8_t fx_param = params[a].param; switch (params[a].type) { @@ -39,37 +43,28 @@ void FXPage::update_encoders() { encoders[n]->cur = MD.kit.dynamics[fx_param]; break; } - encoders[n]->old = encoders[n]->cur; - ((LightPage *)this)->encoders_used_clock[n] = - slowclock - SHOW_VALUE_TIMEOUT - 1; } + + init_encoders_used_clock(); } void FXPage::cleanup() { // md_exploit.off(); + MD.set_key_repeat(1); oled_display.clearDisplay(); } void FXPage::loop() { for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { - uint8_t n = i + ((page_mode ? 1 : 0) * GUI_NUM_ENCODERS); + uint8_t n = i + (page_mode * GUI_NUM_ENCODERS); if (encoders[i]->hasChanged()) { uint8_t fx_param = params[n].param; uint8_t fx_type = params[n].type; uint8_t val; - // Interpolation. -#ifdef INTERPOLATE - for (val = encoders[i]->old; val < encoders[i]->cur; val++) { - MD.sendFXParam(fx_param, val, fx_type); - } - for (val = encoders[i]->old; val > encoders[i]->cur; val--) { - MD.sendFXParam(fx_param, val, fx_type); - } -#endif MD.sendFXParam(fx_param, encoders[i]->cur, fx_type); switch (fx_type) { case MD_FX_ECHO: @@ -85,11 +80,6 @@ void FXPage::loop() { MD.kit.eq[fx_param] = encoders[i]->cur; break; } - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].check_and_update_params_offset( - NUM_MD_TRACKS + 1 + fx_type - MD_FX_ECHO, fx_param, - encoders[i]->cur); - } } } } @@ -100,11 +90,12 @@ void FXPage::display() { oled_display.clearDisplay(); auto oldfont = oled_display.getFont(); - if (page_id == 0) { - oled_display.drawBitmap(0, 0, R.icons_page->icon_rhytmecho, 24, 18, WHITE); - } else { - oled_display.drawBitmap(0, 0, R.icons_page->icon_gatebox, 24, 18, WHITE); + uint8_t *icon = R.icons_page->icon_rhytmecho; + if (page_id == 1) { + icon = R.icons_page->icon_gatebox; } + + oled_display.drawBitmap(0, 0, icon, 24, 18, WHITE); mcl_gui.draw_knob_frame(); for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { @@ -119,12 +110,12 @@ void FXPage::display() { // mcl_gui.draw_light_encoder(30 + 20 * i, 18, encoders[i], str); } oled_display.setFont(&TomThumb); - const char *info1; + const char *info1;; const char *info2; if (page_mode) { info1 = "FX A"; - } else { - info1 = "FX B"; + } else { + info1 = "FX B"; } info2 = &fx_page_title[0]; mcl_gui.draw_panel_labels(info1, info2); @@ -132,43 +123,6 @@ void FXPage::display() { oled_display.setFont(oldfont); } -void FXPage::onControlChangeCallback_Midi(uint8_t *msg) { - uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); - uint8_t param = msg[1]; - uint8_t value = msg[2]; - uint8_t track; - uint8_t track_param; - // If external keyboard controlling MD pitch, send parameter updates - // to all polyphonic tracks - uint8_t param_true = 0; - - MD.parseCC(channel, param, &track, &track_param); - if (track > 15) { - return; - } -} - -void FXPage::setup_callbacks() { - if (midi_state) { - return; - } - Midi.addOnControlChangeCallback( - this, (midi_callback_ptr_t)&FXPage::onControlChangeCallback_Midi); - - midi_state = true; -} - -void FXPage::remove_callbacks() { - if (!midi_state) { - return; - } - - Midi.removeOnControlChangeCallback( - this, (midi_callback_ptr_t)&FXPage::onControlChangeCallback_Midi); - - midi_state = false; -} - bool FXPage::handleEvent(gui_event_t *event) { if (note_interface.is_event(event)) { uint8_t track = event->source - 128; @@ -176,6 +130,37 @@ bool FXPage::handleEvent(gui_event_t *event) { return true; } } + if (EVENT_CMD(event)) { + uint8_t key = event->source - 64; + if (event->mask == EVENT_BUTTON_RELEASED) { + switch (key) { + case MDX_KEY_NO: + mcl.setPage(MIXER_PAGE); + break; + } + } + if (event->mask == EVENT_BUTTON_PRESSED) { + switch (key) { + case MDX_KEY_SCALE: + case MDX_KEY_DOWN: + if (mcl.currentPage() == FX_PAGE_B) { + goto toggle_mode; + } + else { + mcl.setPage(FX_PAGE_B); + } + break; + case MDX_KEY_LEFT: + if (mcl.currentPage() == FX_PAGE_A) { + goto toggle_mode; + } + else { + mcl.setPage(FX_PAGE_A); + } + break; + } + } + } if (event->mask == EVENT_BUTTON_RELEASED) { return true; } @@ -183,11 +168,13 @@ bool FXPage::handleEvent(gui_event_t *event) { EVENT_PRESSED(event, Buttons.ENCODER2) || EVENT_PRESSED(event, Buttons.ENCODER3) || EVENT_PRESSED(event, Buttons.ENCODER4)) { - // GUI.setPage(&grid_page); + //mcl.setPage(GRID_PAGE); } if (EVENT_PRESSED(event, Buttons.BUTTON1)) { + toggle_mode: page_mode = !(page_mode); update_encoders(); + return true; } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { @@ -196,7 +183,7 @@ bool FXPage::handleEvent(gui_event_t *event) { if (EVENT_PRESSED(event, Buttons.BUTTON4)) { } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } diff --git a/avr/cores/megacommand/MCL/FXPage.h b/avr/cores/megacommand/MCL/FXPage.h index a431a3b94..556af3db9 100644 --- a/avr/cores/megacommand/MCL/FXPage.h +++ b/avr/cores/megacommand/MCL/FXPage.h @@ -14,7 +14,7 @@ typedef struct fx_param_t { //params_ 2 dimensional array, consisting of [MD_FX_TYPE][MD_FX_PARAM_NUMBER] // -class FXPage : public LightPage, MidiCallback { +class FXPage : public LightPage { public: FXPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL, fx_param_t *params_ = NULL, uint8_t num_of_params_ = 0, const char* title = NULL, uint8_t page_id_ = 0) @@ -27,6 +27,8 @@ class FXPage : public LightPage, MidiCallback { } } + static PageIndex last_page; + bool handleEvent(gui_event_t *event); bool midi_state = false; @@ -45,10 +47,6 @@ class FXPage : public LightPage, MidiCallback { void update_encoders(); - void setup_callbacks(); - void remove_callbacks(); - - void onControlChangeCallback_Midi(uint8_t *msg); }; extern MCLEncoder fx_page_param1; diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.cpp b/avr/cores/megacommand/MCL/FileBrowserPage.cpp index 201321288..d301d425f 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/FileBrowserPage.cpp @@ -4,13 +4,12 @@ File FileBrowserPage::file; int FileBrowserPage::numEntries; -char FileBrowserPage::match[5]; -char FileBrowserPage::lwd[128]; char FileBrowserPage::title[12]; -uint8_t FileBrowserPage::cur_col = 0; -uint8_t FileBrowserPage::cur_row = 0; +char FileBrowserPage::str_save[12]; +char FileBrowserPage::focus_match[14]; uint8_t FileBrowserPage::cur_file = 0; +bool FileBrowserPage::draw_dirs = false; bool FileBrowserPage::show_dirs = false; bool FileBrowserPage::select_dirs = false; bool FileBrowserPage::show_save = true; @@ -20,19 +19,20 @@ bool FileBrowserPage::show_filemenu = true; bool FileBrowserPage::show_overwrite = false; bool FileBrowserPage::show_samplemgr = false; -bool FileBrowserPage::show_filetypes = false; -uint8_t FileBrowserPage::filetype_idx = 0; -uint8_t FileBrowserPage::filetype_max = 0; -const char *FileBrowserPage::filetypes[MAX_FT_SELECT]; -const char *FileBrowserPage::filetype_names[MAX_FT_SELECT]; bool FileBrowserPage::filemenu_active = false; bool FileBrowserPage::call_handle_filemenu = false; +FileBrowserFileTypes FileBrowserPage::file_types; + +bool FileBrowserPage::selection_change = false; + +uint16_t FileBrowserPage::selection_change_clock = 0; + void FileBrowserPage::cleanup() { // always call setup() when entering this page. - this->isSetup = false; +// this->isSetup = false; } void FileBrowserPage::setup() { @@ -41,39 +41,42 @@ void FileBrowserPage::setup() { // strcpy(match, mcl); strcpy(title, "Files"); SD.chdir(); - strcpy(lwd,"/"); + strcpy(lwd, "/"); + + encoders[1]->cur = 1; + encoders[2]->cur = 1; } void FileBrowserPage::get_entry(uint16_t n, const char *entry) { + uint8_t discard_type; + get_entry(n, entry, discard_type); +} + +void FileBrowserPage::get_entry(uint16_t n, const char *entry, uint8_t &type) { volatile uint8_t *ptr = - (uint8_t *)BANK1_FILE_ENTRIES_START + n * FILE_ENTRY_SIZE; - get_bank3((volatile void *)entry, ptr, FILE_ENTRY_SIZE); + (uint8_t *)BANK3_FILE_ENTRIES_START + n * FILE_ENTRY_SIZE; + char buf[FILE_ENTRY_SIZE]; + get_bank3(buf, ptr, FILE_ENTRY_SIZE); + type = buf[0]; + strcpy(entry, buf + 1); } -bool FileBrowserPage::add_entry(const char *entry) { +bool FileBrowserPage::add_entry(const char *entry, uint8_t type) { if (numEntries >= NUM_FILE_ENTRIES) { return false; } char buf[FILE_ENTRY_SIZE]; - strncpy(buf, entry, FILE_ENTRY_SIZE); + buf[0] = type; + strncpy(buf + 1, entry, FILE_ENTRY_SIZE - 1); buf[FILE_ENTRY_SIZE - 1] = '\0'; volatile uint8_t *ptr = - (uint8_t *)BANK1_FILE_ENTRIES_START + numEntries * FILE_ENTRY_SIZE; + (uint8_t *)BANK3_FILE_ENTRIES_START + numEntries * FILE_ENTRY_SIZE; put_bank3(ptr, buf, sizeof(buf)); numEntries++; return true; } void FileBrowserPage::query_filesystem() { - if (show_filetypes) { - if (filetype_idx > filetype_max) - filetype_idx = filetype_max; - if (filetype_idx < 0) - filetype_idx = 0; - strcpy(match, filetypes[filetype_idx]); - ((MCLEncoder *)param1)->min = 0; - ((MCLEncoder *)param1)->max = filetype_max; - } char temp_entry[FILE_ENTRY_SIZE]; call_handle_filemenu = false; @@ -82,7 +85,7 @@ void FileBrowserPage::query_filesystem() { file_menu_page.menu.enable_entry(FM_NEW_FOLDER, show_new_folder); file_menu_page.menu.enable_entry(FM_DELETE, true); // delete file_menu_page.menu.enable_entry(FM_RENAME, true); // rename - file_menu_page.menu.enable_entry(FM_OVERWRITE, show_overwrite); + file_menu_page.menu.enable_entry(FM_OVERWRITE, false); //show_overwrite); file_menu_page.menu.enable_entry(FM_CANCEL, true); // cancel file_menu_page.menu.enable_entry(FM_RECVALL, false); file_menu_page.menu.enable_entry(FM_SENDALL, false); @@ -91,6 +94,7 @@ void FileBrowserPage::query_filesystem() { file_menu_encoder.max = file_menu_page.menu.get_number_of_items() - 1; DEBUG_PRINTLN("query"); + DEBUG_PRINTLN(lwd); DEBUG_PRINTLN(file_menu_encoder.max); // reset directory pointer @@ -99,50 +103,40 @@ void FileBrowserPage::query_filesystem() { d.rewind(); numEntries = 0; cur_file = 255; + if (show_save) { - if (filetype_idx == FILETYPE_WAV) { - add_entry("[ RECV ]"); - } else { - add_entry("[ SAVE ]"); - } + add_entry(&str_save[0]); } - //SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); - //SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); + // SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); + // SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); file.getName(temp_entry, FILE_ENTRY_SIZE); - if ((show_parent) && !(strcmp(temp_entry, "/") == 0)) { + if ((show_parent) && !(strcmp(lwd, "/") == 0)) { add_entry(".."); } - cur_row = 1; - encoders[1]->cur = 1; - encoders[1]->old = 1; // iterate through the files while (file.openNext(&d, O_READ) && (numEntries < MAX_ENTRIES)) { - for (uint8_t c = 0; c < FILE_ENTRY_SIZE; c++) { - temp_entry[c] = 0; - } + memset(temp_entry, 0, sizeof(temp_entry)); file.getName(temp_entry, FILE_ENTRY_SIZE); bool is_match_file = false; DEBUG_PRINTLN(numEntries); DEBUG_PRINTLN(temp_entry); + bool is_dir = false; if (temp_entry[0] == '.') { is_match_file = false; } else if (file.isDirectory() && show_dirs) { + is_dir = true; is_match_file = true; } else { // XXX only 3char suffix - char *arg1 = &temp_entry[strlen(temp_entry) - 4]; - if (strcmp(arg1, match) == 0) { - is_match_file = true; - } + is_match_file = file_types.compare(&temp_entry[strlen(temp_entry) - 4]); } if (is_match_file && (strlen(temp_entry) > 0)) { DEBUG_PRINTLN(F("file matched")); - if (add_entry(temp_entry)) { - if (strcmp(temp_entry, mcl_cfg.project) == 0) { + if (add_entry(temp_entry,is_dir)) { + if (strlen(focus_match) > 0 && strcmp(temp_entry, focus_match) == 0) { DEBUG_DUMP(temp_entry); DEBUG_DUMP(mcl_cfg.project); - cur_file = numEntries - 1; encoders[1]->cur = numEntries - 1; } @@ -163,68 +157,76 @@ void FileBrowserPage::query_filesystem() { void FileBrowserPage::init() { filemenu_active = false; show_samplemgr = false; - show_filetypes = false; - query_filesystem(); + draw_dirs = false; + strcpy(focus_match, ""); + file_types.reset(); + SD.chdir(lwd); } -void FileBrowserPage::display() { - if (filemenu_active) { - oled_display.fillRect(0, 3, 45, 28, BLACK); - oled_display.drawRect(1, 4, 43, 26, WHITE); - file_menu_page.draw_menu(6, 12, 39); - oled_display.display(); - return; - } +void FileBrowserPage::draw_menu() { + oled_display.fillRect(0, 3, 45, 28, BLACK); + oled_display.drawRect(1, 4, 43, 26, WHITE); + file_menu_page.draw_menu(6, 12, 39); + oled_display.display(); +} - constexpr uint8_t x_offset = 43, y_offset = 8, width = MENU_WIDTH; +void FileBrowserPage::draw_sidebar() { + constexpr uint8_t x_offset = 43; oled_display.clearDisplay(); oled_display.setFont(&TomThumb); oled_display.setCursor(0, 8); oled_display.setTextColor(WHITE, BLACK); oled_display.println(title); mcl_gui.draw_vertical_dashline(x_offset - 6); +} +void FileBrowserPage::draw_filebrowser() { + + constexpr uint8_t x_offset = 43, y_offset = 8, width = MENU_WIDTH; oled_display.setCursor(x_offset, 8); - uint8_t max_items; - if (numEntries > MAX_VISIBLE_ROWS) { - max_items = MAX_VISIBLE_ROWS; - } else { - max_items = numEntries; - } - for (uint8_t n = 0; n < max_items; n++) { + uint8_t max_items = min(MAX_VISIBLE_ROWS,numEntries); - oled_display.setCursor(x_offset, y_offset + 8 * n); - if (n == cur_row) { + char temp_entry[FILE_ENTRY_SIZE]; + + for (uint8_t n = 0; n < max_items; n++) { + uint8_t y_pos = y_offset + 8 * n; + oled_display.setCursor(x_offset, y_pos); + bool color = n == cur_row; + if (color) { oled_display.setTextColor(BLACK, WHITE); oled_display.fillRect(oled_display.getCursorX() - 3, oled_display.getCursorY() - 6, width, 7, WHITE); } else { oled_display.setTextColor(WHITE, BLACK); - if (encoders[1]->cur - cur_row + n == cur_file) { - oled_display.setCursor(x_offset - 4, y_offset + n * 8); - oled_display.print(">"); - } } - char temp_entry[FILE_ENTRY_SIZE]; + if (encoders[1]->cur - cur_row + n == cur_file) { + oled_display.setCursor(x_offset - 4, y_pos); + oled_display.print(F(">")); + } uint16_t entry_num = encoders[1]->cur - cur_row + n; if (entry_num < numEntries) { - get_entry(entry_num, temp_entry); + uint8_t type; + get_entry(entry_num, temp_entry, type); + if (type == DIR_TYPE && draw_dirs) { + oled_display.drawRect(x_offset, y_pos - 4, 6, 4, !color); + oled_display.drawFastHLine(x_offset + 1, y_pos - 1 - 4, 3, !color); + oled_display.setCursor(x_offset + 8, y_pos); + } oled_display.println(temp_entry); } } if (numEntries > MAX_VISIBLE_ROWS) { draw_scrollbar(120); } +} - if (show_filetypes) { - oled_display.setTextColor(WHITE, BLACK); - for (int i = 0; i <= filetype_max; ++i) { - oled_display.setCursor(2, 17 + i * 7); - oled_display.println(filetype_names[i]); - } - oled_display.fillRect(0, 11 + filetype_idx * 7, 35, 7, INVERT); +void FileBrowserPage::display() { + if (filemenu_active) { + draw_menu(); + return; } - + draw_sidebar(); + draw_filebrowser(); oled_display.display(); return; } @@ -241,7 +243,8 @@ void FileBrowserPage::loop() { } if (encoders[1]->hasChanged()) { - + selection_change = true; + selection_change_clock = slowclock; uint8_t diff = encoders[1]->cur - encoders[1]->old; int8_t new_val = cur_row + diff; @@ -254,12 +257,6 @@ void FileBrowserPage::loop() { // MD.assignMachine(0, encoders[1]->cur); cur_row = new_val; } - - if (show_filetypes && param1->hasChanged()) { - filetype_idx = param1->cur; - chdir_type(); - init(); - } } bool FileBrowserPage::create_folder() { @@ -307,6 +304,12 @@ void FileBrowserPage::_cd_up() { DEBUG_PRINTLN("bad directory change"); } init(); + uint16_t pos = 0; + uint8_t row = 0; + position.pop(pos, row); + encoders[1]->cur = pos; + encoders[1]->old = pos; + cur_row = row; } bool FileBrowserPage::_cd(const char *child) { @@ -329,7 +332,6 @@ bool FileBrowserPage::_cd(const char *child) { return false; } - uint8_t len_lwd = strlen(lwd); if (len_lwd == 1) { @@ -346,7 +348,12 @@ bool FileBrowserPage::_cd(const char *child) { } strcat(lwd, child); DEBUG_PRINTLN(lwd); + uint16_t pos = encoders[1]->getValue(); + uint8_t row = cur_row; init(); + encoders[1]->cur = 1; + encoders[2]->cur = 1; + position.push(pos, row); return true; } @@ -410,19 +417,20 @@ bool FileBrowserPage::_handle_filemenu() { bool FileBrowserPage::rm_dir(const char *dir) { char temp_entry[FILE_ENTRY_SIZE]; - //SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); + // SD.vwd()->getName(temp_entry, FILE_ENTRY_SIZE); DEBUG_PRINTLN("preparing to delete"); DEBUG_PRINTLN(dir); if (_cd(dir)) { File d; d.open(lwd); d.rewind(); - // bool ret = SD.vwd()->rmRfStar(); // extra 276 bytes + // bool ret = SD.vwd()->rmRfStar(); // extra 276 bytes while (file.openNext(&d, O_READ)) { - file.getName(temp_entry, FILE_ENTRY_SIZE); - DEBUG_PRINT("deleting "); DEBUG_PRINTLN(temp_entry); - file.close(); - SD.remove(temp_entry); + file.getName(temp_entry, FILE_ENTRY_SIZE); + DEBUG_PRINT("deleting "); + DEBUG_PRINTLN(temp_entry); + file.close(); + SD.remove(temp_entry); } SD.chdir("/"); _cd_up(); @@ -461,6 +469,8 @@ bool FileBrowserPage::handleEvent(gui_event_t *event) { if (note_interface.is_event(event)) { return false; } + //bool dir_only = false; + if (EVENT_CMD(event)) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { @@ -481,12 +491,14 @@ bool FileBrowserPage::handleEvent(gui_event_t *event) { case MDX_KEY_DOWN: encoders[1]->cur += inc; break; + /* case MDX_KEY_LEFT: - encoders[0]->cur -= inc; + _cd_up(); break; case MDX_KEY_RIGHT: - encoders[0]->cur += inc; - break; + dir_only = true; + goto YES; + */ } } } @@ -504,58 +516,57 @@ bool FileBrowserPage::handleEvent(gui_event_t *event) { encoders[0] = param1; encoders[1] = param2; - _handle_filemenu(); - init(); + filemenu_active = false; + if (_handle_filemenu()) { + init(); + return true; + } + selection_change = true; return true; } if (EVENT_PRESSED(event, Buttons.BUTTON4)) { + GUI.ignoreNextEvent(event->source); YES: int i_save; _calcindices(i_save); - if (encoders[1]->getValue() == i_save) { - on_new(); - return true; - } - char temp_entry[FILE_ENTRY_SIZE]; get_entry(encoders[1]->getValue(), temp_entry); - // chdir to parent - if ((temp_entry[0] == '.') && (temp_entry[1] == '.')) { - _cd_up(); - return true; - } - - DEBUG_DUMP(temp_entry); - // chdir to child if (!show_samplemgr) { file.open(temp_entry, O_READ); + // if (!dir_only) { + + if (encoders[1]->getValue() == i_save) { + on_new(); + goto fin; + } + + // chdir to parent + if ((temp_entry[0] == '.') && (temp_entry[1] == '.')) { + _cd_up(); + goto fin; + } + // } // chdir to child if (!select_dirs && file.isDirectory()) { _cd(temp_entry); - return true; + goto fin; } } - // select an entry - GUI.ignoreNextEvent(event->source); - on_select(temp_entry); + GUI.ignoreNextEvent(event->source); + on_select(temp_entry); + fin: + //file.close(); return true; } // cancel if (EVENT_PRESSED(event, Buttons.BUTTON1)) { + GUI.ignoreNextEvent(event->source); NO: - if (show_samplemgr) { - // on cancel, break out of sample manager - // and intercept cancel event - show_samplemgr = false; - init(); - return true; - } - on_cancel(); return true; } diff --git a/avr/cores/megacommand/MCL/FileBrowserPage.h b/avr/cores/megacommand/MCL/FileBrowserPage.h index a174fc0aa..8ecf6d494 100644 --- a/avr/cores/megacommand/MCL/FileBrowserPage.h +++ b/avr/cores/megacommand/MCL/FileBrowserPage.h @@ -5,10 +5,10 @@ #include "GUI.h" #include "MCLEncoder.h" -#include "SdFat.h" -#include "SeqPage.h" #include "Menu.h" #include "MenuPage.h" +#include "SdFat.h" +#include "SeqPage.h" #define MAX_ENTRIES 1024 @@ -31,21 +31,75 @@ #define FM_RECVALL 5 #define FM_SENDALL 6 -#define FILETYPE_WAV 1 +class FileBrowserFileTypes { + constexpr static uint8_t size = 2; + char types[size][5]; + uint8_t count = 0; + public: + void add(char *str) { + if (count < size) { + strcpy(types[count], str); + count++; + } + } + void reset() { count = 0; } + + bool compare(char *str) { + for (uint8_t n = 0; n < count; n++) { + DEBUG_PRINT("Comparing "); DEBUG_PRINT(str); DEBUG_PRINT(" "); DEBUG_PRINTLN(types[n]); + if (strcmp(str, types[n]) == 0) { + DEBUG_PRINTLN("match"); + return true; + } + } + return false; + } +}; + +class FileSystemPosition { + constexpr static uint8_t size = 12; + uint16_t last_pos[8]; + uint8_t last_cur_row[8]; + uint8_t depth; + public: + void push(uint16_t pos, uint8_t row) { + if (depth < size) { + last_pos[depth] = pos; + last_cur_row[depth] = row; + } + depth++; + } + void pop(uint16_t &pos, uint8_t &row) { + if (depth != 0) { + depth--; + if (depth >= size) { + goto end; + } + pos = last_pos[depth]; + row = last_cur_row[depth]; + return; + } + end: + pos = 1; + row = 1; + } + void reset() { depth = 0; } +}; class FileBrowserPage : public LightPage { public: static File file; static int numEntries; - static char match[5]; - static char lwd[128]; + char lwd[128]; static char title[12]; - static uint8_t cur_col; - static uint8_t cur_row; + static char str_save[12]; + uint8_t cur_row; static uint8_t cur_file; // configuration, should be set before calling base init() + static bool draw_dirs; + static bool show_dirs; static bool select_dirs; static bool show_save; @@ -53,33 +107,42 @@ class FileBrowserPage : public LightPage { static bool show_new_folder; static bool show_filemenu; static bool show_overwrite; - static bool show_samplemgr; - static bool show_filetypes; - static uint8_t filetype_idx; - static uint8_t filetype_max; - static const char* filetypes[MAX_FT_SELECT]; - static const char* filetype_names[MAX_FT_SELECT]; static bool filemenu_active; static bool call_handle_filemenu; - Encoder* param1; - Encoder* param2; + static char focus_match[PRJ_NAME_LEN]; + static FileBrowserFileTypes file_types; + + FileSystemPosition position; + + static bool selection_change; + static uint16_t selection_change_clock; + Encoder *param1; + Encoder *param2; FileBrowserPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) { - param1 = e1; - param2 = e2; - lwd[0] = '\0'; - } + param1 = e1; + param2 = e2; + lwd[0] = '\0'; + } virtual bool handleEvent(gui_event_t *event); + void draw_sidebar(); + void draw_filebrowser(); + void draw_menu(); + virtual void display(); - bool add_entry(const char *entry); + static constexpr uint8_t FILE_TYPE = 0; + static constexpr uint8_t DIR_TYPE = 1; + + bool add_entry(const char *entry, uint8_t type = FILE_TYPE); void get_entry(uint16_t n, const char *entry); + void get_entry(uint16_t n, const char *entry, uint8_t &type); void draw_scrollbar(uint8_t x_offset); bool create_folder(); @@ -97,17 +160,16 @@ class FileBrowserPage : public LightPage { virtual void on_rename(const char *from, const char *to); // on cancel, the page will be popped, // and there's a last chance to clean up. - virtual void on_cancel() { GUI.popPage(); } + virtual void on_cancel() { mcl.popPage(); } virtual void chdir_type() {} virtual bool _handle_filemenu(); + protected: void _cd_up(); bool _cd(const char *); - void query_filesystem(); private: - void _calcindices(int &); }; diff --git a/avr/cores/megacommand/MCL/Grid.cpp b/avr/cores/megacommand/MCL/Grid.cpp index c41bb31e5..7945abed2 100644 --- a/avr/cores/megacommand/MCL/Grid.cpp +++ b/avr/cores/megacommand/MCL/Grid.cpp @@ -64,12 +64,15 @@ bool Grid::new_file(const char *gridname) { bool Grid::new_grid(const char *gridname) { - bool ret; + bool ret = false; DEBUG_PRINT_FN(); DEBUG_PRINTLN(F("Creating new grid")); if (!new_file(gridname)) { - return false; + goto end; + } + if (!write_header()) { + goto end; } DEBUG_PRINTLN(F("Initializing grid.. please wait")); @@ -78,7 +81,7 @@ bool Grid::new_grid(const char *gridname) { #endif // Initialise the project file by filling the grid with blank data. uint8_t ledstatus; - for (int32_t i = 0; i < GRID_LENGTH; i++) { + for (uint16_t i = 0; i < GRID_LENGTH; i++) { #ifdef OLED_DISPLAY mcl_gui.draw_progress("INITIALIZING", i, GRID_LENGTH); @@ -96,26 +99,17 @@ bool Grid::new_grid(const char *gridname) { ret = clear_row(i); if (!ret) { DEBUG_PRINTLN(F("coud not clear row")); - return false; + goto end; } } + ret = true; + end: clearLed2(); - ret = file.seekSet(0); - - if (!ret) { - DEBUG_PRINTLN(F("Could not seek")); - return false; - } - - if (!write_header()) { - return false; - } - file.close(); - return true; + return ret; } -bool Grid::copy_slot(int16_t s_col, int16_t s_row, int16_t d_col, int16_t d_row, +bool Grid::copy_slot(uint8_t s_col, uint16_t s_row, uint8_t d_col, uint16_t d_row, bool destination_same) { DEBUG_PRINT_FN(); DEBUG_PRINT(s_col); @@ -138,14 +132,13 @@ bool Grid::copy_slot(int16_t s_col, int16_t s_row, int16_t d_col, int16_t d_row, track->store_in_grid(d_col, d_row); } -uint8_t Grid::get_slot_model(int column, int row, bool load) { +uint8_t Grid::get_slot_model(uint8_t column, uint16_t row, bool load) { GridTrack temp_track; temp_track.load_from_grid(column, row); - // XXX why active, not the actual model? return temp_track.active; } -bool Grid::clear_slot(int16_t column, int16_t row, bool update_header) { +bool Grid::clear_slot(uint8_t column, uint16_t row, bool update_header) { bool ret; int b; @@ -183,10 +176,10 @@ bool Grid::clear_slot(int16_t column, int16_t row, bool update_header) { return true; } -__attribute__((noinline)) bool Grid::clear_row(int16_t row) { +bool Grid::clear_row(uint16_t row) { GridRowHeader row_header; row_header.init(); - for (int x = 0; x < GRID_WIDTH; x++) { + for (uint8_t x = 0; x < GRID_WIDTH; x++) { clear_slot(x, row, false); } return write_row_header(&row_header, row); diff --git a/avr/cores/megacommand/MCL/Grid.h b/avr/cores/megacommand/MCL/Grid.h index b6f45f1ad..f752321e4 100644 --- a/avr/cores/megacommand/MCL/Grid.h +++ b/avr/cores/megacommand/MCL/Grid.h @@ -3,7 +3,6 @@ #ifndef GRID_H__ #define GRID_H__ -#include "A4Track.h" #include "GridRowHeader.h" #include "MCLSd.h" #include "SdFat.h" @@ -41,19 +40,19 @@ class Grid : public GridHeader { bool close_file() { return file.close(); } - uint8_t get_slot_model(int column, int row, bool load); + uint8_t get_slot_model(uint8_t column, uint16_t row, bool load); - uint32_t get_slot_offset(int16_t column, int16_t row) { - uint32_t offset = (int32_t)(GRID_SLOT_BYTES * GRID_WIDTH) + - (int32_t)((column + 1) + (row * (GRID_WIDTH + 1))) * - (int32_t)GRID_SLOT_BYTES; + uint32_t get_slot_offset(uint8_t column, int16_t row) { + uint32_t offset = (uint32_t)(GRID_SLOT_BYTES * GRID_WIDTH) + + (uint32_t)((column + 1) + (row * (GRID_WIDTH + 1))) * + (uint32_t)GRID_SLOT_BYTES; return offset; } uint32_t get_row_header_offset(int16_t row) { uint32_t offset = - (int32_t)(GRID_SLOT_BYTES * GRID_WIDTH) + - (int32_t)(0 + (row * (GRID_WIDTH + 1))) * (int32_t)GRID_SLOT_BYTES; + (uint32_t)(GRID_SLOT_BYTES * GRID_WIDTH) + + (uint32_t)(0 + (row * (GRID_WIDTH + 1))) * (uint32_t)GRID_SLOT_BYTES; return offset; } @@ -65,11 +64,11 @@ class Grid : public GridHeader { return mcl_sd.seek(get_row_header_offset(row), &file); } - bool copy_slot(int16_t s_col, int16_t s_row, int16_t d_col, int16_t d_row, + bool copy_slot(uint8_t s_col, uint16_t s_row, uint8_t d_col, uint16_t d_row, bool destination_same); - bool clear_slot(int16_t column, int16_t row, bool update_header = true); - bool clear_row(int16_t row); - bool clear_model(int16_t column, uint16_t row); + bool clear_slot(uint8_t column, uint16_t row, bool update_header = true); + bool clear_row(uint16_t row); + bool clear_model(uint8_t column, uint16_t row); bool read(void *data, size_t len) { return mcl_sd.read_data((uint8_t *)(data), len, &file); diff --git a/avr/cores/megacommand/MCL/GridChainTrack.h b/avr/cores/megacommand/MCL/GridChainTrack.h index e97f8ebc8..b409aa3dd 100644 --- a/avr/cores/megacommand/MCL/GridChainTrack.h +++ b/avr/cores/megacommand/MCL/GridChainTrack.h @@ -24,7 +24,7 @@ class GridChainTrack : public AUXTrack { void place_chains(); virtual uint16_t get_track_size() { return sizeof(GridChainTrack); } - virtual uint32_t get_region() { return BANK1_GRIDCHAIN_TRACK_START; } + virtual uint16_t get_region() { return BANK1_GRIDCHAIN_TRACK_START; } virtual uint8_t get_model() { return GRIDCHAIN_TRACK_TYPE; } virtual uint8_t get_device_type() { return GRIDCHAIN_TRACK_TYPE; } diff --git a/avr/cores/megacommand/MCL/GridEncoder.cpp b/avr/cores/megacommand/MCL/GridEncoder.cpp deleted file mode 100644 index e214a69aa..000000000 --- a/avr/cores/megacommand/MCL/GridEncoder.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "MCL_impl.h" - -int GridEncoder::update(encoder_t *enc) { - uint8_t amount = abs(enc->normal); - int inc = 0; - - while (amount > 0) { - if (enc->normal > 0) { - rot_counter_up += 1; - if (rot_counter_up > rot_res) { - rot_counter_up = 0; - inc += 1; - } - rot_counter_down = 0; - } - if (enc->normal < 0) { - rot_counter_down += 1; - if (rot_counter_down > rot_res) { - rot_counter_down = 0; - inc -= 1; - } - - rot_counter_up = 0; - } - amount--; - } - inc = inc + (pressmode ? 0 : (fastmode ? 5 * enc->button : enc->button)); - cur = limit_value(cur, inc, min, max); - - return cur; -} - -void GridEncoder::displayAt(int i) {} diff --git a/avr/cores/megacommand/MCL/GridEncoder.h b/avr/cores/megacommand/MCL/GridEncoder.h deleted file mode 100644 index bdd47b2fc..000000000 --- a/avr/cores/megacommand/MCL/GridEncoder.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2018, Justin Mammarella jmamma@gmail.com */ - -#ifndef GRIDENCODER_H__ -#define GRIDENCODER_H__ - -#include "GUI.h" - -class GridEncoder : public Encoder { - /** - \addtogroup gui_rangeencoder_class - @{ - **/ - -public: - /** Minimum value of the encoder. **/ - int min; - /** Maximum value of the encoder. **/ - int max; - - uint8_t fxparam; - uint8_t effect; - uint8_t num; - bool scroll_fastmode = false; - /** - Create a new range-limited encoder with max and min value, short - name, initial value, and handling function. The initRangeEncoder - will be called with the constructor arguments. - **/ - - GridEncoder(int _max = 127, int _min = 0, int res = 1) { - initGridEncoder(_max, _min, (int)0, res, - (encoder_handle_t)NULL); - } - - /** - Initialize the encoder with the same argument as the constructor. - - The initRangeEncoder functions automatically determines which of - min and max is the minimum value. As of now this can't be used to - have an "inverted" encoder. - - The initial value is called without calling the handling function. - **/ - void initGridEncoder(int _max = 128, int _min = 0, - int init = 0, int res = 1, - encoder_handle_t _handler = NULL) { - rot_res = res; - handler = _handler; - if (_min > _max) { - min = _max; - max = _min; - } else { - min = _min; - max = _max; - } - setValue(init); - } - - /** - Update the value of the encoder according to pressmode and - fastmode, and limit the resulting value using limit_value(). - **/ - virtual int update(encoder_t *enc); - virtual void displayAt(int i); - - /* @} */ -}; - -#endif /* GRIDENCODER_H__ */ diff --git a/avr/cores/megacommand/MCL/GridIOPage.cpp b/avr/cores/megacommand/MCL/GridIOPage.cpp index ab97b3bd9..edbb70cd8 100644 --- a/avr/cores/megacommand/MCL/GridIOPage.cpp +++ b/avr/cores/megacommand/MCL/GridIOPage.cpp @@ -1,4 +1,5 @@ #include "MCL_impl.h" +#include "ResourceManager.h" uint32_t GridIOPage::track_select = 0; bool GridIOPage::show_track_type = false; @@ -14,37 +15,65 @@ void GridIOPage::init() { old_grid = proj.get_grid(); show_track_type = false; track_select = 0; + R.Clear(); + R.use_icons_logo(); } void GridIOPage::track_select_array_from_type_select( uint8_t *track_select_array) { - uint8_t track_idx, dev_idx; - for (uint8_t n = 0; n < NUM_SLOTS; n++) { - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(n); + uint8_t device_idx = gdt->device_idx; if (gdt == nullptr) continue; - - if ((gdt->group_type == GROUP_DEV) && - IS_BIT_SET16(mcl_cfg.track_type_select, dev_idx)) { - track_select_array[n] = 1; + uint8_t match = 255; + switch (gdt->group_type) { + case GROUP_DEV: + match = gdt->device_idx; + break; + case GROUP_AUX: + case GROUP_PERF: + case GROUP_TEMPO: + match = gdt->group_type + 1; + break; } - // AUX tracks - if ((gdt->group_type == GROUP_AUX) && - IS_BIT_SET16(mcl_cfg.track_type_select, 2)) { - track_select_array[n] = 1; + if (match == 255) { + continue; } - - if ((gdt->group_type == GROUP_TEMPO) && - IS_BIT_SET16(mcl_cfg.track_type_select, 3)) { + if (IS_BIT_SET16(mcl_cfg.track_type_select, match)) { track_select_array[n] = 1; } } } bool GridIOPage::handleEvent(gui_event_t *event) { + if (note_interface.is_event(event)) { + uint8_t track = event->source - 128; + if (event->mask == EVENT_BUTTON_PRESSED) { + if (show_track_type) { + if (track < 5) { + TOGGLE_BIT16(mcl_cfg.track_type_select, track); + MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); + } + } else { + trig_interface.send_md_leds(TRIGLED_OVERLAY); + } + } else { + if (!show_track_type) { + trig_interface.send_md_leds(TRIGLED_OVERLAY); + if (note_interface.notes_all_off()) { + if (BUTTON_DOWN(Buttons.BUTTON2)) { + return true; + } else { + action(); + } + } + } + } + + return true; + } if (EVENT_CMD(event)) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { @@ -56,10 +85,10 @@ bool GridIOPage::handleEvent(gui_event_t *event) { group_select(); return true; } - case MDX_KEY_BANKGROUP: { + case MDX_KEY_SCALE: { goto toggle_grid; } - } + } } } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { @@ -83,17 +112,17 @@ bool GridIOPage::handleEvent(gui_event_t *event) { return true; } if (EVENT_PRESSED(event, Buttons.ENCODER4)) { -// encoders[3]->pressmode = !encoders[3]->pressmode; + // encoders[3]->pressmode = !encoders[3]->pressmode; } - // if (EVENT_PRESSED(event, Buttons.ENCODER1) || + // if (EVENT_PRESSED(event, Buttons.ENCODER1) || // EVENT_PRESSED(event, Buttons.ENCODER2) || // EVENT_PRESSED(event, Buttons.ENCODER3) || // EVENT_PRESSED(event, Buttons.ENCODER4)) { - // } - if (EVENT_RELEASED(event, Buttons.BUTTON1) || + // } + if (EVENT_RELEASED(event, Buttons.BUTTON1) || EVENT_RELEASED(event, Buttons.BUTTON4)) { - close: - GUI.setPage(&grid_page); + close: + mcl.setPage(GRID_PAGE); return true; } return false; diff --git a/avr/cores/megacommand/MCL/GridIOPage.h b/avr/cores/megacommand/MCL/GridIOPage.h index dc438bc18..f41a2a6ba 100644 --- a/avr/cores/megacommand/MCL/GridIOPage.h +++ b/avr/cores/megacommand/MCL/GridIOPage.h @@ -20,6 +20,7 @@ class GridIOPage : public LightPage { virtual void cleanup(); virtual void draw_popup(); virtual void group_select(); + virtual void action() = 0; virtual bool handleEvent(gui_event_t *event); }; diff --git a/avr/cores/megacommand/MCL/GridLoadPage.cpp b/avr/cores/megacommand/MCL/GridLoadPage.cpp index f4459be36..ad30cfa8d 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.cpp +++ b/avr/cores/megacommand/MCL/GridLoadPage.cpp @@ -7,17 +7,18 @@ void GridLoadPage::init() { note_interface.init_notes(); trig_interface.send_md_leds(TRIGLED_OVERLAY); trig_interface.on(); - draw_popup_title(); // GUI.display(); encoders[0]->cur = mcl_cfg.load_mode; encoders[1]->cur = mcl_cfg.chain_queue_length; encoders[3]->cur = mcl_cfg.chain_load_quant; + + draw_popup_title(mcl_cfg.load_mode); } void GridLoadPage::setup() {} -void GridLoadPage::get_mode_str(char *str) { - switch (encoders[0]->cur) { +void GridLoadPage::get_mode_str(char *str, uint8_t mode) { + switch (mode) { case LOAD_MANUAL: { strcpy(str, "MANUAL"); break; @@ -34,10 +35,10 @@ void GridLoadPage::get_mode_str(char *str) { } } } -void GridLoadPage::draw_popup_title() { +void GridLoadPage::draw_popup_title(uint8_t mode, bool persistent) { char modestr[16] = "LOAD "; - get_mode_str(modestr + 5); - MD.popup_text(modestr, true); + get_mode_str(modestr + 5, mode); + MD.popup_text(modestr, persistent); } void GridLoadPage::draw_popup() { @@ -48,12 +49,12 @@ void GridLoadPage::draw_popup() { strcpy(str, "LOAD FROM "); str[10] = 'X' + proj.get_grid(); } - mcl_gui.draw_popup(str, true, 28); + mcl_gui.draw_popup(str, true); } void GridLoadPage::display_load() { - char *str2 = " SLOTS"; - char *str1 = "LOAD"; + const char *str2 = " SLOTS"; + const char *str1 = "LOAD"; if (mcl_cfg.load_mode == LOAD_QUEUE) { str1 = "QUEUE"; } @@ -64,10 +65,10 @@ void GridLoadPage::display_load() { oled_display.textbox(str1, str2); } -void GridLoadPage::get_modestr(char *modestr) { +void GridLoadPage::loop() { if (encoders[0]->hasChanged()) { mcl_cfg.load_mode = encoders[0]->cur; - draw_popup_title(); + draw_popup_title(mcl_cfg.load_mode); } if (encoders[1]->hasChanged()) { if (encoders[0]->cur == LOAD_QUEUE) { @@ -81,6 +82,10 @@ void GridLoadPage::get_modestr(char *modestr) { mcl_cfg.chain_load_quant = encoders[3]->cur; } + +} + +void GridLoadPage::get_modestr(char *modestr) { switch (encoders[0]->cur) { case LOAD_MANUAL: { strcpy(modestr, "MAN"); @@ -108,26 +113,25 @@ void GridLoadPage::display() { auto oldfont = oled_display.getFont(); if (show_track_type) { - mcl_gui.draw_track_type_select(36, MCLGUI::s_menu_y + 12, - mcl_cfg.track_type_select); + mcl_gui.draw_track_type_select(mcl_cfg.track_type_select); } else { - mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 21, note_interface.notes_off | note_interface.notes_on ); + mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 4 + 20, note_interface.notes_off | note_interface.notes_on ); oled_display.setFont(&Elektrothic); - oled_display.setCursor(MCLGUI::s_menu_x + 4, 22); + oled_display.setCursor(MCLGUI::s_menu_x + 4, 21); oled_display.print((char) (0x3A + proj.get_grid())); oled_display.setFont(&TomThumb); char K[4] = {'\0'}; - // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 4, + // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 8, // "STEP", K); char modestr[7]; get_modestr(modestr); - mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4 + 9, MCLGUI::s_menu_y + 4, + mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4 + 9, MCLGUI::s_menu_y + 7, "MODE", modestr); @@ -137,7 +141,7 @@ void GridLoadPage::display() { } else { mcl_gui.put_value_at(encoders[1]->cur, K); } - mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 28 + 9, MCLGUI::s_menu_y + 4, + mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 28 + 9, MCLGUI::s_menu_y + 7, "LEN", K); } // draw quantize @@ -147,7 +151,7 @@ void GridLoadPage::display() { mcl_gui.put_value_at(mcl_cfg.chain_load_quant, K); } mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + MCLGUI::s_menu_w - 38, - MCLGUI::s_menu_y + 4, "QUANT", K); + MCLGUI::s_menu_y + 7, "QUANT", K); oled_display.setFont(&TomThumb); // draw step count @@ -156,30 +160,30 @@ void GridLoadPage::display() { (64 * ((MidiClock.div16th_counter - mcl_actions.start_clock32th / 2) / 64)); oled_display.setCursor(MCLGUI::s_menu_x + MCLGUI::s_menu_w - 11, - MCLGUI::s_menu_y + 18); + MCLGUI::s_menu_y + 4 + 17); oled_display.print(step_count); // draw data flow in the center /* - oled_display.setCursor(48, MCLGUI::s_menu_y + 12); - oled_display.print("SND"); - oled_display.setCursor(46, MCLGUI::s_menu_y + 19); - oled_display.print("GRID"); - - mcl_gui.draw_horizontal_arrow(63, MCLGUI::s_menu_y + 8, 5); - mcl_gui.draw_horizontal_arrow(63, MCLGUI::s_menu_y + 15, 5); - - oled_display.setCursor(74, MCLGUI::s_menu_y + 12); - oled_display.print("MD"); - oled_display.setCursor(74, MCLGUI::s_menu_y + 19); - oled_display.print("SEQ"); + oled_display.setCursor(48, MCLGUI::s_menu_y + 4 + 12); + oled_display.print(F("SND")); + oled_display.setCursor(46, MCLGUI::s_menu_y + 4 + 19); + oled_display.print(F("GRID")); + + mcl_gui.draw_horizontal_arrow(63, MCLGUI::s_menu_y + 4 + 8, 5); + mcl_gui.draw_horizontal_arrow(63, MCLGUI::s_menu_y + 4 + 15, 5); + + oled_display.setCursor(74, MCLGUI::s_menu_y + 4 + 12); + oled_display.print(F("MD")); + oled_display.setCursor(74, MCLGUI::s_menu_y + 4 + 19); + oled_display.print(F("SEQ")); */ } oled_display.display(); oled_display.setFont(oldfont); } void GridLoadPage::load() { - display_load(); + //display_load(); // oled_display.display(); /// !Note, note_off_event has reentry issues, so we have to first set /// the page to avoid driving this code path again. @@ -197,7 +201,7 @@ void GridLoadPage::load() { track_select_array[n] = 1; } } - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); trig_interface.off(); grid_task.load_queue.put(mcl_cfg.load_mode, grid_page.getRow(), track_select_array); @@ -205,19 +209,20 @@ void GridLoadPage::load() { void GridLoadPage::group_select() { show_track_type = true; - MD.popup_text("LOAD GROUPS", true); + char str[] = "LOAD GROUPS"; + MD.popup_text(str, true); MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); } -void GridLoadPage::group_load(uint8_t row, bool silent) { +void GridLoadPage::group_load(uint8_t row) { if (row >= GRID_LENGTH) { return; } uint8_t track_select_array[NUM_SLOTS] = {0}; track_select_array_from_type_select(track_select_array); // load_tracks_to_md(-1); - if (!silent) { - oled_display.textbox("LOAD GROUPS", ""); - } + // if (!silent) { + // oled_display.textbox("LOAD GROUPS", ""); + // } //oled_display.display(); mcl_actions.write_original = 1; @@ -230,39 +235,12 @@ bool GridLoadPage::handleEvent(gui_event_t *event) { return true; } DEBUG_DUMP(event->source); - if (note_interface.is_event(event)) { - uint8_t track = event->source - 128; - if (event->mask == EVENT_BUTTON_PRESSED) { - if (show_track_type) { - if (track < 4) { - TOGGLE_BIT16(mcl_cfg.track_type_select, track); - MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); - } - } else { - trig_interface.send_md_leds(TRIGLED_OVERLAY); - } - } else { - if (!show_track_type) { - trig_interface.send_md_leds(TRIGLED_OVERLAY); - if (note_interface.notes_all_off()) { - DEBUG_PRINTLN(F("notes all off")); - if (BUTTON_DOWN(Buttons.BUTTON2)) { - return true; - } else { - load(); - } - } - } - } - return true; - } - if (EVENT_CMD(event)) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { default: { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return false; } case MDX_KEY_YES: { @@ -299,7 +277,7 @@ bool GridLoadPage::handleEvent(gui_event_t *event) { group_load(grid_page.getRow()); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } } diff --git a/avr/cores/megacommand/MCL/GridLoadPage.h b/avr/cores/megacommand/MCL/GridLoadPage.h index c88eaf3fb..5f9f6c10f 100644 --- a/avr/cores/megacommand/MCL/GridLoadPage.h +++ b/avr/cores/megacommand/MCL/GridLoadPage.h @@ -15,13 +15,15 @@ class GridLoadPage : public GridIOPage { void get_modestr(char *modestr); void load(); void group_select(); - void group_load(uint8_t row, bool silent = false); + void group_load(uint8_t row); bool handleEvent(gui_event_t *event); - void get_mode_str(char *str); + void get_mode_str(char *str, uint8_t mode); void display_load(); void draw_popup(); - void draw_popup_title(); + void draw_popup_title(uint8_t mode, bool persistent = true); + void loop(); void display(); + void action() { load(); } void init(); void setup(); }; diff --git a/avr/cores/megacommand/MCL/GridPage.cpp b/avr/cores/megacommand/MCL/GridPage.cpp index 2b0f24c37..68bfa2f21 100644 --- a/avr/cores/megacommand/MCL/GridPage.cpp +++ b/avr/cores/megacommand/MCL/GridPage.cpp @@ -9,7 +9,7 @@ void GridPage::init() { show_slot_menu = false; reload_slot_models = false; // Edge case, prevent R.Clear being called if we're outside of GridPage - if (GUI.currentPage() != &grid_page) { + if (mcl.currentPage() != GRID_PAGE) { return; } trig_interface.off(); @@ -22,6 +22,7 @@ void GridPage::init() { void GridPage::setup() { encoders[0]->cur = encoders[0]->old = mcl_cfg.col; encoders[1]->cur = encoders[1]->old = mcl_cfg.row; + encoders[2]->cur = 1; cur_col = mcl_cfg.cur_col; cur_row = mcl_cfg.cur_row; memset(active_slots, SLOT_DISABLED, sizeof(active_slots)); @@ -71,8 +72,6 @@ void GridPage::send_row_led() { if (row >= GRID_LENGTH) { return; } SET_BIT128_P(&rows, grid_task.last_active_row); uint16_t *blink_mask = (uint16_t *)&rows[0]; - DEBUG_PRINTLN("Sending row led"); - DEBUG_PRINTLN(blink_mask[grid_page.bank]); MD.set_trigleds(blink_mask[grid_page.bank], TRIGLED_EXCLUSIVENDYNAMIC, 1); } void GridPage::close_bank_popup() { @@ -80,21 +79,52 @@ void GridPage::close_bank_popup() { MD.draw_close_bank(); } trig_interface.off(); - if (last_page != nullptr) { + if (last_page != 255) { DEBUG_PRINTLN("setting page"); - GUI.setPage(last_page); + mcl.setPage(last_page); } - last_page = nullptr; + last_page = 255; bank_popup = 0; note_interface.init_notes(); // Clear blink leds MD.set_trigleds(0, TRIGLED_EXCLUSIVENDYNAMIC, 1); } +void GridPage::load_old_col() { + cur_col = old_col; + param1.cur = cur_col; + param1.old = cur_col; + encoders[2]->cur = GRID_WIDTH - cur_col; + encoders[2]->old = encoders[2]->cur; + grid_page.grid_select_apply = 0; + proj.grid_select = 0; + ((MCLEncoder *)encoders[2])->max = getWidth() + 1; +} + void GridPage::loop() { int8_t diff, new_val; if (show_slot_menu) { - + if (encoders[2]->hasChanged()) { + if ((proj.get_grid() == 0) && (getCol() + encoders[2]->cur > GRID_WIDTH)) { + old_col = getCol(); + cur_col = 0; + param1.cur = 0; + param1.old = 0; + encoders[2]->cur = 1; + encoders[2]->old = 1; + grid_page.grid_select_apply = 1; + proj.grid_select = 1; + ((MCLEncoder *)encoders[2])->max = getWidth(); + load_slot_models(); + reload_slot_models = true; + } + else if ((proj.get_grid() == 1) && (encoders[2]->cur == 0) && (old_col != 255)) { + load_old_col(); + load_slot_models(); + reload_slot_models = true; + } + if (encoders[2]->cur == 0) { encoders[2]->cur = 1; encoders[2]->old = 1; } + } if (encoders[3]->hasChanged()) { if (cur_row + encoders[3]->cur > MAX_VISIBLE_ROWS - 1) { load_slot_models(); @@ -114,6 +144,9 @@ void GridPage::loop() { } } */ + if (encoders[2]->hasChanged()) { + if (encoders[2]->cur == 0) { encoders[2]->cur = 1; encoders[2]->old = 1; } + } if (encoders[0]->hasChanged()) { diff = encoders[0]->cur - encoders[0]->old; new_val = cur_col + diff; @@ -149,7 +182,7 @@ void GridPage::loop() { } encoders[2]->cur = 1; encoders[3]->cur = 1; - ((MCLEncoder *)encoders[2])->max = getWidth() - getCol(); + //((MCLEncoder *)encoders[2])->max = getWidth() + 1 - getCol(); ((MCLEncoder *)encoders[3])->max = GRID_LENGTH - getRow(); if (!reload_slot_models) { @@ -227,7 +260,7 @@ uint8_t GridPage::getCol() { return param1.cur; } uint8_t GridPage::getWidth() { return GRID_WIDTH; } void GridPage::load_slot_models() { - DEBUG_PRINT_FN(); + DEBUG_PRINTLN("load slot models"); uint8_t row_shift = 0; if ((cur_row + encoders[3]->cur > MAX_VISIBLE_ROWS - 1)) { row_shift = cur_row + encoders[3]->cur - MAX_VISIBLE_ROWS; @@ -258,7 +291,7 @@ void GridPage::display_counters() { oled_display.setCursor(24, y_offset); oled_display.print(val); - oled_display.print(":"); + oled_display.print(F(":")); oled_display.print(MidiClock.beat_counter); if ((mcl_actions.next_transition != (uint16_t)-1) && @@ -275,7 +308,7 @@ void GridPage::display_counters() { } oled_display.setCursor(24, y_offset + 8); oled_display.print(val); - oled_display.print(":"); + oled_display.print(F(":")); oled_display.print(mcl_actions.nearest_beat); } } @@ -290,7 +323,7 @@ void GridPage::display_grid_info() { display_counters(); oled_display.setFont(&TomThumb); - // oled_display.print(":"); + // oled_display.print(F(":")); // oled_display.print(MidiClock.step_counter); oled_display.setCursor(22, y_offset + 1 * 8); @@ -327,7 +360,7 @@ void GridPage::display_grid_info() { mcl_gui.put_value_at2(encoders[0]->cur + 1, val); val[2] = '\0'; oled_display.print(val); - oled_display.print(" "); + oled_display.print(F(" ")); uint8_t b = encoders[1]->cur / 16; oled_display.print((char)('A' + b)); mcl_gui.put_value_at2(encoders[1]->cur - b * 16 + 1, val); @@ -437,6 +470,10 @@ void GridPage::display_grid() { str[0] = 'C'; str[1] = 'N'; break; + case PERF_TRACK_TYPE: + str[0] = 'P'; + str[1] = 'F'; + break; case MNM_TRACK_TYPE: tmp = getMNMMachineNameShort(model, 2); if (tmp) { @@ -567,11 +604,11 @@ void rename_row() { void apply_slot_changes_cb() { grid_page.apply_slot_changes(); } -void GridPage::swap_grids() { +bool GridPage::swap_grids() { if (grid_select_apply != proj.grid_select) { proj.grid_select = grid_select_apply; ((MCLEncoder *)encoders[0])->max = getWidth() - 1; - // load_slot_models(); + //load_slot_models(); return; } } @@ -580,15 +617,27 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { uint8_t width; uint8_t height; + uint8_t _col = getCol();; + + //old_col != 255 indicates that the grid selection spans grids x and y. + if (old_col != 255) { + _col = old_col; + proj.select_grid(0); + } + GridTrack temp_slot; + temp_slot.load_from_grid(_col, getRow()); - temp_slot.load_from_grid(getCol(), getRow()); + if (old_col == 255) { + if (swap_grids()) { return; } + } uint8_t load_mode_old = mcl_cfg.load_mode; - uint8_t undo = slot_undo && !ignore_undo && slot_undo_x == getCol() && + uint8_t undo = slot_undo && !ignore_undo && slot_undo_x == _col && slot_undo_y == getRow(); DEBUG_PRINTLN("apply slot"); - swap_grids(); + + if (!ignore_func) { void (*row_func)() = grid_slot_page.menu.get_row_function(grid_slot_page.encoders[1]->cur); @@ -598,34 +647,11 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { return; } } - width = encoders[2]->cur; + width = old_col != 255 ? GRID_WIDTH - _col : encoders[2]->cur; height = encoders[3]->cur; uint8_t slot_update = 0; - if (insert_rows) { - int8_t row_count = GRID_LENGTH - getRow() - insert_rows; - uint8_t row_dst = getRow() + insert_rows; - if (row_dst > GRID_LENGTH || row_count < 1) { - return; - } - - if (mcl_gui.wait_for_confirm("Insert", "Rows?")) { - for (uint8_t g = 0; g < 2; g++) { - for (uint8_t n = 0; n < row_count; n++) { - if (n % 8) mcl_gui.draw_progress("INSERT ROWS", n + g * row_count, row_count * 2); - mcl_clipboard.copy(0, getRow() + row_count - n - insert_rows, - GRID_WIDTH, 1, g); - mcl_clipboard.paste(0, getRow() + row_count - n, g); - } - for (uint8_t n = 0; n < insert_rows; n++) { - proj.clear_row_grid(getRow() + n, g); - } - } - } - goto end; - } - if (slot_copy + slot_paste + slot_clear + slot_load + undo == 0) { if ((temp_slot.link.row != slot.link.row) || (temp_slot.link.loops != slot.link.loops) || @@ -641,7 +667,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { if (slot_copy == 1 || (slot_clear == 1 && !undo)) { if (slot_clear == 1) { - slot_undo_x = getCol(); + slot_undo_x = _col; slot_undo_y = getRow(); if (width > 0) { oled_display.textbox("CLEAR ", "SLOTS"); @@ -657,11 +683,18 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { oled_display.textbox("COPY ", "SLOT"); } } - mcl_clipboard.copy(getCol(), getRow(), width, height, proj.get_grid()); + mcl_clipboard.copy(_col + 16 * proj.get_grid(), getRow(), width, height); + if (old_col != 255 && proj.get_grid() == 0) { + mcl_clipboard.copy(16, getRow(), encoders[2]->cur, height); + mcl_clipboard.t_col = _col; + mcl_clipboard.t_w += GRID_WIDTH - cur_col; + DEBUG_PRINTLN("copy grid 1+2"); + DEBUG_PRINTLN(mcl_clipboard.t_w); + } + } if (slot_clear) { goto run; } - } else if (slot_paste == 1) { if (undo) { @@ -670,7 +703,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { oled_display.textbox("PASTE", ""); } slot_undo = 0; - mcl_clipboard.paste(getCol(), getRow(), proj.get_grid()); + mcl_clipboard.paste(_col + 16 * proj.get_grid(), getRow()); } else { if (slot_update == 1) { oled_display.textbox("SLOT ", "UPDATE"); @@ -686,14 +719,17 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { oled_display.display(); + bool activate_header = false; - uint8_t track_select_array[GRID_LENGTH] = {0}; + uint8_t track_select_array[NUM_SLOTS] = {0}; GridRowHeader header; SeqTrack seq_track; uint16_t target_length = slot.link.length * seq_track.get_speed_multiplier(slot.link.speed) * slot.link.loops; + again: + for (uint8_t y = 0; y < height && y + getRow() < GRID_LENGTH; y++) { uint8_t ypos = y + getRow(); proj.read_grid_row_header(&header, y + getRow()); @@ -703,8 +739,8 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { if (slot_clear && height > 8) { mcl_gui.draw_progress("", y, height); } - for (uint8_t x = 0; x < width && x + getCol() < getWidth(); x++) { - uint8_t xpos = x + getCol(); + for (uint8_t x = 0; x < width && x + _col < getWidth(); x++) { + uint8_t xpos = x + _col; if (slot_clear == 1) { // Delete slot(s) proj.clear_slot_grid(xpos, ypos); @@ -738,6 +774,7 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { } } if (slot_load == 1) { + DEBUG_PRINTLN("slot load put"); grid_task.load_queue.put(mcl_cfg.load_mode,ypos, track_select_array); } // If all slots are deleted then clear the row name @@ -748,11 +785,20 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { } } } -end: - if ((slot_clear == 1) || (slot_paste == 1) || (slot_update == 1) || - (insert_rows == 1)) { + end: + + if ((slot_clear == 1) || (slot_paste == 1) || (slot_update == 1)) { proj.sync_grid(); - load_slot_models(); + } + + if (old_col != 255) { + if (proj.get_grid() == 0) { + proj.select_grid(1); + width = encoders[2]->cur; + _col = 0; + goto again; + } + load_old_col(); } mcl_cfg.load_mode = load_mode_old; slot_apply = 0; @@ -760,8 +806,8 @@ void GridPage::apply_slot_changes(bool ignore_undo, bool ignore_func) { slot_clear = 0; slot_copy = 0; slot_paste = 0; - insert_rows = 0; - slot.load_from_grid(getCol(), getRow()); + slot.load_from_grid(_col, getRow()); + old_col = 255; } bool GridPage::handleEvent(gui_event_t *event) { @@ -779,8 +825,10 @@ bool GridPage::handleEvent(gui_event_t *event) { if (event->mask == EVENT_BUTTON_RELEASED) { if (grid_page.bank_popup > 0) { if (note_interface.notes_all_off()) { - note_interface.init_notes(); + //note_interface.init_notes(); grid_page.bank_popup_loadmask = 0; + //grid_page.bank_popup = 0; + grid_page.close_bank_popup(); } return true; } @@ -832,24 +880,24 @@ bool GridPage::handleEvent(gui_event_t *event) { uint8_t key = event->source - 64; if (trig_interface.is_key_down(MDX_KEY_PATSONG)) { - if (key == MDX_KEY_PATSONGKIT && event->mask == EVENT_BUTTON_PRESSED) { - grid_page.grid_select_apply = !grid_page.grid_select_apply; - swap_grids(); - init(); - return true; - } - if (show_slot_menu) { + if (show_slot_menu) { if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { case MDX_KEY_BANKA: case MDX_KEY_BANKB: case MDX_KEY_BANKC: { mcl_cfg.load_mode = key - MDX_KEY_BANKA + 1; + bool persistent = false; + grid_load_page.draw_popup_title(mcl_cfg.load_mode, persistent); return true; } case MDX_KEY_NO: { goto next; } + case MDX_KEY_PATSONGKIT: { + set_active_row(grid_task.last_active_row); + return true; + } } } return grid_slot_page.handleEvent(event); @@ -859,7 +907,7 @@ bool GridPage::handleEvent(gui_event_t *event) { if (event->mask == EVENT_BUTTON_PRESSED) { uint8_t inc = 1; if (trig_interface.is_key_down(MDX_KEY_FUNC)) { - inc = 16; + inc = 4; } if (show_slot_menu) { switch (key) { @@ -928,9 +976,15 @@ bool GridPage::handleEvent(gui_event_t *event) { return true; } } - } + } } switch (key) { + case MDX_KEY_SCALE: { + grid_page.grid_select_apply = !grid_page.grid_select_apply; + swap_grids(); + init(); + return true; + } case MDX_KEY_UP: { up: param2.cur -= inc; @@ -1007,14 +1061,14 @@ bool GridPage::handleEvent(gui_event_t *event) { if (!show_slot_menu) { if (EVENT_RELEASED(event, Buttons.BUTTON1)) { save: - GUI.setPage(&grid_save_page); + mcl.setPage(GRID_SAVE_PAGE); return true; } if (EVENT_RELEASED(event, Buttons.BUTTON4)) { load: - GUI.setPage(&grid_load_page); + mcl.setPage(GRID_LOAD_PAGE); return true; } @@ -1033,15 +1087,17 @@ bool GridPage::handleEvent(gui_event_t *event) { encoders[2]->cur = 1; encoders[3]->cur = 1; slot_apply = 0; + old_col = 255; if (!slot.is_ext_track()) { - grid_slot_page.menu.enable_entry(2, true); - grid_slot_page.menu.enable_entry(3, false); - } else { + grid_slot_page.menu.enable_entry(1, true); grid_slot_page.menu.enable_entry(2, false); - grid_slot_page.menu.enable_entry(3, true); + } else { + grid_slot_page.menu.enable_entry(1, false); + grid_slot_page.menu.enable_entry(2, true); } show_slot_menu = true; grid_slot_page.init(); + grid_slot_page.gen_menu_row_names(); return true; } @@ -1072,11 +1128,11 @@ bool GridPage::handleEvent(gui_event_t *event) { (EVENT_PRESSED(event, Buttons.BUTTON4) && BUTTON_DOWN(Buttons.BUTTON1))) { system: system_page.isSetup = false; - GUI.pushPage(&system_page); + mcl.pushPage(SYSTEM_PAGE); return true; } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } diff --git a/avr/cores/megacommand/MCL/GridPage.h b/avr/cores/megacommand/MCL/GridPage.h index 3ebefdeeb..aa445d510 100644 --- a/avr/cores/megacommand/MCL/GridPage.h +++ b/avr/cores/megacommand/MCL/GridPage.h @@ -4,7 +4,6 @@ #define GRIDPAGE_H__ #include "GUI.h" -#include "GridEncoder.h" #include "GridRowHeader.h" #define MAX_VISIBLE_ROWS 4 @@ -25,6 +24,7 @@ class GridPage : public LightPage { uint8_t row = 0; uint8_t cur_col = 0; uint8_t cur_row = 0; + uint8_t old_col = 0; uint8_t display_name = 0; uint8_t bank = 0; @@ -52,7 +52,7 @@ class GridPage : public LightPage { uint8_t row_scan = 0; uint64_t row_states[2]; - LightPage *last_page = nullptr; + PageIndex last_page = NULL_PAGE; uint8_t bank_popup = 0; uint16_t bank_popup_lastclock; @@ -86,9 +86,9 @@ class GridPage : public LightPage { void cleanup(); void init(); void prepare(); - void swap_grids(); + bool swap_grids(); void apply_slot_changes(bool ignore_undo = false, bool ignore_func = false); - + void load_old_col(); void close_bank_popup(); void loop(); diff --git a/avr/cores/megacommand/MCL/GridPages.cpp b/avr/cores/megacommand/MCL/GridPages.cpp index 4ec69ac45..20e96b7a2 100644 --- a/avr/cores/megacommand/MCL/GridPages.cpp +++ b/avr/cores/megacommand/MCL/GridPages.cpp @@ -3,7 +3,7 @@ MCLEncoder param1(GRID_WIDTH - 1, 0, 1); MCLEncoder param2(GRID_LENGTH - 1, 0 , 1); -MCLEncoder param3(GRID_WIDTH, 1, ENCODER_RES_GRID); +MCLEncoder param3(GRID_WIDTH + 1, 0, ENCODER_RES_GRID); MCLEncoder param4(6, 1, ENCODER_RES_GRID); GridPage grid_page(¶m1, ¶m2, ¶m3, ¶m4); diff --git a/avr/cores/megacommand/MCL/GridPages.h b/avr/cores/megacommand/MCL/GridPages.h index 108c1ffb3..f2ceb1d34 100644 --- a/avr/cores/megacommand/MCL/GridPages.h +++ b/avr/cores/megacommand/MCL/GridPages.h @@ -7,7 +7,6 @@ #define ENCODER_RES_GRID 1 #define ENCODER_RES_PAT 2 -#include "GridEncoder.h" #include "GridPage.h" #include "MCLEncoder.h" diff --git a/avr/cores/megacommand/MCL/GridRowHeader.cpp b/avr/cores/megacommand/MCL/GridRowHeader.cpp index ae6935ec1..868e3087e 100644 --- a/avr/cores/megacommand/MCL/GridRowHeader.cpp +++ b/avr/cores/megacommand/MCL/GridRowHeader.cpp @@ -18,10 +18,13 @@ bool GridRowHeader::is_empty() { } void GridRowHeader::init() { + memset(this, 0, sizeof(GridRowHeader)); + /* active = false; for (uint8_t x = 0; x < GRID_WIDTH; x++) { track_type[x] = EMPTY_TRACK_TYPE; model[x] = 0; } + */ } diff --git a/avr/cores/megacommand/MCL/GridSavePage.cpp b/avr/cores/megacommand/MCL/GridSavePage.cpp index fe4fe0e65..c5313fcc4 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.cpp +++ b/avr/cores/megacommand/MCL/GridSavePage.cpp @@ -7,21 +7,21 @@ void GridSavePage::init() { trig_interface.send_md_leds(TRIGLED_OVERLAY); trig_interface.on(); grid_page.reload_slot_models = false; - MD.popup_text("SAVE SLOTS", true); + char str[] = "SAVE SLOTS"; + MD.popup_text(str, true); draw_popup(); } void GridSavePage::setup() {} void GridSavePage::draw_popup() { - char str[16]; - strcpy(str, "GROUP SAVE"); + char str[16] = "GROUP SAVE"; if (!show_track_type) { strcpy(str, "SAVE TO "); str[8] = 'X' + proj.get_grid(); } - mcl_gui.draw_popup(str, true, 28); + mcl_gui.draw_popup(str, true); } void GridSavePage::loop() {} @@ -34,17 +34,16 @@ void GridSavePage::display() { const uint64_t slide_mask = 0; const uint64_t mute_mask = 0; if (show_track_type) { - mcl_gui.draw_track_type_select(36, MCLGUI::s_menu_y + 12, - mcl_cfg.track_type_select); + mcl_gui.draw_track_type_select(mcl_cfg.track_type_select); } else { - mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 21, note_interface.notes_off | note_interface.notes_on ); + mcl_gui.draw_trigs(MCLGUI::s_menu_x + 4, MCLGUI::s_menu_y + 24, note_interface.notes_off | note_interface.notes_on ); oled_display.setFont(&Elektrothic); - oled_display.setCursor(MCLGUI::s_menu_x + 4, 22); + oled_display.setCursor(MCLGUI::s_menu_x + 4, 21); oled_display.print((char)(0x3A + proj.get_grid())); oled_display.setFont(&TomThumb); - mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4 + 9, MCLGUI::s_menu_y + 4, + mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + 4 + 9, MCLGUI::s_menu_y + 7, "MODE", "SAVE"); char step[4] = {'\0'}; @@ -55,25 +54,25 @@ void GridSavePage::display() { mcl_gui.put_value_at(step_count, step); // mcl_gui.draw_text_encoder(MCLGUI::s_menu_x + MCLGUI::s_menu_w - 26, - // MCLGUI::s_menu_y + 4, "STEP", step); + // MCLGUI::s_menu_y + 8, "STEP", step); oled_display.setFont(&TomThumb); // draw data flow in the center constexpr uint8_t data_x = 56; - oled_display.setCursor(data_x + 9, MCLGUI::s_menu_y + 12); - oled_display.print("SND"); - oled_display.setCursor(data_x + 9, MCLGUI::s_menu_y + 19); - oled_display.print("SEQ"); + oled_display.setCursor(data_x + 9, MCLGUI::s_menu_y + 15); + oled_display.print(F("SND")); + oled_display.setCursor(data_x + 9, MCLGUI::s_menu_y + 22); + oled_display.print(F("SEQ")); - oled_display.drawFastHLine(data_x + 13 + 9, MCLGUI::s_menu_y + 8, 2, WHITE); - oled_display.drawFastHLine(data_x + 13 + 9, MCLGUI::s_menu_y + 15, 2, + oled_display.drawFastHLine(data_x + 13 + 9, MCLGUI::s_menu_y + 11, 2, WHITE); + oled_display.drawFastHLine(data_x + 13 + 9, MCLGUI::s_menu_y + 18, 2, WHITE); - oled_display.drawFastVLine(data_x + 15 + 9, MCLGUI::s_menu_y + 8, 8, WHITE); - mcl_gui.draw_horizontal_arrow(data_x + 16 + 9, MCLGUI::s_menu_y + 12, 5); + oled_display.drawFastVLine(data_x + 15 + 9, MCLGUI::s_menu_y + 11, 8, WHITE); + mcl_gui.draw_horizontal_arrow(data_x + 16 + 9, MCLGUI::s_menu_y + 15, 5); - oled_display.setCursor(data_x + 24 + 9, MCLGUI::s_menu_y + 15); - oled_display.print("GRID"); + oled_display.setCursor(data_x + 24 + 9, MCLGUI::s_menu_y + 18); + oled_display.print(F("GRID")); } oled_display.display(); oled_display.setFont(oldfont); @@ -98,14 +97,15 @@ void GridSavePage::save() { } } - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); trig_interface.off(); mcl_actions.save_tracks(grid_page.getRow(), track_select_array, save_mode); } void GridSavePage::group_select() { show_track_type = true; - MD.popup_text("SAVE GROUPS", true); + char str[] = "SAVE GROUPS"; + MD.popup_text(str, true); MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); } @@ -114,40 +114,13 @@ bool GridSavePage::handleEvent(gui_event_t *event) { return true; } - if (note_interface.is_event(event)) { - uint8_t track = event->source - 128; - if (event->mask == EVENT_BUTTON_PRESSED) { - if (show_track_type) { - if (track < 4) { - TOGGLE_BIT16(mcl_cfg.track_type_select, track); - MD.set_trigleds(mcl_cfg.track_type_select, TRIGLED_EXCLUSIVE); - } - } else { - trig_interface.send_md_leds(TRIGLED_OVERLAY); - } - } else { - if (!show_track_type) { - trig_interface.send_md_leds(TRIGLED_OVERLAY); - if (note_interface.notes_all_off()) { - if (BUTTON_DOWN(Buttons.BUTTON2)) { - return true; - } else { - save(); - } - } - } - } - - return true; - } - if (EVENT_CMD(event)) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { default: { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return false; } case MDX_KEY_YES: { @@ -184,12 +157,12 @@ bool GridSavePage::handleEvent(gui_event_t *event) { track_select_array_from_type_select(track_select_array); oled_display.textbox("SAVE GROUPS", ""); - oled_display.display(); + //oled_display.display(); uint8_t save_mode = SAVE_SEQ; mcl_actions.save_tracks(grid_page.getRow(), track_select_array, save_mode); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } } diff --git a/avr/cores/megacommand/MCL/GridSavePage.h b/avr/cores/megacommand/MCL/GridSavePage.h index 53bfba145..3113a8745 100644 --- a/avr/cores/megacommand/MCL/GridSavePage.h +++ b/avr/cores/megacommand/MCL/GridSavePage.h @@ -15,6 +15,7 @@ class GridSavePage : public GridIOPage { bool handleEvent(gui_event_t *event); void group_select(); void loop(); + void action() { save(); } void display(); void init(); void setup(); diff --git a/avr/cores/megacommand/MCL/GridTask.cpp b/avr/cores/megacommand/MCL/GridTask.cpp index 7fd5ebcba..28f364986 100644 --- a/avr/cores/megacommand/MCL/GridTask.cpp +++ b/avr/cores/megacommand/MCL/GridTask.cpp @@ -6,26 +6,23 @@ void GridTask::setup(uint16_t _interval) { interval = _interval; } void GridTask::destroy() {} -void GridTask::gui_update() { - auto &active_track = mcl_seq.md_tracks[last_md_track]; - if (GUI.currentPage() == &seq_step_page && - IS_BIT_SET(MDSeqTrack::sync_cursor, last_md_track)) { - MD.sync_seqtrack(active_track.length, active_track.speed, - active_track.length - 1); - } +void GridTask::row_update() { grid_page.set_active_row(last_active_row); // send led update MD.draw_pattern_idx(last_active_row, next_active_row, chain_behaviour); } -void GridTask::sync_cursor() { - if (MDSeqTrack::sync_cursor) { +void GridTask::gui_update() { + if (MDSeqTrack::gui_update) { if (MidiClock.state == 2) { if (last_active_row < GRID_LENGTH) { - gui_update(); - MD.setKitName(kit_names[0]); + if (mcl.currentPage() == SEQ_STEP_PAGE && IS_BIT_SET16(MDSeqTrack::gui_update,last_md_track)) { + auto active_track = mcl_seq.md_tracks[last_md_track]; + MD.sync_seqtrack(active_track.length, active_track.speed, active_track.length - 1); + } + row_update(); } } - MDSeqTrack::sync_cursor = 0; + MDSeqTrack::gui_update = 0; } } @@ -34,15 +31,18 @@ void GridTask::run() { // A4Track *a4_track = (A4Track *)&temp_track; // ExtTrack *ext_track = (ExtTrack *)&temp_track; // MD GUI update. + + perf_page.encoder_check(); + trig_interface.check_key_throttle(); + if (stop_hard_callback) { - mcl_actions_callbacks.StopHardCallback(); - stop_hard_callback = false; - load_queue.init(); - return; - } + mcl_actions_callbacks.StopHardCallback(); + stop_hard_callback = false; + load_queue.init(); + return; + } - sync_cursor(); - GridTask::transition_handler(); + gui_update(); if (!load_queue.is_empty()) { uint8_t mode; @@ -55,16 +55,19 @@ void GridTask::run() { if (row_select_array[n] < 128) { track_select[n] = 1; } - DEBUG_PRINT(n); DEBUG_PRINT(" "); DEBUG_PRINT(track_select[n]); DEBUG_PRINT(" "); DEBUG_PRINTLN(row_select_array[n]); + DEBUG_PRINT(n); + DEBUG_PRINT(" "); + DEBUG_PRINT(track_select[n]); + DEBUG_PRINT(" "); + DEBUG_PRINTLN(row_select_array[n]); } mcl_actions.write_original = 1; mcl_actions.load_tracks(255, track_select, row_select_array, mode); } - + GridTask::transition_handler(); } -void GridTask::transition_handler() { - +void GridTask::update_transition_details() { MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), midi_active_peering.get_device(UART2_PORT), @@ -74,6 +77,28 @@ void GridTask::transition_handler() { devs[1]->asElektronDevice(), }; + GridRowHeader row_header; + proj.read_grid_row_header(&row_header, next_active_row); + uint8_t dev_idx = 0; + + uint8_t len = elektron_devs[0]->sysex_protocol.kitname_length; + + if (row_header.active) { + memcpy(kit_names[dev_idx], row_header.name, len); + m_toupper(kit_names[dev_idx]); + kit_names[dev_idx][len - 1] = '\0'; + } else { + strcpy(kit_names[dev_idx], "NEW_KIT"); + } +} + +void GridTask::transition_handler() { + + MidiDevice *devs[2] = { + midi_active_peering.get_device(UART1_PORT), + midi_active_peering.get_device(UART2_PORT), + }; + bool send_device[2] = {0}; uint8_t slots_changed[NUM_SLOTS]; @@ -84,16 +109,17 @@ void GridTask::transition_handler() { uint8_t div32th_margin = 6; - GUI.removeTask(&grid_task); + // 240ms headroom = 0.240 * (MidiClock.get_tempo()* 0.133333333333 + // = 0.032 * MidiClock.get_tempo() + // while (MidiClock.clock_less_than( - MidiClock.div32th_counter + 0.240 * (MidiClock.get_tempo()* 0.133333333333f), + MidiClock.div32th_counter + 0.032 * MidiClock.get_tempo(), (uint32_t)mcl_actions.next_transition * 2) <= 0) { - float div32th_per_second = MidiClock.get_tempo() * 0.133333333333f; - float div32th_time = 1.0 / div32th_per_second; - + float div32th_per_second = MidiClock.get_tempo() * 0.133333333333f; + float div32th_time = 1.0 / div32th_per_second; if (MidiClock.state != 2 || mcl_actions.next_transition == (uint16_t)-1) { break; @@ -103,29 +129,32 @@ void GridTask::transition_handler() { DEBUG_PRINTLN(mcl_actions.next_transition); DEBUG_PRINTLN((int)SP); - uint8_t track_idx, dev_idx; uint8_t row = 255; - + uint8_t last_slot = 255; for (uint8_t n = 0; n < NUM_SLOTS; n++) { slots_changed[n] = 255; DEBUG_PRINTLN(n); - DEBUG_PRINT(mcl_actions.next_transition); DEBUG_PRINT(" "); DEBUG_PRINTLN(mcl_actions.next_transitions[n]); + DEBUG_PRINT(mcl_actions.next_transition); + DEBUG_PRINT(" "); + DEBUG_PRINTLN(mcl_actions.next_transitions[n]); if ((mcl_actions.links[n].loops == 0) || - (grid_page.active_slots[n] == SLOT_DISABLED) || (mcl_actions.next_transition != mcl_actions.next_transitions[n])) + (grid_page.active_slots[n] == SLOT_DISABLED) || + (mcl_actions.next_transition != mcl_actions.next_transitions[n])) continue; - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(n); + uint8_t track_idx = mcl_actions.get_track_idx(n); + uint8_t device_idx = gdt->device_idx; if (gdt == nullptr) { continue; } if (link_load(n, track_idx, slots_changed, track_select_array, gdt)) { - send_device[dev_idx] = true; + send_device[device_idx] = true; } if (row == 255) { @@ -133,6 +162,12 @@ void GridTask::transition_handler() { } } + if (send_device[0]) { + //Send kitName before tracks are cache-loaded in MD. + //This allows the kitName to be stored in the undokit. + update_transition_details(); + } + DEBUG_PRINTLN(F("sending tracks")); bool wait; @@ -150,10 +185,11 @@ void GridTask::transition_handler() { for (uint8_t n = 0; n < NUM_SLOTS; n++) { if (slots_changed[n] == 255) continue; + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(n); + uint8_t track_idx = mcl_actions.get_track_idx(n); + uint8_t device_idx = gdt->device_idx; - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(n, &track_idx, &dev_idx); - if ((gdt == nullptr) || (dev_idx != c)) + if (gdt == nullptr || (device_idx != c)) continue; // Wait on first track of each device; @@ -164,7 +200,7 @@ void GridTask::transition_handler() { mcl_actions.div192th_total_latency - 1; mcl_actions.div192th_total_latency -= - mcl_actions.dev_latency[dev_idx].latency; + mcl_actions.dev_latency[device_idx].latency; uint32_t diff; @@ -172,16 +208,16 @@ void GridTask::transition_handler() { MidiClock.div192th_counter, go_step)) != 0) && (MidiClock.div192th_counter < go_step) && (MidiClock.state == 2)) { - MidiUartParent::handle_midi_lock = 1; - handleIncomingMidi(); - MidiUartParent::handle_midi_lock = 0; + MidiUartParent::handle_midi_lock = 1; + handleIncomingMidi(); + MidiUartParent::handle_midi_lock = 0; if ((float)diff > (tempo * 0.8f) * 0.08) { - GUI.loop(); + GUI.loop(); } } } wait = false; - if (transition_load(n, track_idx, dev_idx, gdt)) { + if (transition_load(n, track_idx, gdt)) { grid_page.active_slots[n] = slots_changed[n]; } } @@ -200,11 +236,10 @@ void GridTask::transition_handler() { DEBUG_PRINTLN("time"); DEBUG_PRINTLN(t); + // Once tracks are cached, we can calculate their next transition - uint8_t last_slot = 255; for (uint8_t n = 0; n < NUM_SLOTS; n++) { - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(n); if (gdt == nullptr) { continue; @@ -216,37 +251,20 @@ void GridTask::transition_handler() { last_slot = n; ignore_chain_settings = false; auto_check = false; + } else if (mcl_actions.chains[n].mode == LOAD_AUTO && + mcl_actions.links[n].loops == 0) { + mcl_actions.next_transitions[n] = -1; + continue; } - mcl_actions.calc_next_slot_transition(n, ignore_chain_settings, auto_check); + mcl_actions.calc_next_slot_transition(n, ignore_chain_settings); } - if (last_slot != 255 && slots_changed[last_slot] < GRID_LENGTH) { - // GridDeviceTrack *gdt = - // mcl_actions.get_grid_dev_track(last_slot, &track_idx, &dev_idx); last_active_row = slots_changed[last_slot]; next_active_row = mcl_actions.links[last_slot].row; chain_behaviour = mcl_actions.chains[last_slot].mode > 1; - - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(last_slot, &track_idx, &dev_idx); - - GridRowHeader row_header; - proj.read_grid_row_header(&row_header, last_active_row); - dev_idx = 0; - - if (elektron_devs[dev_idx]) { - uint8_t len = elektron_devs[dev_idx]->sysex_protocol.kitname_length; - - if (row_header.active) { - memcpy(kit_names[dev_idx], row_header.name, len); - kit_names[dev_idx][len - 1] = '\0'; - } else { - strcpy(kit_names[dev_idx], "NEW_KIT"); - } - } } - sync_cursor(); + gui_update(); mcl_actions.calc_next_transition(); mcl_actions.calc_latency(); } @@ -263,23 +281,16 @@ bool GridTask::link_load(uint8_t n, uint8_t track_idx, uint8_t *slots_changed, } slots_changed[n] = mcl_actions.links[n].row; track_select_array[n] = 1; - memcpy(&mcl_actions.links[n], &pmem_track->link, sizeof(GridLink)); + + pmem_track->link.store_in_mem(n, &(mcl_actions.links[0])); if (pmem_track->active) { return true; } return false; } -bool GridTask::transition_load(uint8_t n, uint8_t track_idx, uint8_t dev_idx, - GridDeviceTrack *gdt) { - MidiDevice *devs[2] = { - midi_active_peering.get_device(UART1_PORT), - midi_active_peering.get_device(UART2_PORT), - }; - ElektronDevice *elektron_devs[2] = { - devs[0]->asElektronDevice(), - devs[1]->asElektronDevice(), - }; +bool GridTask::transition_load(uint8_t n, uint8_t track_idx, + GridDeviceTrack *gdt) { EmptyTrack empty_track; auto *pmem_track = diff --git a/avr/cores/megacommand/MCL/GridTask.h b/avr/cores/megacommand/MCL/GridTask.h index a4bad79ca..d28d9858c 100644 --- a/avr/cores/megacommand/MCL/GridTask.h +++ b/avr/cores/megacommand/MCL/GridTask.h @@ -1,7 +1,7 @@ #ifndef GRID_TASK_H__ #define GRID_TASK_H__ -#include "MCL.h" +#include "mcl.h" #include "Task.h" #include "Elektron.h" #include "GridChain.h" @@ -12,22 +12,30 @@ class LoadQueue { uint8_t modes[NUM_LINKS]; uint8_t rd; uint8_t wr; + bool full; void init() { rd = 0; wr = 0; + bool full = false; } void put(uint8_t mode, uint8_t *row_select) { + if (full) { return; } memcpy(row_selects[wr],row_select,NUM_SLOTS); modes[wr++] = mode; if (wr == NUM_LINKS) { wr = 0; } + if (wr == rd) { + full = true; + } } void put(uint8_t mode, uint8_t row, uint8_t *track_select_array) { + if (full) { return; } + for (uint8_t n = 0; n < NUM_SLOTS; n++) { row_selects[wr][n] = 255; if (track_select_array[n]) { row_selects[wr][n] = row; } @@ -36,6 +44,9 @@ class LoadQueue { if (wr == NUM_LINKS) { wr = 0; } + if (wr == rd) { + full = true; + } } void get(uint8_t *mode, uint8_t *row_select) { @@ -44,11 +55,11 @@ class LoadQueue { if (rd == NUM_LINKS) { rd = 0; } + full = false; } bool is_empty() { - bool ret = (rd == wr); - return ret; + return !full && (rd == wr); } }; @@ -82,7 +93,6 @@ class GridTask : public Task { virtual void run(); virtual void destroy(); - void sync_cursor(); void init() { reset_midi_states(); load_queue.init(); @@ -95,12 +105,13 @@ class GridTask : public Task { //midi_row_select = 255; midi_load = false; } - + void row_update(); void gui_update(); + void update_transition_details(); void transition_handler(); bool link_load(uint8_t n, uint8_t track_idx, uint8_t *slots_changed, uint8_t *track_select_array, GridDeviceTrack *gdt); - bool transition_load(uint8_t n, uint8_t track_idx, uint8_t dev_idx, GridDeviceTrack *gdt); + bool transition_load(uint8_t n, uint8_t track_idx, GridDeviceTrack *gdt); bool transition_send(uint8_t n, uint8_t track_idx, uint8_t dev_idx, GridDeviceTrack *gdt); /* @} */ diff --git a/avr/cores/megacommand/MCL/GridTrack.cpp b/avr/cores/megacommand/MCL/GridTrack.cpp index 5247f3c28..c00ffce17 100644 --- a/avr/cores/megacommand/MCL/GridTrack.cpp +++ b/avr/cores/megacommand/MCL/GridTrack.cpp @@ -43,7 +43,7 @@ bool GridTrack::load_from_grid_512(uint8_t column, uint16_t row, Grid *grid) { ::new (this) GridTrack; this->active = tmp; - if ((active == EMPTY_TRACK_TYPE) || (active == 255)) { + if ((active == 255)) { init(); } @@ -61,7 +61,7 @@ bool GridTrack::load_from_grid(uint8_t column, uint16_t row) { ::new (this) GridTrack; this->active = tmp; - if ((active == EMPTY_TRACK_TYPE) || (active == 255)) { + if ((active == 255)) { init(); } diff --git a/avr/cores/megacommand/MCL/GridTrack.h b/avr/cores/megacommand/MCL/GridTrack.h index a05f7d402..a37515258 100644 --- a/avr/cores/megacommand/MCL/GridTrack.h +++ b/avr/cores/megacommand/MCL/GridTrack.h @@ -22,6 +22,8 @@ #define EXT_ARP_TRACK_TYPE 14 #define GRIDCHAIN_TRACK_TYPE 15 +#define PERF_TRACK_TYPE 16 + #define NULL_TRACK_TYPE 128 #define EMPTY_TRACK_TYPE 0 @@ -78,13 +80,17 @@ class GridTrack { void init() { link.length = 16; link.speed = SEQ_SPEED_1X; - } + link.loops = 0; + } /* Load track from Grid in to sequencer, place in payload to be transmitted to device*/ void load_link_data(SeqTrack *seq_track); virtual void init(uint8_t tracknumber, SeqTrack *seq_track) {} + virtual void load_immediate(uint8_t tracknumber, SeqTrack *seq_track) {} + virtual void load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) { load_immediate(tracknumber, seq_track); } + virtual bool transition_cache(uint8_t tracknumber, uint8_t slotnumber) { return false; } virtual void transition_send(uint8_t tracknumber, uint8_t slotnumber) {} virtual void transition_load(uint8_t tracknumber, SeqTrack* seq_track, uint8_t slotnumber); @@ -96,7 +102,7 @@ class GridTrack { virtual uint16_t get_track_size() { return sizeof(GridTrack); } virtual uint16_t get_region_size() { return get_track_size(); } - virtual uint32_t get_region() { return BANK1_MD_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_MD_TRACKS_START; } bool is_external() { return get_region() != BANK1_MD_TRACKS_START; } /* Calibrate data members on slot copy */ virtual void on_copy(int16_t s_col, int16_t d_col, bool destination_same) { } diff --git a/avr/cores/megacommand/MCL/LFO.cpp b/avr/cores/megacommand/MCL/LFO.cpp index c45cd6b57..930091634 100644 --- a/avr/cores/megacommand/MCL/LFO.cpp +++ b/avr/cores/megacommand/MCL/LFO.cpp @@ -2,7 +2,7 @@ #include "LFO.h" #include "math.h" -#define DIV_1_127 (1.00 / 127.0) +#define DIV_1_127 (1.00f / 127.0f) // Exponential Rise Formua: // y = M * (1-e^(-x/a)); // M = Maximum @@ -34,9 +34,9 @@ uint8_t ExpLFO::get_sample(uint8_t sample_number) { uint8_t IExpLFO::get_sample(uint8_t sample_number) { - uint8_t y = amplitude - (uint8_t)((float)amplitude * - powf(M_E, (float)-1 * (float)sample_number * - (float)time_constant)); + ExpLFO e; + e.amplitude = amplitude; + uint8_t y = amplitude - e.get_sample(sample_number); return y; } @@ -48,7 +48,9 @@ uint8_t RampLFO::get_sample(uint8_t sample_number) { } uint8_t IRampLFO::get_sample(uint8_t sample_number) { - uint8_t y = amplitude - ((float)amplitude / (float)(LFO_LENGTH)) * (sample_number); + RampLFO r; + r.amplitude = amplitude; + uint8_t y = amplitude - r.get_sample(sample_number); return y; } @@ -65,11 +67,11 @@ uint8_t TriLFO::get_sample(uint8_t sample_number) { } uint8_t SinLFO::get_sample(uint8_t sample_number) { - float sample_duration = (float)1.0 / (float)LFO_LENGTH; + float sample_duration = (float)1.0f / (float)LFO_LENGTH; - uint8_t y = (float)(amplitude / 2.0) * - sin(2.0 * PI * (float) sample_number * sample_duration - (0.5 * PI)) + - (float)(amplitude / 2.0); + uint8_t y = (float)(amplitude / 2.0f) * + (float) sin(2.0f * (float)M_PI * (float) sample_number * sample_duration - (0.5f * (float)M_PI)) + + (float)(amplitude / 2.0f); return y; } diff --git a/avr/cores/megacommand/MCL/LFO.h b/avr/cores/megacommand/MCL/LFO.h index 8fd31a627..c3a819553 100644 --- a/avr/cores/megacommand/MCL/LFO.h +++ b/avr/cores/megacommand/MCL/LFO.h @@ -3,7 +3,7 @@ #ifndef LFOOSC_H__ #define LFOOSC_H__ -#include "MCL.h" +#include "mcl.h" #include "math.h" #define EXP_LFO 1 @@ -19,7 +19,7 @@ class ExpLFO : public LFO { float time_constant; public: - ExpLFO(float time_constant_ = 40) { time_constant = 1.00 / time_constant_; } + ExpLFO(float time_constant_ = 40) { time_constant = 1.00f / time_constant_; } uint8_t get_sample(uint8_t sample_number); }; @@ -28,7 +28,7 @@ class IExpLFO : public LFO { float time_constant; public: - IExpLFO(float time_constant_ = 40) { time_constant = 1.00 / time_constant_; } + IExpLFO(float time_constant_ = 40) { time_constant = 1.00f / time_constant_; } uint8_t get_sample(uint8_t sample_number); }; diff --git a/avr/cores/megacommand/MCL/LFOPage.cpp b/avr/cores/megacommand/MCL/LFOPage.cpp index 9e8cce8fb..0e39ec9f1 100644 --- a/avr/cores/megacommand/MCL/LFOPage.cpp +++ b/avr/cores/megacommand/MCL/LFOPage.cpp @@ -6,41 +6,51 @@ #define INTERPOLATE #define DIV_1_127 .0079 +#define LFO_OFFSET 2 #define LFO_DESTINATION 1 #define LFO_SETTINGS 0 void LFOPage::setup() { // lfo_track = &mcl_seq.lfo_tracks[0]; - lfo_track->params[0].update_offset(); - lfo_track->params[1].update_offset(); - lfo_track->wav_table_state[0] = false; - lfo_track->wav_table_state[1] = false; DEBUG_PRINT_FN(); } void LFOPage::init() { - DEBUG_PRINT_FN(); - oled_display.clearDisplay(); - oled_display.setFont(); - update_encoders(); + PerfPageParent::init(); + MD.sync_seqtrack(lfo_track->length, lfo_track->speed, lfo_track->step_count); if (lfo_track->mode != LFO_MODE_FREE) { trig_interface.on(); } - // LFOPage not using base SeqPage init? - R.Clear(); - R.use_machine_param_names(); + } void LFOPage::cleanup() { + PerfPageParent::cleanup(); trig_interface.off(); oled_display.clearDisplay(); } -void LFOPage::update_encoders() { +void LFOPage::config_encoder_range(uint8_t i) { + + ((MCLEncoder *)encoders[i])->max = NUM_MD_TRACKS + 4 + 16; + + uint8_t dest = encoders[i]->cur - 1; + if (dest >= NUM_MD_TRACKS + 4) { + ((MCLEncoder *)encoders[i + 1])->max = 127; + } + else if (dest >= NUM_MD_TRACKS) { + ((MCLEncoder *)encoders[i + 1])->max = 7; + } + else { + ((MCLEncoder *)encoders[i + 1])->max = 23; + } +} + +void LFOPage::config_encoders() { if (page_mode == LFO_DESTINATION) { encoders[0]->cur = lfo_track->params[0].dest; ((MCLEncoder *)encoders[0])->max = NUM_MD_TRACKS + 4; @@ -51,19 +61,10 @@ void LFOPage::update_encoders() { encoders[3]->cur = lfo_track->params[1].param; ((MCLEncoder *)encoders[3])->max = 23; - if (encoders[0]->cur > NUM_MD_TRACKS) { - ((MCLEncoder *)encoders[1])->max = 7; - } else { - ((MCLEncoder *)encoders[1])->max = 23; - } - - if (encoders[2]->cur > NUM_MD_TRACKS) { - ((MCLEncoder *)encoders[3])->max = 7; - } else { - ((MCLEncoder *)encoders[3])->max = 23; - } + config_encoder_range(0); + config_encoder_range(2); } - if (page_mode == LFO_SETTINGS) { + else if (page_mode == LFO_SETTINGS) { encoders[0]->cur = waveform; ((MCLEncoder *)encoders[0])->max = 5; @@ -76,69 +77,42 @@ void LFOPage::update_encoders() { encoders[3]->cur = lfo_track->params[1].depth; ((MCLEncoder *)encoders[3])->max = 127; } - // loop(); + else if (page_mode == LFO_OFFSET) { + encoders[2]->cur = lfo_track->params[0].offset; + ((MCLEncoder *)encoders[2])->max = 127; - for (uint8_t i = 0; i < GUI_NUM_ENCODERS; i++) { - encoders[i]->old = encoders[i]->cur; - ((LightPage *)this)->encoders_used_clock[i] = - slowclock - SHOW_VALUE_TIMEOUT - 1; + encoders[3]->cur = lfo_track->params[1].offset; + ((MCLEncoder *)encoders[3])->max = 127; } + + // loop(); + + init_encoders_used_clock(); + } void LFOPage::loop() { if (page_mode == LFO_DESTINATION) { + config_encoder_range(0); + config_encoder_range(2); if (encoders[0]->hasChanged()) { - USE_LOCK(); - SET_LOCK(); - lfo_track->params[0].reset_param_offset(); lfo_track->params[0].dest = encoders[0]->cur; - lfo_track->params[0].update_offset(); - CLEAR_LOCK(); - if (encoders[0]->cur > NUM_MD_TRACKS) { - ((MCLEncoder *)encoders[1])->max = 7; - } else { - ((MCLEncoder *)encoders[1])->max = 23; - } } if (encoders[1]->hasChanged()) { - USE_LOCK(); - SET_LOCK(); - lfo_track->params[0].reset_param_offset(); lfo_track->params[0].param = encoders[1]->cur; - // lfo_track->params[0].offset = lfo_track->params[0].get_param_offset( - // encoders[0]->cur, encoders[1]->cur); - lfo_track->params[0].update_offset(); - CLEAR_LOCK(); } if (encoders[2]->hasChanged()) { - USE_LOCK(); - SET_LOCK(); - lfo_track->params[1].reset_param_offset(); lfo_track->params[1].dest = encoders[2]->cur; - lfo_track->params[1].update_offset(); - CLEAR_LOCK(); - if (encoders[2]->cur > NUM_MD_TRACKS) { - ((MCLEncoder *)encoders[3])->max = 7; - } else { - ((MCLEncoder *)encoders[3])->max = 23; - } } if (encoders[3]->hasChanged()) { - USE_LOCK(); - SET_LOCK(); - lfo_track->params[1].reset_param_offset(); lfo_track->params[1].param = encoders[3]->cur; - // lfo_track->params[1].offset = lfo_track->params[1].get_param_offset( - // encoders[2]->cur, encoders[3]->cur); - lfo_track->params[1].update_offset(); - CLEAR_LOCK(); } } // wav_tables need to be recalculated when depth or waveform changes. - if (page_mode == LFO_SETTINGS) { + else if (page_mode == LFO_SETTINGS) { if (encoders[0]->hasChanged()) { lfo_track->set_wav_type(encoders[0]->cur); } @@ -156,57 +130,22 @@ void LFOPage::loop() { } } - if (!lfo_track->wav_table_up_to_date(0)) { - lfo_track->load_wav_table(0); - } - - if (!lfo_track->wav_table_up_to_date(1)) { - lfo_track->load_wav_table(1); - } -} - -void LFOPage::draw_param(uint8_t knob, uint8_t dest, uint8_t param) { - - char myName[4] = "-- "; - - const char* modelname = NULL; - if (dest != 0) { - if (dest < 17) { - modelname = model_param_name(MD.kit.get_model(dest - 1), param); - } else { - modelname = fx_param_name(MD_FX_ECHO + dest - 17, param); + else if (page_mode == LFO_OFFSET) { + if (encoders[2]->hasChanged()) { + if (lfo_track->params[0].dest > NUM_MD_TRACKS + 4) { + lfo_track->params[0].offset = encoders[2]->cur; + } + else { encoders[2]->cur = encoders[2]->old; } } - if (modelname != NULL) { - strncpy(myName, modelname, 4); + + if (encoders[3]->hasChanged()) { + if (lfo_track->params[1].dest > NUM_MD_TRACKS + 4) { + lfo_track->params[1].offset = encoders[3]->cur; + } + else { encoders[3]->cur = encoders[3]->old; } } } - draw_knob(knob, "PAR", myName); -} -void LFOPage::draw_dest(uint8_t knob, uint8_t value) { - char K[4]; - switch (value) { - case 0: - strcpy(K, "--"); - break; - case 17: - strcpy(K, "ECH"); - break; - case 18: - strcpy(K, "REV"); - break; - case 19: - strcpy(K, "EQ"); - break; - case 20: - strcpy(K, "DYN"); - break; - default: - // K[0] = 'T'; - mcl_gui.put_value_at(value, K); - break; - } - draw_knob(knob, "DEST", K); } void LFOPage::display() { @@ -221,46 +160,56 @@ void LFOPage::display() { uint8_t y = 8; uint8_t lfo_height = 7; uint8_t width = 13; - LFOSeqTrack temp_track; // mcl_gui.draw_vertical_dashline(x, 0, knob_y); SeqPage::draw_knob_frame(); + const char *info1; + const char *info2; + if (page_mode == LFO_DESTINATION) { draw_dest(0, encoders[0]->cur); draw_param(1, encoders[0]->cur, encoders[1]->cur); draw_dest(2, encoders[2]->cur); draw_param(3, encoders[2]->cur, encoders[3]->cur); + info2 = "LFO>DST"; } - if (page_mode == LFO_SETTINGS) { - temp_track.set_wav_type(lfo_track->wav_type); - temp_track.set_depth(0, lfo_height); - temp_track.load_wav_table(0); + else if (page_mode == LFO_SETTINGS) { uint8_t inc = LFO_LENGTH / width; for (uint8_t n = 0; n < LFO_LENGTH; n += inc, x++) { if (n < LFO_LENGTH) { - oled_display.drawPixel(x, y + lfo_height - temp_track.wav_table[0][n], - WHITE); + int16_t out = 0; + + switch (lfo_track->wav_type) { + case IRAMP_WAV: + case EXP_WAV: + out = (int16_t)128 - lfo_track->wav_tables[lfo_track->wav_type - 2][n]; + break; + default: + out = lfo_track->wav_tables[lfo_track->wav_type][n]; + break; + } + uint8_t sample = ((int16_t) out * (int16_t) lfo_height) / 128; + + oled_display.drawPixel(x, y + lfo_height - sample, WHITE); } } - x = mcl_gui.knob_x0 + 2; oled_display.setCursor(x + 5, 6); - oled_display.print("WAV"); + oled_display.print(F("WAV")); draw_knob(1, encoders[1], "SPD"); draw_knob(2, encoders[2], "DEP1"); draw_knob(3, encoders[3], "DEP2"); - } - oled_display.setFont(&TomThumb); - const char *info1; - const char *info2; - - if (page_mode) { - info2 = "LFO>DST"; - } else { info2 = "LFO>MOD"; } + else { //if (page_mode == LFO_OFFSET) { + draw_knob(2, encoders[2], "OFS1"); + draw_knob(3, encoders[3], "OFS2"); + info2 = "LFO>OFS"; + } + + oled_display.setFont(&TomThumb); const uint64_t slide_mask = 0; const uint64_t mute_mask = 0; @@ -293,42 +242,37 @@ void LFOPage::display() { oled_display.setFont(oldfont); } -void LFOPage::onControlChangeCallback_Midi(uint8_t *msg) { - uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); - uint8_t param = msg[1]; - uint8_t value = msg[2]; - uint8_t track; - uint8_t track_param; - // If external keyboard controlling MD pitch, send parameter updates - // to all polyphonic tracks - uint8_t param_true = 0; - - MD.parseCC(channel, param, &track, &track_param); - if (track > 15) { return; } -} - -void LFOPage::setup_callbacks() { - if (midi_state) { - return; +void LFOPage::learn_param(uint8_t track, uint8_t param, uint8_t value) { + bool reconfig = false; + if (mcl.currentPage() == LFO_PAGE) { + if (page_mode == LFO_DESTINATION) { + if (encoders[0]->cur == 0 && encoders[1]->cur > 0) { + lfo_track->params[0].dest = track + 1; + lfo_track->params[0].param = param; + reconfig = true; + } + if (encoders[2]->cur == 0 && encoders[3]->cur > 0) { + lfo_track->params[1].dest = track + 1; + lfo_track->params[1].param = param; + reconfig = true; + } } - Midi.addOnControlChangeCallback( - this, (midi_callback_ptr_t)&LFOPage::onControlChangeCallback_Midi); - - midi_state = true; -} - -void LFOPage::remove_callbacks() { - if (!midi_state) { - return; } - - Midi.removeOnControlChangeCallback( - this, (midi_callback_ptr_t)&LFOPage::onControlChangeCallback_Midi); - - midi_state = false; + if (lfo_track->params[0].dest - 1 == track && lfo_track->params[0].param == param) { + lfo_track->params[0].offset = value; + reconfig = true; + } + if (lfo_track->params[1].dest - 1 == track && lfo_track->params[1].param == param) { + lfo_track->params[1].offset = value; + reconfig = true; + } + if (reconfig) { config_encoders(); } } + bool LFOPage::handleEvent(gui_event_t *event) { + if (PerfPageParent::handleEvent(event)) { return true; } + if (note_interface.is_event(event)) { uint8_t mask = event->mask; uint8_t port = event->port; @@ -339,7 +283,7 @@ bool LFOPage::handleEvent(gui_event_t *event) { uint8_t step = track + (page_select * 16); if (event->mask == EVENT_BUTTON_PRESSED) { if (device == &Analog4) { - // GUI.setPage(&seq_extstep_page) + // mcl.setPage(SEQ_EXTSTEP_PAGE) return true; } if (!IS_BIT_SET64(lfo_track->pattern_mask, step)) { @@ -354,19 +298,36 @@ bool LFOPage::handleEvent(gui_event_t *event) { } } } - if (event->mask == EVENT_BUTTON_RELEASED) { - return true; - } - /* if (EVENT_PRESSED(event, Buttons.ENCODER1) || - EVENT_PRESSED(event, Buttons.ENCODER2) || - EVENT_PRESSED(event, Buttons.ENCODER3) || - EVENT_PRESSED(event, Buttons.ENCODER4)) { - GUI.setPage(&grid_page); + if (EVENT_CMD(event)) { + uint8_t key = event->source - 64; + if (event->mask == EVENT_BUTTON_PRESSED) { + switch (key) { + case MDX_KEY_YES: { + lfo_track->enable = !(lfo_track->enable); + break; + } + case MDX_KEY_UP: { + if (page_mode < LFO_OFFSET) { + page_mode++; + config_encoders(); + } + return true; + } + case MDX_KEY_DOWN: { + if (page_mode > 0) { + page_mode--; + config_encoders(); + } + return true; + } + } } - */ + } + if (EVENT_PRESSED(event, Buttons.BUTTON4)) { - page_mode = !(page_mode); - update_encoders(); + page_mode++; + if (page_mode > LFO_OFFSET) { page_mode = 0; } + config_encoders(); } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { @@ -383,15 +344,7 @@ bool LFOPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON1)) { - if (lfo_track->enable) { - lfo_track->reset_params_offset(); - } lfo_track->enable = !(lfo_track->enable); } - if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); - return true; - } - return false; } diff --git a/avr/cores/megacommand/MCL/LFOPage.h b/avr/cores/megacommand/MCL/LFOPage.h index 0dfbbf91b..f026005a9 100644 --- a/avr/cores/megacommand/MCL/LFOPage.h +++ b/avr/cores/megacommand/MCL/LFOPage.h @@ -7,6 +7,7 @@ #include "MCLEncoder.h" #include "LFOSeqTrack.h" #include "SeqPage.h" +#include "PerfPageParent.h" #define NUM_LFO_PAGES 2 @@ -16,8 +17,9 @@ #define IEXP_WAV 3 #define IRAMP_WAV 4 #define EXP_WAV 5 -// -class LFOPage : public SeqPage, MidiCallback { + + +class LFOPage : public SeqPage, PerfPageParent { public: LFOPage(LFOSeqTrack *lfo_track_, Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) @@ -28,7 +30,7 @@ class LFOPage : public SeqPage, MidiCallback { bool handleEvent(gui_event_t *event); bool midi_state = false; - bool page_mode; + uint8_t page_mode; uint8_t page_id; LFOSeqTrack *lfo_track; @@ -36,20 +38,16 @@ class LFOPage : public SeqPage, MidiCallback { uint8_t depth; uint8_t depth2; - void draw_dest(uint8_t knob, uint8_t value); - void draw_param(uint8_t knob, uint8_t dest, uint8_t param); void display(); void setup(); // void draw_pattern_mask(); void init(); void loop(); void cleanup(); - void update_encoders(); - - void setup_callbacks(); - void remove_callbacks(); + virtual void config_encoders(); - void onControlChangeCallback_Midi(uint8_t *msg); + void config_encoder_range(uint8_t i); + void learn_param(uint8_t track, uint8_t param, uint8_t value); }; extern MCLEncoder lfo_page_param1; diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp index 25cc85046..2ac0d4594 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.cpp @@ -1,121 +1,128 @@ #include "MCL_impl.h" -void LFOSeqTrack::load_wav_table(uint8_t table) { +static uint8_t LFOSeqTrack::wav_tables[4][WAV_LENGTH]; + +void LFOSeqTrack::load_tables() { SinLFO sin_lfo; TriLFO tri_lfo; RampLFO ramp_lfo; - IRampLFO iramp_lfo; - ExpLFO exp_lfo; IExpLFO iexp_lfo; LFO *lfo; + + + for (uint8_t n = 0; n < 4; n++) { + switch (n) { + case SIN_WAV: + lfo = (LFO *)&sin_lfo; + break; + case TRI_WAV: + lfo = (LFO *)&tri_lfo; + break; + case RAMP_WAV: + lfo = (LFO *)&ramp_lfo; + break; + case IEXP_WAV: + lfo = (LFO *)&iexp_lfo; + break; + } + lfo->amplitude = 128; + for (uint8_t i = 0; i < LFO_LENGTH; i++) { + wav_tables[n][i] = lfo->get_sample(i); + } + } +} + +int16_t LFOSeqTrack::get_sample(uint8_t n) { + + int16_t out = 0; switch (wav_type) { - case SIN_WAV: - lfo = (LFO *)&sin_lfo; - offset_behaviour = LFO_OFFSET_CENTRE; - break; - case TRI_WAV: - lfo = (LFO *)&tri_lfo; - offset_behaviour = LFO_OFFSET_CENTRE; - break; - case IRAMP_WAV: - lfo = (LFO *)&iramp_lfo; - offset_behaviour = LFO_OFFSET_MAX; + case IRAMP_WAV: + case EXP_WAV: + out = 128 - wav_tables[wav_type - 2][n]; break; - case RAMP_WAV: - lfo = (LFO *)&ramp_lfo; - offset_behaviour = LFO_OFFSET_MAX; - break; - case EXP_WAV: - lfo = (LFO *)&exp_lfo; - offset_behaviour = LFO_OFFSET_MAX; - break; - case IEXP_WAV: - lfo = (LFO *)&iexp_lfo; - offset_behaviour = LFO_OFFSET_MAX; + default: + out = wav_tables[wav_type][n]; break; } - lfo->amplitude = params[table].depth; - // ExpLFO exp_lfo(20); - for (uint8_t n = 0; n < LFO_LENGTH; n++) { - wav_table[table][n] = (float)lfo->get_sample(n); + + switch (wav_type) { + //OFFSET CENTRE + case SIN_WAV: + case TRI_WAV: + out -= 64; + break; + //OFFSET MAX + default: + out -= 128; + break; } - wav_table_state[table] = true; + return out; } -uint8_t LFOSeqTrack::get_wav_value(uint8_t sample_count, uint8_t param) { - int8_t offset = params[param].offset; - int8_t depth = params[param].depth; - int8_t sample = wav_table[param][sample_count]; - int16_t val; - - switch (offset_behaviour) { - case LFO_OFFSET_CENTRE: - val = offset + (sample - (depth / 2)); - if (val > 127) { - return 127; - } - if (val < 0) { - return 0; - } else { - return (uint8_t)val; - } - break; - case LFO_OFFSET_MAX: - // val = 127 - sample; - val = offset - depth + sample; - if (val > 127) { - return 127; - } - if (val < 0) { - return 0; - } else { - return (uint8_t)val; - } - break; - } - return offset; +uint8_t LFOSeqTrack::get_wav_value(uint8_t sample_count, uint8_t dest, uint8_t param) { + int8_t offset = get_param_offset(dest, params[param].param); + int16_t depth = params[param].depth; + + int16_t sample = ((get_sample(sample_count) * depth) / 128) + offset; + + if (sample > 127) { return 127; } + if (sample < 0) { return 0; } + + return (uint8_t) sample; } -void LFOSeqTrack::seq(MidiUartParent *uart_) { +void LFOSeqTrack::seq(MidiUartParent *uart_, MidiUartParent *uart2_) { MidiUartParent *uart_old = uart; uart = uart_; if ((MidiClock.mod12_counter == 0) && (mode != LFO_MODE_FREE) && - IS_BIT_SET64(pattern_mask, step_count)) { - sample_count = 0; - } + IS_BIT_SET64(pattern_mask, step_count)) { + sample_count = 0; + } if (enable) { for (uint8_t i = 0; i < NUM_LFO_PARAMS; i++) { - uint8_t wav_value = get_wav_value(sample_count, i); + if (params[i].dest == 0) { continue; } + uint8_t dest = params[i].dest - 1; + uint8_t wav_value = get_wav_value(sample_count, dest, i); if (last_wav_value[i] != wav_value) { - - if (params[i].dest > 0) { - // MD CC LFO - if (params[i].dest <= NUM_MD_TRACKS) { - MD.setTrackParam_inline(params[i].dest - 1, params[i].param, - wav_value, uart); - } - // MD FX LFO - else { - MD.sendFXParam(params[i].param, wav_value, - MD_FX_ECHO + params[i].dest - NUM_MD_TRACKS - 1, uart); - } - last_wav_value[i] = wav_value; + uint8_t param = params[i].param; + + if (dest >= NUM_MD_TRACKS + 4) { + uint8_t channel = dest - (NUM_MD_TRACKS + 4); + uart2_->sendCC(channel, param, wav_value); + } else if (dest >= NUM_MD_TRACKS) { + MD.sendFXParam(param, wav_value, MD_FX_ECHO + dest - NUM_MD_TRACKS, + uart); + } else { + MD.setTrackParam(dest, param, wav_value, uart); } + + last_wav_value[i] = wav_value; } } } + if (speed < 1) { + sample_count += 1; + } else { + sample_hold += 1; + if (sample_hold >= (speed - 1)) { + sample_hold = 0; + sample_count += 1; + } + } - if (speed == 0) { - sample_count += 2; + /* + if (speed < 8) { + sample_count += 8 - speed; } else { sample_hold += 1; - if (sample_hold >= speed - 1) { + if (sample_hold >= (speed - 8)) { sample_hold = 0; sample_count += 1; } } - if (sample_count > LFO_LENGTH) { + */ + if (sample_count >= LFO_LENGTH) { // Free running LFO should reset, oneshot should hold at last value. if (mode == LFO_MODE_ONE) { sample_count = LFO_LENGTH - 1; @@ -134,80 +141,17 @@ void LFOSeqTrack::seq(MidiUartParent *uart_) { uart = uart_old; } -void LFOSeqTrack::check_and_update_params_offset(uint8_t track, uint8_t dest, - uint8_t value) { - for (uint8_t n = 0; n < NUM_LFO_PARAMS; n++) { - if ((params[n].dest == track) && (params[n].param == dest)) { - wav_table_state[n] = false; - params[n].offset = value; - } - } -} - -void LFOSeqTrack::reset_params_offset() { - if (enable) { - for (uint8_t n = 0; n < NUM_LFO_PARAMS; n++) { - params[n].reset_param_offset(); - } - } -} - -void LFOSeqTrack::update_params_offset() { - for (uint8_t n = 0; n < NUM_LFO_PARAMS; n++) { - params[n].update_offset(); - } -} - -void LFOSeqTrack::update_kit_params() { - for (uint8_t n = 0; n < NUM_LFO_PARAMS; n++) { - params[n].update_kit(); - } -} - -void LFOSeqParam::update_kit() { - if (dest <= NUM_MD_TRACKS) { - MD.kit.params[dest - 1][param] = offset; - } else { - switch (dest - NUM_MD_TRACKS - 1) { - case MD_FX_ECHO - MD_FX_ECHO: - MD.kit.delay[param] = offset; - break; - case MD_FX_DYN - MD_FX_ECHO: - MD.kit.dynamics[param] = offset; - break; - case MD_FX_REV - MD_FX_ECHO: - MD.kit.reverb[param] = offset; - break; - case MD_FX_EQ - MD_FX_ECHO: - MD.kit.eq[param] = offset; - break; - } - } -} - -void LFOSeqParam::update_offset() { offset = get_param_offset(dest, param); } -void LFOSeqParam::reset_param_offset() { reset_param(dest, param, offset); } - -void LFOSeqParam::reset_param(uint8_t dest, uint8_t param, uint8_t value) { - if (dest <= NUM_MD_TRACKS) { - MD.setTrackParam(dest - 1, param, value); - } else { - MD.sendFXParam(param, value, MD_FX_ECHO + dest - NUM_MD_TRACKS - 1); - } -} - -uint8_t LFOSeqParam::get_param_offset(uint8_t dest, uint8_t param) { - if (dest <= NUM_MD_TRACKS) { - return MD.kit.params[dest - 1][param]; - } else { - switch (dest - NUM_MD_TRACKS - 1) { +uint8_t LFOSeqTrack::get_param_offset(uint8_t dest, uint8_t param) { + if (dest < NUM_MD_TRACKS) { + return MD.kit.params[dest][param]; + } else if (dest < NUM_MD_TRACKS + 4) { + switch (dest - NUM_MD_TRACKS) { case MD_FX_ECHO - MD_FX_ECHO: return MD.kit.delay[param]; break; case MD_FX_DYN - MD_FX_ECHO: return MD.kit.dynamics[param]; break; - case MD_FX_REV - MD_FX_ECHO: return MD.kit.reverb[param]; break; @@ -216,5 +160,9 @@ uint8_t LFOSeqParam::get_param_offset(uint8_t dest, uint8_t param) { break; } } + else { + //MIDI + return param; + } return 255; } diff --git a/avr/cores/megacommand/MCL/LFOSeqTrack.h b/avr/cores/megacommand/MCL/LFOSeqTrack.h index d92bdcc2a..56b5a3975 100644 --- a/avr/cores/megacommand/MCL/LFOSeqTrack.h +++ b/avr/cores/megacommand/MCL/LFOSeqTrack.h @@ -28,11 +28,6 @@ class LFOSeqParam { uint8_t depth; uint8_t offset; - uint8_t get_param_offset(uint8_t dest, uint8_t param); - void reset_param(uint8_t dest, uint8_t param, uint8_t value); - void reset_param_offset(); - void update_offset(); - void update_kit(); }; class LFOSeqTrackData { @@ -40,14 +35,15 @@ class LFOSeqTrackData { LFOSeqParam params[NUM_LFO_PARAMS]; uint8_t wav_type; - uint8_t wav_table[NUM_LFO_PARAMS][WAV_LENGTH]; - bool wav_table_state[NUM_LFO_PARAMS]; + uint8_t wav_table[NUM_LFO_PARAMS][WAV_LENGTH];// <--- remove + bool wav_table_state[NUM_LFO_PARAMS]; // <---- remove + uint8_t last_wav_value[NUM_LFO_PARAMS]; - uint8_t sample_hold; + uint8_t sample_hold; //<--- shouldnt be stored here; uint8_t speed; uint8_t mode; - uint8_t offset_behaviour; + uint8_t offset_behaviour; //<--- no longer needed uint64_t pattern_mask; bool enable; uint8_t length; @@ -60,11 +56,12 @@ class LFOSeqTrackData { length = 16; for (uint8_t a = 0; a < NUM_LFO_PARAMS; a++) { last_wav_value[a] = 255; - params[a].dest = 255; + params[a].dest = 0; } } }; + class LFOSeqTrack : public LFOSeqTrackData { public: MidiUartParent *uart; @@ -72,32 +69,26 @@ class LFOSeqTrack : public LFOSeqTrackData { uint8_t step_count; uint8_t sample_count; + static uint8_t wav_tables[4][WAV_LENGTH]; + LFOSeqTrack() { init(); }; - ALWAYS_INLINE() uint8_t get_wav_value(uint8_t sample_count, uint8_t param); - void update_kit_params(); - void update_params_offset(); - void reset_params_offset(); - bool wav_table_up_to_date(uint8_t n) { return wav_table_state[n]; } + int16_t get_sample(uint8_t n); + + void load_tables(); + + uint8_t get_param_offset(uint8_t dest, uint8_t param); + ALWAYS_INLINE() uint8_t get_wav_value(uint8_t sample_count, uint8_t dest, uint8_t param); - void check_and_update_params_offset(uint8_t dest, uint8_t param, - uint8_t value); void set_wav_type(uint8_t _wav_type) { - if (wav_type != _wav_type) { wav_type = _wav_type; - wav_table_state[0] = false; - wav_table_state[1] = false; - } } void set_speed(uint8_t _speed) { speed = _speed; } void set_depth(uint8_t param, uint8_t depth) { - if (params[param].depth != depth) { params[param].depth = depth; - wav_table_state[param] = false; - } } void load_wav_table(uint8_t table); - ALWAYS_INLINE() void seq(MidiUartParent *uart_); + ALWAYS_INLINE() void seq(MidiUartParent *uart_, MidiUartParent *uart2_); }; #endif /* LFOSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.cpp b/avr/cores/megacommand/MCL/LoadProjectPage.cpp index feef26a4c..3204781a7 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.cpp +++ b/avr/cores/megacommand/MCL/LoadProjectPage.cpp @@ -1,5 +1,6 @@ #include "MCL_impl.h" + void LoadProjectPage::init() { DEBUG_PRINT_FN(); @@ -12,6 +13,8 @@ void LoadProjectPage::init() { show_overwrite = false; FileBrowserPage::init(); + strncpy(focus_match,mcl_cfg.project,PRJ_NAME_LEN); + query_filesystem(); } void LoadProjectPage::setup() { @@ -31,7 +34,7 @@ void LoadProjectPage::on_select(const char *entry) { while (count--) { if (proj.load_project(proj_filename)) { DEBUG_PRINTLN("loaded, setting grid"); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return; } else { gfx.alert("PROJECT ERROR", "NOT COMPATIBLE"); diff --git a/avr/cores/megacommand/MCL/LoadProjectPage.h b/avr/cores/megacommand/MCL/LoadProjectPage.h index 0816f08d5..109f414f6 100644 --- a/avr/cores/megacommand/MCL/LoadProjectPage.h +++ b/avr/cores/megacommand/MCL/LoadProjectPage.h @@ -19,7 +19,7 @@ class LoadProjectPage : public FileBrowserPage { virtual void on_delete(const char *entry); virtual void on_rename(const char *from, const char *to); virtual void setup(); - void init(); + virtual void init(); }; #endif /* LOADPROJECTPAGE_H__ */ diff --git a/avr/cores/megacommand/MCL/MCL.cpp b/avr/cores/megacommand/MCL/MCL.cpp index 83b2644ff..da502f799 100644 --- a/avr/cores/megacommand/MCL/MCL.cpp +++ b/avr/cores/megacommand/MCL/MCL.cpp @@ -1,3 +1,4 @@ +#include "mcl.h" #include "MCL_impl.h" #include "ResourceManager.h" @@ -33,6 +34,54 @@ void sdcard_bench() { void mcl_setup() { mcl.setup(); } +static LightPage *const MCL::pages_table[NUM_PAGES] PROGMEM = { + &grid_page, // Index: 0 + &page_select_page, // Index: 1 + &system_page, // Index: 2 + &mixer_page, // Index: 3 + &grid_save_page, // Index: 4 + &grid_load_page, // Index: 5 +#ifdef WAV_DESIGNER + &wd.mixer, // Index: 6 +#endif + &seq_step_page, // Index: 7 + &seq_extstep_page, // Index: 8 + &seq_ptc_page, // Index: 9 + &text_input_page, // Index: 10 + &poly_page, // Index: 11 + &sample_browser, // Index: 12 + &questiondialog_page, // Index: 13 + &start_menu_page, // Index: 14 + &boot_menu_page, // Index: 15 + &fx_page_a, // Index: 16 + &fx_page_b, // Index: 17 +#ifdef WAV_DESIGNER + &wd.pages[0], // Index: 18 + &wd.pages[1], // Index: 19 + &wd.pages[2], // Index: 20 +#endif + &route_page, // Index: 21 + &lfo_page, // Index: 22 + &ram_page_a, // Index: 23 + &ram_page_b, // Index: 24 + &load_proj_page, // Index: 25 + &midi_config_page, // Index: 26 + &md_config_page, // Index: 27 + &chain_config_page, // Index: 28 + &aux_config_page, // Index: 29 + &mcl_config_page, // Index: 30 + &ram_config_page, // Index: 31 + &arp_page, // Index: 32 + &md_import_page, // Index: 33 + &midiport_menu_page, // Index: 34 + &midiprogram_menu_page, // Index: 35 + &midiclock_menu_page, // Index: 36 + &midiroute_menu_page, // Index: 37 + &midimachinedrum_menu_page,// Index: 38 + &sound_browser, // Index: 39 + &perf_page // Index: 40 +}; + void MCL::setup() { DEBUG_PRINTLN(F("Welcome to MegaCommand Live")); @@ -50,7 +99,7 @@ void MCL::setup() { DEBUG_DUMP(sizeof(GridChainTrack)); DEBUG_PRINTLN("bank1 end: "); - DEBUG_PRINTLN(BANK1_FILE_ENTRIES_END); + DEBUG_PRINTLN(BANK3_FILE_ENTRIES_END); bool ret = false; delay(100); @@ -62,15 +111,15 @@ void MCL::setup() { if (BUTTON_DOWN(Buttons.BUTTON2)) { // gfx.draw_evil(R.icons_boot->evilknievel_bitmap); - GUI.setPage(&boot_menu_page); - while (GUI.currentPage() == &boot_menu_page) { + mcl.setPage(BOOT_MENU_PAGE); + while (mcl.currentPage() == BOOT_MENU_PAGE) { GUI.loop(); } return; } if (!ret) { - oled_display.print("SD CARD ERROR :-("); + oled_display.print(F("SD CARD ERROR :-(")); oled_display.display(); delay(2000); return; @@ -82,7 +131,7 @@ void MCL::setup() { GUI.addEventHandler((event_handler_t)&mcl_handleEvent); if (ret) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } DEBUG_PRINTLN(F("tempo:")); @@ -107,6 +156,7 @@ void MCL::setup() { A4SysexListener.setup(&Midi2); MNMSysexListener.setup(&Midi2); #endif + perf_page.setup(); grid_task.init(); @@ -163,18 +213,18 @@ bool mcl_handleEvent(gui_event_t *event) { case MDX_KEY_BANKB: case MDX_KEY_BANKC: case MDX_KEY_BANKD: { - if (GUI.currentPage() == &grid_load_page || - GUI.currentPage() == &grid_save_page || - (GUI.currentPage() == &grid_page && grid_page.show_slot_menu)) { + if (mcl.currentPage() == GRID_LOAD_PAGE || + mcl.currentPage() == GRID_SAVE_PAGE || + (mcl.currentPage() == GRID_PAGE && grid_page.show_slot_menu)) { return false; } if (trig_interface.is_key_down(MDX_KEY_FUNC)) { return false; } - if (grid_page.last_page == nullptr) { - grid_page.last_page = GUI.currentPage(); + if (grid_page.last_page == 255) { + grid_page.last_page = mcl.currentPage(); } - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); grid_page.bank_popup = 1; grid_page.bank_popup_loadmask = 0; bool clear_states = false; @@ -190,30 +240,34 @@ bool mcl_handleEvent(gui_event_t *event) { return true; } case MDX_KEY_BANKGROUP: { - if (GUI.currentPage() != &text_input_page && - GUI.currentPage() != &grid_save_page && - GUI.currentPage() != &grid_load_page && + if (mcl.currentPage() != TEXT_INPUT_PAGE && + mcl.currentPage() != GRID_SAVE_PAGE && + mcl.currentPage() != GRID_LOAD_PAGE && !trig_interface.is_key_down(MDX_KEY_PATSONG)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } return false; } case MDX_KEY_REC: { - if (GUI.currentPage() != &seq_step_page && - GUI.currentPage() != &seq_ptc_page && - GUI.currentPage() != &seq_extstep_page) { + if (mcl.currentPage() != SEQ_STEP_PAGE && + mcl.currentPage() != SEQ_PTC_PAGE && + mcl.currentPage() != SEQ_EXTSTEP_PAGE) { seq_step_page.prepare = true; - GUI.setPage(&seq_step_page); + if (mcl.currentPage() != SOUND_BROWSER && mcl.currentPage() != ARP_PAGE && mcl.currentPage() != POLY_PAGE) { + seq_step_page.last_page = mcl.currentPage(); + } + mcl.setPage(SEQ_STEP_PAGE); } else { if (seq_step_page.recording) { seq_step_page.recording = 0; - MD.set_rec_mode(GUI.currentPage() == &seq_step_page); + MD.set_rec_mode(mcl.currentPage() == SEQ_STEP_PAGE); clearLed2(); trig_interface.ignoreNextEvent(MDX_KEY_REC); } else { - if (GUI.currentPage() == &seq_step_page) { - GUI.setPage(&grid_page); + if (mcl.currentPage() == SEQ_STEP_PAGE) { + trig_interface.ignoreNextEvent(MDX_KEY_REC); + mcl.setPage(seq_step_page.last_page); } } } @@ -224,34 +278,34 @@ bool mcl_handleEvent(gui_event_t *event) { return true; } case MDX_KEY_COPY: { - if (GUI.currentPage() == &seq_step_page) + if (mcl.currentPage() == SEQ_STEP_PAGE || mcl.currentPage() == PERF_PAGE_0) break; - if (GUI.currentPage() != &seq_ptc_page && + if (mcl.currentPage() != SEQ_PTC_PAGE && (trig_interface.is_key_down(MDX_KEY_SCALE) || trig_interface.is_key_down(MDX_KEY_NO))) { // Ignore scale + copy if page != seq_step_page break; } opt_copy = 2; - if (GUI.currentPage() == &seq_ptc_page || - GUI.currentPage() == &seq_extstep_page) { + if (mcl.currentPage() == SEQ_PTC_PAGE || + mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_copy = SeqPage::recording ? 2 : 1; } opt_copy_track_handler_cb(); break; } case MDX_KEY_PASTE: { - if (GUI.currentPage() == &seq_step_page) + if (mcl.currentPage() == SEQ_STEP_PAGE || mcl.currentPage() == PERF_PAGE_0) break; - if (GUI.currentPage() != &seq_ptc_page && + if (mcl.currentPage() != SEQ_PTC_PAGE && (trig_interface.is_key_down(MDX_KEY_SCALE) || trig_interface.is_key_down(MDX_KEY_NO))) { // Ignore scale + copy if page != seq_step_page break; } opt_paste = 2; - if (GUI.currentPage() == &seq_ptc_page || - GUI.currentPage() == &seq_extstep_page) { + if (mcl.currentPage() == SEQ_PTC_PAGE || + mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_paste = SeqPage::recording ? 2 : 1; } reset_undo(); @@ -259,7 +313,7 @@ bool mcl_handleEvent(gui_event_t *event) { break; } case MDX_KEY_CLEAR: { - if (GUI.currentPage() == &seq_step_page) + if (mcl.currentPage() == SEQ_STEP_PAGE || mcl.currentPage() == PERF_PAGE_0) break; if ((note_interface.notes_count_on() > 0) || (trig_interface.is_key_down(MDX_KEY_SCALE) || @@ -267,13 +321,10 @@ bool mcl_handleEvent(gui_event_t *event) { break; opt_clear = 2; // MidiDevice *dev = midi_active_peering.get_device(UART2_PORT); - if (GUI.currentPage() == &seq_ptc_page || - GUI.currentPage() == &seq_extstep_page) { - // if (SeqPage::midi_device == dev) { + if (mcl.currentPage() == SEQ_PTC_PAGE) { opt_clear = 1; } + if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { opt_clear = 1; - // } else { - // opt_clear = SeqPage::recording ? 2 : 1; - // } + if (seq_extstep_page.pianoroll_mode > 0) { opt_clear_locks_handler(); break; } } opt_clear_track_handler(); break; @@ -293,11 +344,12 @@ bool mcl_handleEvent(gui_event_t *event) { switch (key) { case MDX_KEY_REC: { - if (!SeqPage::recording && (GUI.currentPage() == &seq_ptc_page || - GUI.currentPage() == &seq_extstep_page)) { - if (GUI.currentPage() != &seq_step_page) { + if (!SeqPage::recording && (mcl.currentPage() == SEQ_PTC_PAGE || + mcl.currentPage() == SEQ_EXTSTEP_PAGE)) { + if (mcl.currentPage() != SEQ_STEP_PAGE) { seq_step_page.prepare = true; - GUI.setPage(&seq_step_page); + seq_step_page.last_page = mcl.currentPage(); + mcl.setPage(SEQ_STEP_PAGE); } return true; } diff --git a/avr/cores/megacommand/MCL/MCL.h b/avr/cores/megacommand/MCL/MCL.h index 91a88be03..aa374a552 100644 --- a/avr/cores/megacommand/MCL/MCL.h +++ b/avr/cores/megacommand/MCL/MCL.h @@ -8,44 +8,119 @@ #include "WProgram.h" #ifdef MEGACOMMAND - #define WAV_DESIGNER - #define SOUND_PAGE +#define WAV_DESIGNER +#define SOUND_PAGE #endif -//MCL Fonts -#include "Fonts/TomThumb.h" +// MCL Fonts #include "Fonts/Elektrothic.h" +#include "Fonts/TomThumb.h" -#define VERSION 4043 -#define VERSION_STR "4.43" +#define VERSION 4050 +#define VERSION_STR "4.50" #define CALLBACK_TIMEOUT 500 #define GUI_NAME_TIMEOUT 800 -#define CUE_PAGE 5 -#define NEW_PROJECT_PAGE 7 -#define MIXER_PAGE 10 -#define S_PAGE 3 -#define W_PAGE 4 -#define SEQ_STEP_PAGE 1 -#define SEQ_EXTSTEP_PAGE 18 -#define SEQ_PTC_PAGE 16 -#define SEQ_EUC_PAGE 20 -#define SEQ_EUCPTC_PAGE 21 -#define SEQ_RPTC_PAGE 14 -#define LOAD_PROJECT_PAGE 8 - #define MD_KITBUF_POS 63 -// Sequencer editing constants -#define DIR_LEFT 0 -#define DIR_RIGHT 1 -#define DIR_REVERSE 2 - extern void mcl_setup(); +enum PageIndex { + GRID_PAGE, // Index: 0 + PAGE_SELECT_PAGE, // Index: 1 + SYSTEM_PAGE, // Index: 2 + MIXER_PAGE, // Index: 3 + GRID_SAVE_PAGE, // Index: 4 + GRID_LOAD_PAGE, // Index: 5 +#ifdef WAV_DESIGNER + WD_MIXER_PAGE, // Index: 6 +#endif + SEQ_STEP_PAGE, // Index: 7 + SEQ_EXTSTEP_PAGE, // Index: 8 + SEQ_PTC_PAGE, // Index: 9 + TEXT_INPUT_PAGE, // Index: 10 + POLY_PAGE, // Index: 11 + SAMPLE_BROWSER, // Index: 12 + QUESTIONDIALOG_PAGE, // Index: 13 + START_MENU_PAGE, // Index: 14 + BOOT_MENU_PAGE, // Index: 15 + FX_PAGE_A, // Index: 16 + FX_PAGE_B, // Index: 17 +#ifdef WAV_DESIGNER + WD_PAGE_0, // Index: 18 + WD_PAGE_1, // Index: 19 + WD_PAGE_2, // Index: 20 +#endif + ROUTE_PAGE, // Index: 21 + LFO_PAGE, // Index: 22 + RAM_PAGE_A, // Index: 23 + RAM_PAGE_B, // Index: 24 + + LOAD_PROJ_PAGE, // Index: 25 + MIDI_CONFIG_PAGE, // Index: 26 + MD_CONFIG_PAGE, // Index: 27 + CHAIN_CONFIG_PAGE, // Index: 28 + AUX_CONFIG_PAGE, // Index: 29 + MCL_CONFIG_PAGE, // Index: 30 + RAM_CONFIG_PAGE, // Index: 31 + ARP_PAGE, // Index: 32 + MD_IMPORT_PAGE, // Index: 33 + MIDIPORT_MENU_PAGE, // Index: 34 + MIDIPROGRAM_MENU_PAGE, // Index: 35 + MIDICLOCK_MENU_PAGE, // Index: 36 + MIDIROUTE_MENU_PAGE, // Index: 37 + MIDIMACHINEDRUM_MENU_PAGE,// Index: 38 + SOUND_BROWSER, // Index: 39 + PERF_PAGE_0, // Index: 40 + NULL_PAGE = 255 +}; + + class MCL { public: + static constexpr uint8_t NUM_PAGES = 41; + + static LightPage *const pages_table[NUM_PAGES] PROGMEM; + + PageIndex current_page = GRID_PAGE; + + LightPage *getPage(PageIndex page) { + return (LightPage*) pgm_read_word(pages_table + page); + } + void setPage(PageIndex page) { + if (page >= NUM_PAGES) { + page = GRID_PAGE; + } + current_page = page; + GUI.setPage(getPage(page)); + } + + void pushPage(PageIndex page) { + if (page >= NUM_PAGES) { + page = GRID_PAGE; + } + current_page = page; + GUI.pushPage(getPage(page)); + } + + void popPage() { + GUI.popPage(); + for (uint8_t n = 0; n < NUM_PAGES; n++) { + if (GUI.currentPage() == getPage((PageIndex) n)) { + current_page = (PageIndex) n; + return; + } + } + current_page = NULL_PAGE; + } + + bool isSeqPage() { + return current_page == SEQ_STEP_PAGE || current_page == SEQ_PTC_PAGE || current_page == SEQ_EXTSTEP_PAGE; + } + + PageIndex currentPage() { return current_page; } + void setup(); }; diff --git a/avr/cores/megacommand/MCL/MCLActions.cpp b/avr/cores/megacommand/MCL/MCLActions.cpp index fbb4b1398..e2fa5d292 100644 --- a/avr/cores/megacommand/MCL/MCLActions.cpp +++ b/avr/cores/megacommand/MCL/MCLActions.cpp @@ -66,32 +66,16 @@ void MCLActions::kit_reload(uint8_t pattern) { */ } -uint8_t MCLActions::get_grid_idx(uint8_t slot_number) { - return slot_number / GRID_WIDTH; -} -GridDeviceTrack *MCLActions::get_grid_dev_track(uint8_t slot_number, - uint8_t *track_idx, - uint8_t *dev_idx) { - uint8_t grid_idx = get_grid_idx(slot_number); - MidiDevice *devs[2] = { - midi_active_peering.get_device(UART1_PORT), - midi_active_peering.get_device(UART2_PORT), - }; +GridDeviceTrack *MCLActions::get_grid_dev_track(uint8_t slot_number) { + + uint8_t grid_idx = 0; + if (slot_number >= GRID_WIDTH) { slot_number -= GRID_WIDTH; grid_idx = 1; } // Find first device that is hosting this slot_number. - for (uint8_t n = 0; n < 2; n++) { - auto *p = &(devs[n]->grid_devices[grid_idx]); - for (uint8_t i = 0; i < GRID_WIDTH; i++) { - if (slot_number == p->tracks[i].get_slot_number()) { - *track_idx = i; - *dev_idx = n; - return &(p->tracks[i]); - } - } - } - *track_idx = 255; - *dev_idx = 255; - return nullptr; + + GridDeviceTrack *gdt = &proj.grids[grid_idx].tracks[slot_number]; + if (!gdt->isActive()) { return nullptr; } + return gdt; } void md_import() { @@ -101,7 +85,6 @@ void md_import() { } uint8_t track_select_array[NUM_SLOTS] = {0}; - uint8_t track_idx, dev_idx; MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), @@ -115,12 +98,12 @@ void md_import() { for (uint8_t n = 0; n < NUM_SLOTS; n++) { GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(n, &track_idx, &dev_idx); + mcl_actions.get_grid_dev_track(n); - if (gdt == nullptr || track_idx == 255) + if (gdt == nullptr) continue; - if (devs[dev_idx] == &MD) { + if (devs[gdt->device_idx] == &MD) { track_select_array[n] = 1; } } @@ -135,7 +118,7 @@ void md_import() { grid_page.row_scan = GRID_LENGTH; grid_page.reload_slot_models = false; - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } void MCLActions::save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, @@ -162,13 +145,12 @@ void MCLActions::save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, uint8_t i = 0; - uint8_t track_idx, dev_idx; for (i = 0; i < NUM_SLOTS; i++) { if (slot_select_array[i] > 0) { - GridDeviceTrack *gdt = get_grid_dev_track(i, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(i); if (gdt != nullptr) { - save_dev_tracks[dev_idx] = true; + save_dev_tracks[gdt->device_idx] = true; } } } @@ -234,14 +216,15 @@ void MCLActions::save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, for (i = 0; i < NUM_SLOTS; i++) { if (slot_select_array[i] > 0) { - GridDeviceTrack *gdt = get_grid_dev_track(i, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(i); uint8_t grid_idx = get_grid_idx(i); - - bool online = (devs[dev_idx] != nullptr); + uint8_t track_idx = get_track_idx(i); + uint8_t device_idx = gdt->device_idx; + bool online = (devs[device_idx] != nullptr); // If save_dev_tracks[dev_idx] turns false, it means getBlockingKit // has failed, so we just skip this device. - if (!save_dev_tracks[dev_idx]) { + if (!save_dev_tracks[device_idx]) { continue; } @@ -295,14 +278,13 @@ void MCLActions::load_tracks(int row, uint8_t *slot_select_array, } uint8_t row_array[NUM_SLOTS] = {}; uint8_t cache_track_array[NUM_SLOTS] = {}; - uint8_t track_idx, dev_idx; bool recache = false; DEBUG_PRINTLN("load tracks"); DEBUG_PRINTLN(load_mode); for (uint8_t n = 0; n < NUM_SLOTS; ++n) { - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); // DEBUG_PRINTLN(slot_select_array[n]); - if ((slot_select_array[n] == 0) || (gdt == nullptr)) { + if ((slot_select_array[n] == 0) || gdt == nullptr) { continue; } if (_row_array == nullptr) { @@ -352,25 +334,27 @@ void MCLActions::collect_tracks(uint8_t *slot_select_array, uint8_t old_grid = proj.get_grid(); memset(dev_sync_slot, 255, NUM_DEVS); - uint8_t track_idx, dev_idx; for (uint8_t n = 0; n < NUM_SLOTS; ++n) { - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); uint8_t grid_idx = get_grid_idx(n); + uint8_t track_idx = get_track_idx(n); + proj.select_grid(grid_idx); - if ((slot_select_array[n] == 0) || (gdt == nullptr)) { + if ((slot_select_array[n] == 0) || gdt == nullptr) { // Ignore slots that are not device supported. slot_select_array[n] = 0; continue; } uint8_t row = row_array[n]; EmptyTrack empty_track; - // DEBUG_PRINTLN(F("cl")); + auto *device_track = empty_track.load_from_grid(track_idx, row); if (device_track == nullptr || device_track->active != gdt->track_type && device_track->get_parent_model() != gdt->track_type) { empty_track.clear(); + if (device_track->active != EMPTY_TRACK_TYPE) { empty_track.init(); } device_track = device_track->init_track_type(gdt->track_type); if (device_track) { device_track->init(track_idx, gdt->seq_track); @@ -381,7 +365,7 @@ void MCLActions::collect_tracks(uint8_t *slot_select_array, device_track->init_track_type(device_track->get_parent_model()); } send_machine[n] = device_track->transition_cache(track_idx, n); - dev_sync_slot[dev_idx] = n; + dev_sync_slot[gdt->device_idx] = n; } if (device_track) { device_track->store_in_mem(gdt->mem_slot_idx); @@ -400,13 +384,13 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, collect_tracks(slot_select_array, row_array); - uint16_t next_step = (MidiClock.div16th_counter / q) * q + q; - - uint8_t loops = 1; + uint16_t next_step = q == 255 ? (uint16_t) -1 : (MidiClock.div16th_counter / q) * q + q; - uint8_t track_idx, dev_idx; + bool increase_loops = 0; bool recalc_latency = true; + uint8_t headroom = 3; + //uint8_t headroom = ceil(MidiClock.get_tempo()* 0.133333333333f * 0.200f); ////DEBUG_PRINTLN("manual trans"); again: bool overflow = next_step < MidiClock.div16th_counter; @@ -417,18 +401,33 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, if (slot_select_array[n] > 0) { row = row_array[n]; if (q == 255) { - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); if (gdt != nullptr) { transition_level[n] = 0; - next_transitions[n] = - div16th_counter - ((float)gdt->seq_track->step_count * - gdt->seq_track->get_speed_multiplier()); + if (increase_loops) { + if (next_transitions[n] == next_transition) { + DEBUG_PRINTLN("increasing loops"); + links[n].loops++; + } + } + else { + links[n].loops = 1; + } links[n].speed = gdt->seq_track->speed; links[n].length = gdt->seq_track->length; links[n].row = row; - links[n].loops = loops; + + next_transitions[n] = MidiClock.div16th_counter - ((float)gdt->seq_track->step_count * + gdt->seq_track->get_speed_multiplier() + (gdt->seq_track->mod12_counter / 12) ); + + bool ignore_chain_settings = true; - calc_next_slot_transition(n, ignore_chain_settings); + bool ignore_overflow = true; + calc_next_slot_transition(n, ignore_chain_settings, ignore_overflow); + + if (MidiClock.clock_less_than(next_transitions[n], next_step)) { + next_step = next_transitions[n]; + } grid_page.active_slots[n] = SLOT_PENDING; } } else { @@ -454,7 +453,7 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, grid_task.next_active_row = row; grid_task.chain_behaviour = false; - grid_task.gui_update(); + grid_task.row_update(); if (recalc_latency) { calc_latency(); @@ -469,16 +468,21 @@ void MCLActions::manual_transition(uint8_t *slot_select_array, // MidiClock.div16th_counter; next transition should always be at least 2 // steps away. - uint32_t next32 = (uint32_t)next_transition; + uint32_t next_16th = (uint32_t)next_transition; + + //only recalculate if next_transition is a manual transition. + if (next_transition == next_step) { if (overflow) { - next32 += (uint16_t)-1; + next_16th += (uint16_t)-1; } - if (next32 - (div192th_total_latency / 12) - 2 < - (uint32_t)MidiClock.div16th_counter) { + uint32_t next_32th = next_16th * 2; + + if (next_32th - (div192th_total_latency / 6) - headroom < + (uint32_t)MidiClock.div16th_counter * 2) { if (q == 255) { - loops += 1; + increase_loops = 1; } else { // DEBUG_PRINTLN("try again"); next_step += q; @@ -503,20 +507,23 @@ bool MCLActions::load_track(uint8_t track_idx, uint8_t row, uint8_t pos, if (ptrack->active != gdt->track_type && ptrack->get_parent_model() != gdt->track_type) { empty_track.clear(); - DEBUG_PRINTLN("Clearing track"); - DEBUG_PRINTLN(pos); + if (ptrack->active != EMPTY_TRACK_TYPE) { empty_track.init(); } ptrack->init_track_type(gdt->track_type); ptrack->init(track_idx, gdt->seq_track); - ptrack->load_seq_data(gdt->seq_track); + ptrack->load_immediate_cleared(track_idx, gdt->seq_track); } else { if (ptrack->get_parent_model() == gdt->track_type && ptrack->allow_cast_to_parent()) { ptrack->init_track_type(ptrack->get_parent_model()); } - DEBUG_PRINTLN("load immediate track"); - ptrack->load_immediate(track_idx, gdt->seq_track); - ptrack->store_in_mem(track_idx); - send_masks[pos] = 1; + if (ptrack != nullptr) { + send_masks[pos] = 1; + ptrack->load_immediate(track_idx, gdt->seq_track); + } } + if (ptrack != nullptr) { + ptrack->store_in_mem(gdt->mem_slot_idx); + } + return true; } @@ -539,17 +546,16 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, uint8_t row = 0; uint8_t old_grid = proj.get_grid(); - uint8_t track_idx, dev_idx; - // DEBUG_PRINTLN("send tracks 1"); // DEBUG_PRINTLN((int)SP); // DEBUG_CHECK_STACK(); uint8_t last_slot = 255; for (uint8_t i = 0; i < NUM_SLOTS; i++) { - - GridDeviceTrack *gdt = get_grid_dev_track(i, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(i); uint8_t grid_idx = get_grid_idx(i); + uint8_t track_idx = get_track_idx(i); + proj.select_grid(grid_idx); if (gdt == nullptr) { @@ -601,7 +607,8 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, if (dst != nullptr) { if (row_header.active) { uint8_t len = elektron_dev->sysex_protocol.kitname_length; - memcpy(dst, row_header.name, len); + strncpy(dst, row_header.name, len); + m_toupper(dst); dst[len - 1] = '\0'; } else { strcpy(dst, "NEW KIT"); @@ -622,7 +629,7 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, } GUI.addTask(&grid_task); for (uint8_t i = 0; i < NUM_SLOTS; ++i) { - GridDeviceTrack *gdt = get_grid_dev_track(i, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(i); if (gdt != nullptr) { gdt->seq_track->mute_state = mute_states[i]; } @@ -644,7 +651,7 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, for (uint8_t n = 0; n < NUM_SLOTS; n++) { if ((select_array[n] > 0) && (grid_page.active_slots[n] != SLOT_DISABLED)) { - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); if (gdt != nullptr) { transition_level[n] = 0; next_transitions[n] = MidiClock.div16th_counter - @@ -663,31 +670,18 @@ void MCLActions::send_tracks_to_devices(uint8_t *slot_select_array, grid_task.next_active_row = links[last_slot].row; grid_task.chain_behaviour = chains[last_slot].mode > 1; } - grid_task.gui_update(); + grid_task.row_update(); calc_next_transition(); calc_latency(); } -void MCLActions::cache_track(uint8_t n, uint8_t track_idx, uint8_t dev_idx, - GridDeviceTrack *gdt) {} void MCLActions::cache_next_tracks(uint8_t *slot_select_array, bool gui_update) { - // //DEBUG_PRINT_FN(); - // //DEBUG_PRINTLN("cache next"); - // //DEBUG_PRINTLN((int)SP); - // DEBUG_CHECK_STACK(); - /* - while (SeqTrack::in_countdown && (MidiClock.state == 2)) { - gui_loop(); - } - */ uint8_t old_grid = proj.get_grid(); - uint8_t track_idx, dev_idx; - memset(dev_sync_slot, 255, sizeof(dev_sync_slot)); const uint8_t div32th_margin = 1; @@ -703,25 +697,27 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, // float div192th_time = 1.25 / tempo; // diff * div19th_time > 80ms equivalent to diff > (0.08/1.25) * tempo - float ms = (0.80 / 1.25) * tempo; + //float ms = (0.08 * 0.80) * tempo == 0.064 * tempo; for (uint8_t n = 0; n < NUM_SLOTS; n++) { if (slot_select_array[n] == 0) continue; - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); uint8_t grid_idx = get_grid_idx(n); + uint8_t track_idx = get_track_idx(n); if (gdt == nullptr) continue; uint32_t diff = MidiClock.clock_diff_div192( MidiClock.div192th_counter, (uint32_t)next_transition * 12 + 4 * 12); + while ((gdt->seq_track->count_down && (MidiClock.state == 2))) { proj.select_grid(old_grid); handleIncomingMidi(); - if (((float)diff > 0.08 * 0.8 * tempo) && gui_update) { + if (((float)diff > 0.064 * tempo) && gui_update) { GUI.loop(); } } @@ -759,6 +755,7 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, // EMPTY_TRACK_TYPE ////DEBUG_PRINTLN(F("clear track")); empty_track.clear(); + if (ptrack->active != EMPTY_TRACK_TYPE) { empty_track.init(); } ptrack = empty_track.init_track_type(gdt->track_type); ptrack->init(track_idx, gdt->seq_track); } else { @@ -769,7 +766,7 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, if (ptrack->memcmp_sound(gdt->mem_slot_idx) != 0) { ptrack->transition_cache(track_idx, n); send_machine[n] = 0; - dev_sync_slot[dev_idx] = n; + dev_sync_slot[gdt->device_idx] = n; } } } @@ -784,23 +781,9 @@ void MCLActions::cache_next_tracks(uint8_t *slot_select_array, void MCLActions::calc_next_slot_transition(uint8_t n, bool ignore_chain_settings, - bool auto_check) { - - // DEBUG_PRINT_FN(); + bool ignore_overflow) { - if (auto_check) { - switch (chains[n].mode) { - case LOAD_AUTO: { - if (links[n].loops == 0) { - next_transitions[n] = -1; - return; - } - break; - } - } - } - - if (!ignore_chain_settings) { + if (!ignore_chain_settings) { switch (chains[n].mode) { case LOAD_QUEUE: { break; @@ -820,13 +803,12 @@ void MCLActions::calc_next_slot_transition(uint8_t n, } // next transition[n] already valid, use this. - if (next_transitions[n] == -1 || next_transitions[n] > next_transition) { + if (next_transitions[n] == -1 || (next_transitions[n] > next_transition && !ignore_overflow)) { return; } - uint8_t track_idx, dev_idx; - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); if (gdt == nullptr) { return; } @@ -918,8 +900,6 @@ void MCLActions::calc_latency() { bool send_dev[NUM_DEVS] = {0}; - uint8_t track_idx, dev_idx; - uint8_t num_devices = 0; // DEBUG_PRINTLN("calc latency"); @@ -928,10 +908,12 @@ void MCLActions::calc_latency() { if ((grid_page.active_slots[n] == SLOT_DISABLED)) continue; if (next_transitions[n] == next_transition) { - GridDeviceTrack *gdt = get_grid_dev_track(n, &track_idx, &dev_idx); + GridDeviceTrack *gdt = get_grid_dev_track(n); + uint8_t track_idx = get_track_idx(n); if (gdt == nullptr) { continue; } + uint8_t device_idx = gdt->device_idx; if (send_machine[n] == 0) { // Optimised, assume we dont need to read the entire object to calculate // latency. @@ -943,12 +925,12 @@ void MCLActions::calc_latency() { continue; } // dev_latency[dev_idx].load_latency += diff; - dev_latency[dev_idx].latency += ptrack->calc_latency(n); + dev_latency[device_idx].latency += ptrack->calc_latency(n); } - if (send_dev[dev_idx] != true) { + if (send_dev[device_idx] != true) { num_devices++; } - send_dev[dev_idx] = true; + send_dev[device_idx] = true; } } @@ -978,9 +960,9 @@ void MCLActions::calc_latency() { // latency_in_seconds += (float) dev_latency[a].load_latency * .0002; dev_latency[a].div32th_latency = - floor(div32th_per_second * latency_in_seconds) + 1; + ceil(div32th_per_second * latency_in_seconds); dev_latency[a].div192th_latency = - floor(div192th_per_second * latency_in_seconds) + 1; + ceil(div192th_per_second * latency_in_seconds); // Program change minimum delay = 1 x 16th. if (mcl_cfg.uart2_prg_out > 0 && a == 1) { diff --git a/avr/cores/megacommand/MCL/MCLActions.h b/avr/cores/megacommand/MCL/MCLActions.h index 4081bca08..e2df415ed 100644 --- a/avr/cores/megacommand/MCL/MCLActions.h +++ b/avr/cores/megacommand/MCL/MCLActions.h @@ -69,27 +69,33 @@ class MCLActions : public LinkModeData { uint8_t get_quant() { uint8_t q; if ((mcl_cfg.chain_load_quant == 1)) { - q = QUANT_LEN; //use slot settings + q = QUANT_LEN; // use slot settings } else { - q = mcl_cfg.chain_load_quant; //override + q = mcl_cfg.chain_load_quant; // override } return q; } - //This is the track length quantisatioe + // This is the track length quantisatioe uint8_t get_chain_length() { uint8_t q; if (mcl_cfg.chain_queue_length == 1) { - q = QUANT_LEN; //use slot settings + q = QUANT_LEN; // use slot settings } else { - q = mcl_cfg.chain_queue_length; //override + q = mcl_cfg.chain_queue_length; // override } return q; } - uint8_t get_grid_idx(uint8_t slot_number); - GridDeviceTrack *get_grid_dev_track(uint8_t slot_number, uint8_t *id, - uint8_t *dev_idx); + uint8_t get_grid_idx(uint8_t slot_number) { + return slot_number < GRID_WIDTH ? 0 : 1; + } + + uint8_t get_track_idx(uint8_t slot_number) { + return slot_number < GRID_WIDTH ? slot_number : slot_number - GRID_WIDTH; + } + + GridDeviceTrack *get_grid_dev_track(uint8_t slot_number); void init_chains(); @@ -97,21 +103,27 @@ class MCLActions : public LinkModeData { void switch_global(uint8_t global_page); void kit_reload(uint8_t pattern); - void save_tracks(int row, uint8_t *slot_select_array, - uint8_t merge, uint8_t readpattern = 255); + void save_tracks(int row, uint8_t *slot_select_array, uint8_t merge, + uint8_t readpattern = 255); - void load_tracks(int row, uint8_t *slot_select_array, uint8_t *_row_array = nullptr, uint8_t load_mode = 255); - void send_tracks_to_devices(uint8_t *slot_select_array, uint8_t *row_array = nullptr); + void load_tracks(int row, uint8_t *slot_select_array, + uint8_t *_row_array = nullptr, uint8_t load_mode = 255); + void send_tracks_to_devices(uint8_t *slot_select_array, + uint8_t *row_array = nullptr); void manual_transition(uint8_t *slot_select_array, uint8_t *row_array); void cache_next_tracks(uint8_t *slot_select_array, bool gui_update = false); - void calc_next_slot_transition(uint8_t n, bool ignore_chain_settings = false, bool auto_check = false); + void calc_next_slot_transition(uint8_t n, bool ignore_chain_settings = false, + bool ignore_overflow = false); void calc_next_transition(); void calc_latency(); + private: void collect_tracks(uint8_t *slot_select_array, uint8_t *row_array); - void cache_track(uint8_t n, uint8_t track_idx, uint8_t dev_idx, GridDeviceTrack *gdt); - bool load_track(uint8_t track_idx, uint8_t row, uint8_t pos, GridDeviceTrack *gdt, uint8_t *send_masks); + void cache_track(uint8_t n, uint8_t track_idx, uint8_t dev_idx, + GridDeviceTrack *gdt); + bool load_track(uint8_t track_idx, uint8_t row, uint8_t pos, + GridDeviceTrack *gdt, uint8_t *send_masks); }; extern void md_import(); diff --git a/avr/cores/megacommand/MCL/MCLActionsEvents.cpp b/avr/cores/megacommand/MCL/MCLActionsEvents.cpp index 09e26785a..e400572f1 100644 --- a/avr/cores/megacommand/MCL/MCLActionsEvents.cpp +++ b/avr/cores/megacommand/MCL/MCLActionsEvents.cpp @@ -98,11 +98,11 @@ void MCLActionsCallbacks::StopHardCallback() { } } + uint8_t _midi_lock_tmp = MidiUartParent::handle_midi_lock; if (!proceed) { goto end; } - uint8_t _midi_lock_tmp = MidiUartParent::handle_midi_lock; MidiUartParent::handle_midi_lock = 1; /* ElektronDevice *elektron_devs[2] = { diff --git a/avr/cores/megacommand/MCL/MCLClipBoard.cpp b/avr/cores/megacommand/MCL/MCLClipBoard.cpp index 06a18aced..f34ece62b 100644 --- a/avr/cores/megacommand/MCL/MCLClipBoard.cpp +++ b/avr/cores/megacommand/MCL/MCLClipBoard.cpp @@ -17,7 +17,7 @@ bool MCLClipBoard::open() { DEBUG_PRINT_FN(); SD.chdir("/"); - char *str = FILENAME_CLIPBOARD; + char str[] = FILENAME_CLIPBOARD; char grid_filename[sizeof(FILENAME_CLIPBOARD) + 2]; strcpy(grid_filename, str); uint8_t l = strlen(grid_filename); @@ -69,6 +69,18 @@ bool MCLClipBoard::copy_sequencer(uint8_t offset) { return true; } +void MCLClipBoard::copy_scene(PerfScene *s1) { + memcpy(&scene, s1, sizeof(scene)); + copy_scene_active = 1; +} + +bool MCLClipBoard::paste_scene(PerfScene *s1) { + if (copy_scene_active) { + memcpy(s1, &scene, sizeof(scene)); + } + return copy_scene_active; +} + bool MCLClipBoard::copy_sequencer_track(uint8_t track) { DEBUG_PRINT_FN(); bool ret = false; @@ -78,18 +90,19 @@ bool MCLClipBoard::copy_sequencer_track(uint8_t track) { DEBUG_PRINTLN(F("error could not open clipboard")); return false; } - uint8_t track_idx, dev_idx; - GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(track, &track_idx, &dev_idx); + + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(track); if (gdt == nullptr) { return false; } uint8_t grid_idx = mcl_actions.get_grid_idx(track); + uint8_t track_idx = mcl_actions.get_track_idx(track); auto device_track = ((DeviceTrack *)&empty_track)->init_track_type(gdt->track_type); - if (device_track == nullptr) { goto end; } - bool merge = false; bool online = true; + if (device_track == nullptr) { goto end; } + ret = device_track->store_in_grid(track_idx, GRID_LENGTH, gdt->seq_track, merge, online, &grids[grid_idx]); @@ -127,12 +140,15 @@ bool MCLClipBoard::paste_sequencer_track(uint8_t source_track, uint8_t track) { MDTrack *md_track = (MDTrack *)(&temp_track); ExtTrack *ext_track = (ExtTrack *)(&temp_track); - uint8_t source_track_idx, track_idx, dev_idx; - GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(source_track, &source_track_idx, &dev_idx); + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(source_track); + uint8_t source_track_idx = mcl_actions.get_track_idx(source_track); + if (gdt == nullptr) { return false; } - gdt = mcl_actions.get_grid_dev_track(track, &track_idx, &dev_idx); + gdt = mcl_actions.get_grid_dev_track(track); + uint8_t track_idx = mcl_actions.get_track_idx(track); + if (gdt == nullptr) { return false; } uint8_t grid_idx = mcl_actions.get_grid_idx(track); @@ -158,10 +174,10 @@ bool MCLClipBoard::paste_sequencer_track(uint8_t source_track, uint8_t track) { midi_active_peering.get_device(UART2_PORT), }; if (devs[0] == &MD && track_idx == last_md_track) { - if (GUI.currentPage() == &seq_step_page) { + if (mcl.currentPage() == SEQ_STEP_PAGE) { seq_step_page.config(); } - if (GUI.currentPage() == &seq_ptc_page) { + if (mcl.currentPage() == SEQ_PTC_PAGE) { seq_ptc_page.config(); } } @@ -169,8 +185,7 @@ bool MCLClipBoard::paste_sequencer_track(uint8_t source_track, uint8_t track) { return true; } -bool MCLClipBoard::copy(uint16_t col, uint16_t row, uint16_t w, uint16_t h, - uint8_t grid) { +bool MCLClipBoard::copy(uint8_t col, uint16_t row, uint8_t w, uint16_t h) { DEBUG_PRINT_FN(); uint8_t old_grid = proj.get_grid(); t_col = col; @@ -186,27 +201,39 @@ bool MCLClipBoard::copy(uint16_t col, uint16_t row, uint16_t w, uint16_t h, bool ret; GridRowHeader header; + DEBUG_PRINTLN("copy"); + DEBUG_PRINTLN(col); + DEBUG_PRINTLN(row); + DEBUG_PRINTLN(w); + + uint8_t grid = col / 16; for (int y = 0; y < h; y++) { proj.select_grid(grid); proj.read_grid_row_header(&header, y + row); ret = grids[grid].write_row_header(&header, y + row); DEBUG_PRINTLN(header.name); - if (h > 8) { + if (h > 4) { mcl_gui.draw_progress("", y, h); } for (int x = 0; x < w; x++) { - ret = proj.read_grid(&temp_track, sizeof(temp_track), x + col, y + row); + uint8_t s_col = x + col; + if (x + col >= 16) { s_col -= 16; grid = 1; } + proj.select_grid(grid); + DEBUG_PRINT("Copy: "); DEBUG_PRINT(s_col); DEBUG_PRINT(" "); DEBUG_PRINT(y + row); DEBUG_PRINT(" "); DEBUG_PRINTLN(grid); + auto *ptrack = temp_track.load_from_grid_512(s_col, y + row); DEBUG_DUMP(temp_track.active); - if (ret) { - ret = grids[grid].write(&temp_track, sizeof(temp_track), x + col, - y + row); + if (ptrack != nullptr) { + bool merge = false; + bool online = false; + ptrack->store_in_grid(s_col, y + row, nullptr, merge, online, grids + grid); } + else { DEBUG_PRINTLN("ptrack null"); } } } close(); proj.select_grid(old_grid); } -bool MCLClipBoard::paste(uint16_t col, uint16_t row, uint8_t grid) { +bool MCLClipBoard::paste(uint8_t col, uint16_t row) { DEBUG_PRINT_FN(); uint8_t old_grid = proj.get_grid(); if (!open()) { @@ -214,50 +241,57 @@ bool MCLClipBoard::paste(uint16_t col, uint16_t row, uint8_t grid) { return false; } DEBUG_PRINTLN("paste here"); - bool destination_same = (col == t_col); - if (t_w == 1) { - destination_same = true; - } + bool destination_same = (col == t_col || t_w == 1); // setup buffer frame EmptyTrack empty_track; - GridRowHeader header; + GridRowHeader headers[2]; + GridRowHeader header_copy; - uint8_t track_idx, dev_idx; + uint8_t grid = col / 16; + for (int y = 0; y < t_h && y + row < GRID_LENGTH; y++) { - proj.select_grid(grid); - proj.read_grid_row_header(&header, y + row); - if ((!header.active) || (strlen(header.name) == 0) || + proj.select_grid(0); + proj.read_grid_row_header(headers, y + row); + proj.select_grid(1); + proj.read_grid_row_header(headers + 1, y + row); + if ((!headers[0].active) || (strlen(headers[0].name) == 0) || (t_w == GRID_WIDTH && col == 0)) { grids[grid].read_row_header(&header_copy, y + t_row); - header.active = true; + headers[0].active = true; + headers[1].active = true; if (header_copy.active) { - strncpy(&(header.name[0]), &(header_copy.name[0]), sizeof(header.name)); + strncpy(&(headers[0].name[0]), &(header_copy.name[0]), sizeof(headers[0].name)); + strncpy(&(headers[1].name[0]), &(header_copy.name[0]), sizeof(headers[0].name)); } else { - header.name[0] = '\0'; + headers[0].name[0] = '\0'; + headers[1].name[0] = '\0'; } } if (t_h > 8) { mcl_gui.draw_progress("", y, t_h); } - for (int x = 0; x < t_w && x + col < GRID_WIDTH; x++) { + for (int x = 0; x < t_w && x + col < GRID_WIDTH * 2; x++) { - // track now has full data and correct type uint8_t s_col = x + t_col; uint8_t d_col = x + col; - uint8_t slot_n = grid * GRID_WIDTH + d_col; + uint8_t slot_n = d_col; + + grid = s_col / 16; + + if (s_col >= GRID_WIDTH) { s_col -= GRID_WIDTH; } - grids[grid].read(&empty_track, sizeof(EmptyTrack), s_col, y + t_row); + auto *ptrack = empty_track.load_from_grid_512(s_col, y + t_row, grids + grid); + if (ptrack == nullptr) { continue; } - DeviceTrack *ptrack = - ((DeviceTrack *)&empty_track)->init_track_type(empty_track.active); - DEBUG_DUMP(ptrack->active); - GridDeviceTrack *gdt = - mcl_actions.get_grid_dev_track(slot_n, &track_idx, &dev_idx); + DEBUG_PRINTLN(slot_n); + + GridDeviceTrack *gdt = mcl_actions.get_grid_dev_track(slot_n); + uint8_t track_idx = mcl_actions.get_track_idx(slot_n); if ((gdt == nullptr || (gdt->track_type != ptrack->active && ptrack->get_parent_model() != gdt->track_type)) && (ptrack->active != EMPTY_TRACK_TYPE)) { @@ -273,12 +307,20 @@ bool MCLClipBoard::paste(uint16_t col, uint16_t row, uint8_t grid) { } else if (new_link_row < 0) { new_link_row = y + row; } + grid = d_col / 16; + if (d_col >= GRID_WIDTH) { d_col -= GRID_WIDTH; } + + DEBUG_PRINT("PASTE: "); DEBUG_PRINT(s_col); DEBUG_PRINT("->"); DEBUG_PRINT(d_col); DEBUG_PRINT(" "); DEBUG_PRINTLN(grid); + proj.select_grid(grid); ptrack->link.row = new_link_row; - header.update_model(d_col, ptrack->get_model(), ptrack->active); + headers[grid].update_model(d_col, ptrack->get_model(), ptrack->active); ptrack->on_copy(s_col, d_col, destination_same); ptrack->store_in_grid(d_col, y + row); } - proj.write_grid_row_header(&header, y + row); + proj.select_grid(0); + proj.write_grid_row_header(headers, y + row); + proj.select_grid(1); + proj.write_grid_row_header(headers + 1, y + row); } close(); proj.select_grid(old_grid); diff --git a/avr/cores/megacommand/MCL/MCLClipBoard.h b/avr/cores/megacommand/MCL/MCLClipBoard.h index 416bc3f1a..2075a9b88 100644 --- a/avr/cores/megacommand/MCL/MCLClipBoard.h +++ b/avr/cores/megacommand/MCL/MCLClipBoard.h @@ -6,6 +6,7 @@ #include "SdFat.h" #include "Shared.h" #include "MDSeqTrackData.h" +#include "PerfData.h" #define FILENAME_CLIPBOARD "clipboard.tmp" class MCLClipBoard { @@ -16,22 +17,27 @@ class MCLClipBoard { int t_h; uint8_t copy_track; + bool copy_scene_active; Grid grids[NUM_GRIDS]; MDSeqStep steps[16]; + PerfScene scene; bool init(); bool open(); bool close(); + void copy_scene(PerfScene *s1); + bool paste_scene(PerfScene *s1); + bool copy_sequencer(uint8_t offset = 0); bool copy_sequencer_track(uint8_t track); bool paste_sequencer(uint8_t offset = 0); bool paste_sequencer_track(uint8_t source_track, uint8_t track); - bool copy(uint16_t col, uint16_t row, uint16_t w, uint16_t h, uint8_t grid); - bool paste(uint16_t col, uint16_t row, uint8_t grid); + bool copy(uint8_t col, uint16_t row, uint8_t w, uint16_t h); + bool paste(uint8_t col, uint16_t row); }; diff --git a/avr/cores/megacommand/MCL/MCLEncoder.cpp b/avr/cores/megacommand/MCL/MCLEncoder.cpp index 60f4290d7..440336829 100644 --- a/avr/cores/megacommand/MCL/MCLEncoder.cpp +++ b/avr/cores/megacommand/MCL/MCLEncoder.cpp @@ -3,16 +3,15 @@ int MCLEncoder::update(encoder_t *enc) { int inc = update_rotations(enc); - inc = inc + (pressmode ? 0 : (fastmode ? 4 * enc->button : enc->button)); + inc = inc + (fastmode ? 4 * enc->button : enc->button); cur = limit_value(cur, inc, min, max); - return cur; } int MCLExpEncoder::update(encoder_t *enc) { int inc = update_rotations(enc); - if (!pressmode && fastmode && inc != 0) { + if (fastmode && inc != 0) { int8_t r = 0; while (cur >>= 1) { r++; diff --git a/avr/cores/megacommand/MCL/MCLGUI.cpp b/avr/cores/megacommand/MCL/MCLGUI.cpp index 42ff5eafb..449e28a5d 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.cpp +++ b/avr/cores/megacommand/MCL/MCLGUI.cpp @@ -1,5 +1,5 @@ #include "MCL_impl.h" - +#include "ResourceManager.h" void MCLGUI::put_value_at2(uint8_t value, char *str) { str[0] = (value % 100) / 10 + '0'; @@ -44,8 +44,8 @@ void MCLGUI::draw_textbox(const char *text, const char *text2) { bool MCLGUI::wait_for_input(char *dst, const char *title, uint8_t len) { text_input_page.init(); text_input_page.init_text(dst, title, len); - GUI.pushPage(&text_input_page); - while (GUI.currentPage() == &text_input_page) { + mcl.pushPage(TEXT_INPUT_PAGE); + while (mcl.currentPage() == TEXT_INPUT_PAGE) { GUI.loop(); } m_trim_space(dst); @@ -54,8 +54,8 @@ bool MCLGUI::wait_for_input(char *dst, const char *title, uint8_t len) { bool MCLGUI::wait_for_confirm(const char *title, const char *text) { questiondialog_page.init(title, text); - GUI.pushPage(&questiondialog_page); - while (GUI.currentPage() == &questiondialog_page) { + mcl.pushPage(QUESTIONDIALOG_PAGE); + while (mcl.currentPage() == QUESTIONDIALOG_PAGE) { GUI.loop(); } return questiondialog_page.return_state; @@ -63,8 +63,8 @@ bool MCLGUI::wait_for_confirm(const char *title, const char *text) { void MCLGUI::wait_for_project() { again: - GUI.setPage(&start_menu_page); - while (GUI.currentPage() == &start_menu_page || GUI.currentPage() == &text_input_page || GUI.currentPage() == &load_proj_page) { + mcl.setPage(START_MENU_PAGE); + while (mcl.currentPage() == START_MENU_PAGE || mcl.currentPage() == TEXT_INPUT_PAGE || mcl.currentPage() == LOAD_PROJ_PAGE) { GUI.loop(); } if (!proj.project_loaded) { goto again; } @@ -104,8 +104,13 @@ void MCLGUI::draw_vertical_separator(uint8_t x) { void MCLGUI::draw_vertical_scrollbar(uint8_t x, uint8_t n_items, uint8_t n_window, uint8_t n_current) { - uint8_t length = round(((float)(n_window - 1) / (float)(n_items - 1)) * 32); - uint8_t y = round(((float)(n_current) / (float)(n_items - 1)) * 32); + //uint8_t length = round(((float)(n_window - 1) / (float)(n_items - 1)) * 32); + //uint8_t y = round(((float)(n_current) / (float)(n_items - 1)) * 32); + + uint8_t length = 1 + ((uint16_t) (n_window - 1) * 32) / (n_items - 1); + uint8_t y = (((uint16_t) n_current * 32) / (n_items - 1)); + if (y + length > 32) { length--; } + mcl_gui.draw_vertical_separator(x + 1); oled_display.fillRect(x + 1, y + 1, 3, length - 2, BLACK); oled_display.drawRect(x, y, 5, length, WHITE); @@ -125,9 +130,9 @@ void MCLGUI::draw_knob(uint8_t i, const char *title, const char *text) { draw_text_encoder(x, knob_y0, title, text); } -void MCLGUI::draw_knob(uint8_t i, Encoder *enc, const char *title) { +void MCLGUI::draw_knob(uint8_t i, Encoder *enc, const char *title, bool highlight) { uint8_t x = knob_x0 + i * knob_w; - draw_light_encoder(x + 7, 6, enc, title); + draw_light_encoder(x + 7, 6, enc, title,highlight); } static char title_buf[16]; @@ -143,15 +148,17 @@ void MCLGUI::draw_popup(const char *title, bool deferred_display, uint8_t h) { oled_display.setFont(&TomThumb); // draw menu body - oled_display.fillRect(s_menu_x - 1, s_menu_y - 2, s_menu_w + 2, h + 2, BLACK); - oled_display.drawRect(s_menu_x, s_menu_y, s_menu_w, h, WHITE); - oled_display.fillRect(s_menu_x + 1, s_menu_y - 1, s_menu_w - 2, 5, WHITE); + oled_display.fillRect(s_menu_x - 1, s_menu_y + 1, s_menu_w + 2, h + 4, BLACK); + oled_display.drawRect(s_menu_x, s_menu_y + 2, s_menu_w, h + 2, WHITE); + oled_display.fillRect(s_menu_x + 1, s_menu_y + 3, s_menu_w - 2, 4, WHITE); + oled_display.drawPixel(s_menu_x, s_menu_y + 2, BLACK); + oled_display.drawPixel(s_menu_x + s_menu_w - 1, s_menu_y + 2, BLACK); // draw the title '____/**********\____' part - oled_display.drawRect(s_title_x, s_menu_y - 4, s_title_w, 4, BLACK); - oled_display.fillRect(s_title_x, s_menu_y - 3, s_title_w, 3, WHITE); - oled_display.drawPixel(s_title_x, s_menu_y - 3, BLACK); - oled_display.drawPixel(s_title_x + s_title_w - 1, s_menu_y - 3, BLACK); + oled_display.drawRect(s_title_x, s_menu_y, s_title_w, 2, BLACK); + oled_display.fillRect(s_title_x, s_menu_y + 0, s_title_w, 2, WHITE); + oled_display.drawPixel(s_title_x, s_menu_y + 0, BLACK); + oled_display.drawPixel(s_title_x + s_title_w - 1, s_menu_y, BLACK); oled_display.setTextColor(BLACK); @@ -161,7 +168,7 @@ void MCLGUI::draw_popup(const char *title, bool deferred_display, uint8_t h) { if (title_buf[n] == ' ') { whitespace++; } } len -= whitespace; - oled_display.setCursor(s_title_x + (s_title_w - len * 4) / 2, s_menu_y + 3); + oled_display.setCursor(s_title_x + (s_title_w - len * 4) / 2, s_menu_y + 6); // oled_display.setCursor(s_title_x + 2, s_menu_y + 3); oled_display.println(title_buf); oled_display.setTextColor(WHITE); @@ -252,7 +259,8 @@ void MCLGUI::draw_infobox(const char *line1, const char *line2, oled_display.fillRect(dlg_info_x1 + 1, dlg_info_y1 + 1, dlg_info_w - 2, 6, WHITE); - oled_display.fillCircle(dlg_circle_x, dlg_circle_y, 6, WHITE); + oled_display.fillRect(dlg_circle_x - 4, dlg_circle_y - 4, 9, 9, WHITE); + oled_display.fillRect(dlg_circle_x - 1, dlg_circle_y - 3, 3, 4, BLACK); oled_display.fillRect(dlg_circle_x - 1, dlg_circle_y + 2, 3, 2, BLACK); @@ -270,7 +278,7 @@ void MCLGUI::draw_infobox(const char *line1, const char *line2, oled_display.setFont(oldfont); } -void MCLGUI::draw_encoder(uint8_t x, uint8_t y, uint8_t value) { +void MCLGUI::draw_encoder(uint8_t x, uint8_t y, uint8_t value, bool highlight) { bool vert_flip = false; bool horiz_flip = false; uint8_t image_w = 11; @@ -278,8 +286,9 @@ void MCLGUI::draw_encoder(uint8_t x, uint8_t y, uint8_t value) { // Scale encoder values to 123. encoder animation does not start and stop on // 0. - value = (uint8_t)((float)value * .95); + value = (((uint16_t)value * (uint16_t) 122) / 128); + //value = (uint8_t)((float)value * .95); value += 4; if (value < 32) { @@ -302,35 +311,33 @@ void MCLGUI::draw_encoder(uint8_t x, uint8_t y, uint8_t value) { value = 32 - (value - 96); } + uint8_t *icon = R.icons_knob->encoder_small_0; if (value < 4) { - oled_display.drawBitmap(x, y, encoder_small_0, image_w, image_h, WHITE, - vert_flip, horiz_flip); } else if (value < 9) { - oled_display.drawBitmap(x, y, encoder_small_1, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_1; } else if (value < 14) { - oled_display.drawBitmap(x, y, encoder_small_2, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_2; } else if (value < 19) { - oled_display.drawBitmap(x, y, encoder_small_3, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_3; } else if (value < 24) { - oled_display.drawBitmap(x, y, encoder_small_4, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_4; } else if (value < 30) { - oled_display.drawBitmap(x, y, encoder_small_5, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_5; } else { - oled_display.drawBitmap(x, y, encoder_small_6, image_w, image_h, WHITE, - vert_flip, horiz_flip); + icon = R.icons_knob->encoder_small_6; } + + oled_display.drawBitmap(x, y, icon, image_w, image_h, WHITE, + vert_flip, horiz_flip); + + if (highlight) { oled_display.fillRect(x, y,11,11,INVERT); } } void MCLGUI::draw_encoder(uint8_t x, uint8_t y, Encoder *encoder) { draw_encoder(x, y, encoder->cur); } -bool MCLGUI::show_encoder_value(Encoder *encoder) { +bool MCLGUI::show_encoder_value(Encoder *encoder, int timeout) { uint8_t match = 255; for (uint8_t i = 0; i < GUI_NUM_ENCODERS && match == 255; i++) { @@ -341,11 +348,11 @@ bool MCLGUI::show_encoder_value(Encoder *encoder) { if (match != 255) { if (clock_diff(((LightPage *)GUI.currentPage())->encoders_used_clock[match], - slowclock) < SHOW_VALUE_TIMEOUT) { + slowclock) < timeout || BUTTON_DOWN(Buttons.ENCODER1 + match)) { return true; } else { ((LightPage *)GUI.currentPage())->encoders_used_clock[match] = - slowclock - SHOW_VALUE_TIMEOUT - 1; + slowclock + timeout + 1; } } @@ -412,14 +419,13 @@ void MCLGUI::draw_md_encoder(uint8_t x, uint8_t y, uint8_t value, oled_display.setFont(oldfont); } -void MCLGUI::draw_light_encoder(uint8_t x, uint8_t y, Encoder *encoder, - const char *name) { +void MCLGUI::draw_light_encoder(uint8_t x, uint8_t y, Encoder *encoder, const char *name, bool highlight) { bool show_value = show_encoder_value(encoder); - draw_light_encoder(x, y, encoder->cur, name, show_value); + draw_light_encoder(x, y, encoder->cur, name, highlight, show_value); } void MCLGUI::draw_light_encoder(uint8_t x, uint8_t y, uint8_t value, - const char *name, bool show_value) { + const char *name, bool highlight, bool show_value) { auto oldfont = oled_display.getFont(); oled_display.setFont(&TomThumb); @@ -449,6 +455,7 @@ void MCLGUI::draw_light_encoder(uint8_t x, uint8_t y, uint8_t value, y += 2; draw_encoder(x, y, value); + if (highlight) { oled_display.fillRect(x - 2, 0, 15,20,INVERT); } oled_display.setFont(oldfont); } @@ -460,27 +467,28 @@ void MCLGUI::draw_microtiming(uint8_t speed, uint8_t timing) { oled_display.setTextColor(WHITE); SeqTrack seq_track; uint8_t timing_mid = seq_track.get_timing_mid(speed); - uint8_t heights_len; uint8_t degrees = timing_mid * 2; uint8_t heights[16]; // Triplets + + uint8_t heights_lowres[6] = {11, 4, 6, 10, 4, 8}; + uint8_t heights_triplets[16] = {11, 2, 4, 8, 6, 10, 6, 2, + 10, 2, 6, 8, 10, 4, 6, 2}; + uint8_t heights_triplets2[8] = {11, 4, 8, 10, 2, 8, 4, 2}; + uint8_t heights_highres[12] = {11, 2, 4, 8, 6, 2, 10, 2, 6, 8, 4, 2}; + + uint8_t *h = heights_highres; + uint8_t heights_len = 12; + if (speed == SEQ_SPEED_2X) { - uint8_t heights_lowres[6] = {11, 4, 6, 10, 4, 8}; - memcpy(&heights, &heights_lowres, 6); + h = heights_lowres; heights_len = 6; } else if (speed == SEQ_SPEED_3_4X) { - uint8_t heights_triplets[16] = {11, 2, 4, 8, 6, 10, 6, 2, - 10, 2, 6, 8, 10, 4, 6, 2}; - memcpy(&heights, &heights_triplets, 16); + h = heights_triplets; heights_len = 16; } else if (speed == SEQ_SPEED_3_2X) { - uint8_t heights_triplets2[8] = {11, 4, 8, 10, 2, 8, 4, 2}; - memcpy(&heights, &heights_triplets2, 8); + h = heights_triplets2; heights_len = 8; - } else { - uint8_t heights_highres[12] = {11, 2, 4, 8, 6, 2, 10, 2, 6, 8, 4, 2}; - memcpy(&heights, &heights_highres, 12); - heights_len = 12; } uint8_t y_pos = 11; uint8_t a = 0; @@ -508,18 +516,18 @@ void MCLGUI::draw_microtiming(uint8_t speed, uint8_t timing) { oled_display.drawRect(8 + 1, 1 + 1, 128 - 16 - 2, 32 - 2 - 2, WHITE); oled_display.setCursor(x_pos + 34, 10); - oled_display.print("uTIMING: "); + oled_display.print(F("uTIMING: ")); oled_display.print(K); - oled_display.drawLine(x, y_pos + heights[0], x + w, y_pos + heights[0], + oled_display.drawLine(x, y_pos + h[0], x + w, y_pos + h[0], WHITE); for (uint8_t n = 0; n <= degrees; n++) { - oled_display.drawLine(x, y_pos + heights[0], x, - y_pos + heights[0] - heights[a], WHITE); + oled_display.drawLine(x, y_pos + h[0], x, + y_pos + h[0] - h[a], WHITE); a++; if (n == timing) { - oled_display.fillRect(x - 1, y_pos + heights[0] + 3, 3, 3, WHITE); - oled_display.drawPixel(x, y_pos + heights[0] + 2, WHITE); + oled_display.fillRect(x - 1, y_pos + h[0] + 3, 3, 3, WHITE); + oled_display.drawPixel(x, y_pos + h[0] + 2, WHITE); } if (a == heights_len) { @@ -601,7 +609,7 @@ void MCLGUI::draw_keyboard(uint8_t x, uint8_t y, uint8_t note_width, } void MCLGUI::draw_trigs(uint8_t x, uint8_t y, const uint16_t &trig_selection) { - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (IS_BIT_SET16(trig_selection,i)) { oled_display.fillRect(x, y, seq_w, trig_h, WHITE); } @@ -617,7 +625,7 @@ void MCLGUI::draw_trigs(uint8_t x, uint8_t y, uint8_t offset, const uint64_t &pattern_mask, uint8_t step_count, uint8_t length, const uint64_t &mute_mask, const uint64_t &slide_mask) { - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { uint8_t idx = i + offset; bool in_range = idx < length; @@ -650,49 +658,90 @@ void MCLGUI::draw_trigs(uint8_t x, uint8_t y, uint8_t offset, } } -void MCLGUI::draw_track_type_select(uint8_t x, uint8_t y, - uint8_t track_type_select) { +void MCLGUI::draw_track_type_select(uint8_t track_type_select) { char dev[6]; MidiDevice *devs[2] = { midi_active_peering.get_device(UART1_PORT), midi_active_peering.get_device(UART2_PORT), }; +// oled_display.clearDisplay(); - for (uint8_t i = 0; i < 4; i++) { + uint8_t x = 0; + //oled_display.fillRect(0, 0, 128, 7, WHITE); + oled_display.fillRect(s_title_x + 10, 0, 50, 7, WHITE); + oled_display.setCursor(s_title_x + (s_title_w - 12 * 4) / 2 + 2, 6); + // oled_display.setCursor(s_title_x + 2, s_menu_y + 3); + oled_display.setTextColor(BLACK); + oled_display.println("GROUP SELECT"); + + oled_display.fillRect(0, 8, 128, 23, BLACK); + MCLGIF *gif; + + for (uint8_t i = 0; i < 5; i++) { + + bool select = IS_BIT_SET(track_type_select, i); + + uint8_t *icon = nullptr; + uint8_t offset = 3; + int8_t y_offset = 0; switch (i) { case 0: - strcpy(dev, devs[0]->name); + icon = devs[0]->gif_data(); + gif = devs[0]->gif(); + gif->set_bmp(icon); break; case 1: - if (devs[1] != nullptr) { - strcpy(dev, devs[1]->name); - } else { - strcpy(dev, "MI"); - } + icon = devs[1]->gif_data(); + gif = devs[1]->gif(); + gif->set_bmp(icon); + offset = 4; break; case 2: - strcpy(dev, "FX"); + gif = R.icons_logo->perf_gif; + gif->set_bmp(R.icons_logo->perf_gif_data); + offset = 3; break; case 3: - strcpy(dev, "TEMPO"); + gif = R.icons_logo->route_gif; + gif->set_bmp(R.icons_logo->route_gif_data); + offset = 5; + break; + case 4: + gif = R.icons_logo->metronome_gif; + gif->set_bmp(R.icons_logo->metronome_gif_data); + offset = 4; + y_offset = -3; break; } - oled_display.setCursor(x, y); - oled_display.print(dev); - if (IS_BIT_SET(track_type_select, i)) { - oled_display.fillRect(x, y + 4, seq_w, trig_h, WHITE); + //icon = select ? gif->get_frame(0) : gif->get_next_frame(); + icon = gif->get_next_frame(); + + if (icon) { oled_display.drawBitmap(x + offset, 15 + y_offset, icon, gif->w, gif->h, WHITE); } + + if (note_interface.is_note_on(i)) { gif->reset(); } + + if (select) { + // gif->reset(); + oled_display.fillRect(x, 9, 24, 21, INVERT); + + oled_display.drawRect(x + 1, 10, 22, 19, BLACK); } else { - oled_display.drawRect(x, y + 4, seq_w, trig_h, WHITE); + oled_display.drawRect(x, 9, 24, 21, WHITE); } - x += 16; + oled_display.drawPixel(x,9,!select); + oled_display.drawPixel(x + 23,9,!select); + oled_display.drawPixel(x,9 + 20,!select); + oled_display.drawPixel(x + 23,9 + 20,!select); + + x += 26; } } void MCLGUI::draw_leds(uint8_t x, uint8_t y, uint8_t offset, const uint64_t &lock_mask, uint8_t step_count, uint8_t length, bool show_current_step) { - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { uint8_t idx = i + offset; bool in_range = idx < length; @@ -718,24 +767,27 @@ void MCLGUI::draw_leds(uint8_t x, uint8_t y, uint8_t offset, void MCLGUI::draw_panel_toggle(const char *s1, const char *s2, bool s1_active) { oled_display.setFont(&TomThumb); + + oled_display.setCursor(pane_label_x + 1, pane_label_md_y + 6); if (s1_active) { oled_display.fillRect(pane_label_x, pane_label_md_y, pane_label_w, pane_label_h, WHITE); - oled_display.setCursor(pane_label_x + 1, pane_label_md_y + 6); oled_display.setTextColor(BLACK); oled_display.print(s1); oled_display.setTextColor(WHITE); } else { - oled_display.setCursor(pane_label_x + 1, pane_label_md_y + 6); oled_display.setTextColor(WHITE); oled_display.print(s1); oled_display.fillRect(pane_label_x, pane_label_ex_y, pane_label_w, pane_label_h, WHITE); oled_display.setTextColor(BLACK); } - oled_display.setCursor(pane_label_x + 1, pane_label_ex_y + 6); - oled_display.print(s2); - oled_display.setTextColor(WHITE); + + if (mcl.currentPage() == SEQ_PTC_PAGE || mcl.currentPage() == LFO_PAGE) { + oled_display.setCursor(pane_label_x + 1, pane_label_ex_y + 6); + oled_display.print(s2); + oled_display.setTextColor(WHITE); + } } void MCLGUI::draw_panel_labels(const char *info1, const char *info2) { @@ -784,56 +836,4 @@ void MCLGUI::draw_panel_number(uint8_t number) { oled_display.print(number); } -// ================ SPRITES ================ - -const unsigned char encoder_small_0[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, - 0x20, 0x80, 0x20, 0x4e, 0x40, 0x4e, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder1', 11x11px -const unsigned char encoder_small_1[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, - 0x20, 0x80, 0x20, 0x5c, 0x40, 0x4c, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder2', 11x11px -const unsigned char encoder_small_2[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, - 0x20, 0x90, 0x20, 0x58, 0x40, 0x48, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder3', 11x11px -const unsigned char encoder_small_3[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0x80, - 0x20, 0xb0, 0x20, 0x58, 0x40, 0x40, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder4', 11x11px -const unsigned char encoder_small_4[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0xb0, - 0x20, 0xb0, 0x20, 0x58, 0x40, 0x40, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder5', 11x11px -const unsigned char encoder_small_5[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x20, 0xb0, - 0x20, 0xb0, 0x20, 0x50, 0x40, 0x40, 0x40, 0x31, 0x80, 0x0e, 0x00}; -// 'encoder6', 11x11px -const unsigned char encoder_small_6[] PROGMEM = { - 0x0e, 0x00, 0x31, 0x80, 0x40, 0x40, 0x40, 0x40, 0xb0, 0x20, 0xb0, - 0x20, 0xb0, 0x20, 0x40, 0x40, 0x40, 0x40, 0x31, 0x80, 0x0e, 0x00}; - -// 'wheel1', 19x19px -const unsigned char wheel_top[] PROGMEM = { - 0x03, 0xf8, 0x00, 0x0e, 0x0e, 0x00, 0x1e, 0x0f, 0x00, 0x3e, 0x0f, 0x80, - 0x7f, 0x1f, 0xc0, 0x7f, 0x1f, 0xc0, 0xff, 0xbf, 0xe0, 0xff, 0xff, 0xe0, - 0xff, 0xbf, 0xe0, 0xff, 0x5f, 0xe0, 0xff, 0xbf, 0xe0, 0xf8, 0xe3, 0xe0, - 0x60, 0xe0, 0xe0, 0x40, 0xe0, 0x40, 0x61, 0xf0, 0xc0, 0x31, 0xf1, 0x80, - 0x1b, 0xf7, 0x00, 0x0f, 0xfe, 0x00, 0x03, 0xf8, 0x00}; -// 'wheel2', 19x19px -const unsigned char wheel_angle[] PROGMEM = { - 0x03, 0xf8, 0x00, 0x0f, 0xfe, 0x00, 0x1f, 0xfb, 0x00, 0x3f, 0xf1, 0x80, - 0x7f, 0xf0, 0xc0, 0x7f, 0xe0, 0x40, 0xff, 0xe0, 0xe0, 0x8f, 0xe3, 0xe0, - 0x83, 0xbf, 0xe0, 0x81, 0x5f, 0xe0, 0x83, 0xbf, 0xe0, 0x8f, 0xff, 0xe0, - 0xff, 0xbf, 0xe0, 0x7f, 0x1f, 0xc0, 0x7f, 0x1f, 0xc0, 0x3e, 0x0f, 0x80, - 0x1e, 0x0f, 0x00, 0x0e, 0x0e, 0x00, 0x03, 0xf8, 0x00}; -// 'wheel3', 19x19px -const unsigned char wheel_side[] PROGMEM = { - 0x03, 0xf8, 0x00, 0x0f, 0xfe, 0x00, 0x1b, 0xff, 0x00, 0x31, 0xff, 0x80, - 0x61, 0xff, 0xc0, 0x40, 0xff, 0xc0, 0xe0, 0xff, 0xe0, 0xf8, 0xfe, 0x20, - 0xff, 0xb8, 0x20, 0xff, 0x50, 0x20, 0xff, 0xb8, 0x20, 0xf8, 0xfe, 0x20, - 0xe0, 0xff, 0xe0, 0x40, 0xff, 0xc0, 0x61, 0xff, 0xc0, 0x31, 0xff, 0x80, - 0x1b, 0xff, 0x00, 0x0f, 0xfe, 0x00, 0x03, 0xf8, 0x00}; - MCLGUI mcl_gui; diff --git a/avr/cores/megacommand/MCL/MCLGUI.h b/avr/cores/megacommand/MCL/MCLGUI.h index e417af4a4..310be7c42 100644 --- a/avr/cores/megacommand/MCL/MCLGUI.h +++ b/avr/cores/megacommand/MCL/MCLGUI.h @@ -6,10 +6,25 @@ #include "QuestionDialogPage.h" #include "TextInputPage.h" -#define SHOW_VALUE_TIMEOUT 2000 - +//class MCLGUI : public Print { class MCLGUI { public: + + /* + * Print child implementation: + * + char str_print[30]; + bool str_offset = 0; + size_t write(uint8_t c) { }; + size_t write(const uint8_t *buffer, size_t size) { + uint8_t s = min(sizeof(str_print),size); + strncpy(str_print, buffer + str_offset, s); + str_offset += s; + } + + void print_str() { oled_display.print(str_print); str_offset = 0; } + */ + uint8_t s_progress_cookie = 0b00110011; uint8_t s_progress_count = 0; @@ -50,10 +65,10 @@ class MCLGUI { void clear_leftpane(); void clear_rightpane(); - void draw_encoder(uint8_t x, uint8_t y, uint8_t value); + void draw_encoder(uint8_t x, uint8_t y, uint8_t value, bool highlight = false); void draw_encoder(uint8_t x, uint8_t y, Encoder *encoder); - bool show_encoder_value(Encoder *encoder); + bool show_encoder_value(Encoder *encoder, int timeout = SHOW_VALUE_TIMEOUT); void draw_text_encoder(uint8_t x, uint8_t y, const char *name, const char *value); @@ -62,9 +77,9 @@ class MCLGUI { void draw_md_encoder(uint8_t x, uint8_t y, uint8_t value, const char *name, bool show_value); void draw_light_encoder(uint8_t x, uint8_t y, Encoder *encoder, - const char *name); - void draw_light_encoder(uint8_t x, uint8_t y, uint8_t value, const char *name, - bool show_value); + const char *name, bool highlight = false); + void draw_light_encoder(uint8_t x, uint8_t y, uint8_t value, const char *name, bool highlight = false, + bool show_value = false); void draw_keyboard(uint8_t x, uint8_t y, uint8_t note_width, uint8_t note_height, uint8_t num_of_notes, uint64_t *note_mask); @@ -73,7 +88,7 @@ class MCLGUI { void draw_leds(uint8_t x, uint8_t y, uint8_t offset, const uint64_t &lock_mask, uint8_t step_count, uint8_t length, bool show_current_step); - void draw_track_type_select(uint8_t x, uint8_t y, uint8_t track_type_select); + void draw_track_type_select(uint8_t track_type_select); void draw_panel_toggle(const char *s1, const char *s2, bool s1_active); void draw_panel_labels(const char *info1, const char *info2); @@ -82,23 +97,16 @@ class MCLGUI { void draw_knob_frame(); void draw_knob(uint8_t i, const char *title, const char *text); - void draw_knob(uint8_t i, Encoder *enc, const char *name); - - void init_encoders_used_clock() { + void draw_knob(uint8_t i, Encoder *enc, const char *name, bool highlight = false); - for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { - ((LightPage *)GUI.currentPage())->encoders_used_clock[n] = - slowclock - SHOW_VALUE_TIMEOUT - 1; - } - } static constexpr uint8_t seq_w = 5; static constexpr uint8_t led_h = 3; static constexpr uint8_t trig_h = 5; static constexpr uint8_t s_menu_w = 104; - static constexpr uint8_t s_menu_h = 24; + static constexpr uint8_t s_menu_h = 27; static constexpr uint8_t s_menu_x = (128 - s_menu_w) / 2; - static constexpr uint8_t s_menu_y = (32 - s_menu_h) / 2; + static constexpr uint8_t s_menu_y = 0; static constexpr uint8_t s_title_x = 31; static constexpr uint8_t s_title_w = 64; diff --git a/avr/cores/megacommand/MCL/MCLGfx.cpp b/avr/cores/megacommand/MCL/MCLGfx.cpp index 383a751a8..572733182 100644 --- a/avr/cores/megacommand/MCL/MCLGfx.cpp +++ b/avr/cores/megacommand/MCL/MCLGfx.cpp @@ -1,4 +1,5 @@ #include "MCL_impl.h" +#include "ResourceManager.h" void MCLGfx::init_oled() { oled_display.begin(); @@ -27,19 +28,16 @@ void MCLGfx::draw_evil(unsigned char* evil) { oled_display.setCursor(x - 60, 20); oled_display.println("MACHINE IS O.K."); - oled_display.drawBitmap(x, 0, evil, 45, 32, BLACK); + oled_display.drawBitmap(x, 1, evil, 33, 31, BLACK); oled_display.display(); } - delay(1000); + delay(2000); oled_display.setTextColor(WHITE, BLACK); oled_display.setFont(oldfont); } void MCLGfx::splashscreen(unsigned char* bitmap) { oled_display.setFont(); - oled_display.setTextSize(2); - oled_display.setTextColor(WHITE, BLACK); - oled_display.setCursor(40, 0); oled_display.drawBitmap(35, 8, bitmap, BITMAP_MCL_LOGO_W, BITMAP_MCL_LOGO_H, WHITE); @@ -49,7 +47,7 @@ void MCLGfx::splashscreen(unsigned char* bitmap) { */ oled_display.setCursor(90, 8); oled_display.setTextSize(1); - oled_display.print("V"); + oled_display.print(F("V")); oled_display.print(VERSION_STR); /* for (float length = 0; length < 32; length += 0.7) { diff --git a/avr/cores/megacommand/MCL/MCLGfx.h b/avr/cores/megacommand/MCL/MCLGfx.h index 69b60f134..0141e761a 100644 --- a/avr/cores/megacommand/MCL/MCLGfx.h +++ b/avr/cores/megacommand/MCL/MCLGfx.h @@ -3,14 +3,82 @@ #ifndef MCLGFX_H__ #define MCLGFX_H__ +enum MCLGIFDir { + DIR_FWD, + DIR_FWDBACK, +}; + + +class MCLGIF { +public: + uint8_t frame_offset_bytes; + uint8_t num_of_frames; + uint8_t w; + uint8_t h; + MCLGIFDir dir; + uint8_t loops; + +// MCLGIF(uint8_t b, uint8_t n, uint8_t w_, uint8_t h_, MCLGIFDir d, uint8_t l) : frame_offset_bytes(b), num_of_frames(n), w(w_), h(h_), dir(d),loops(l) { } + +//private: + + uint8_t loop_count; + int8_t cur_frame; + int8_t inc; + uint16_t last_frame_clock; + uint8_t *bitmap; + void reset() { + if (inc == 0) { + inc = 1; + cur_frame = 0; + } + loop_count = 0; + } + + void set_bmp(uint8_t *bmp) { bitmap = bmp; } + + uint8_t *get_frame(uint8_t n) { + uint16_t index = frame_offset_bytes * n; + return &bitmap[index]; + } + + uint8_t *get_current_frame() { + uint8_t *bmp = get_frame(cur_frame); + return bmp; + } + + uint8_t *get_next_frame() { + uint8_t *bmp = get_frame(cur_frame); + if (clock_diff(last_frame_clock,slowclock) < 80 || loop_count == loops) { return bmp; } + last_frame_clock = slowclock; + cur_frame += inc; + + if (cur_frame < 0) { + cur_frame = 0; + inc = 1; + loop_count++; + } + + if (cur_frame == num_of_frames) { + if (dir == DIR_FWD) { + loop_count++; + cur_frame = 0; + } + if (dir == DIR_FWDBACK) { + cur_frame -= 2; + inc = -1; + } + } + return bmp; + } +}; class MCLGfx { - public: - void draw_evil(unsigned char* bitmap); - void splashscreen(unsigned char* bitmap); +public: + void draw_evil(unsigned char *bitmap); + void splashscreen(unsigned char *bitmap); void init_oled(); void alert(const char *str1, const char *str2); - }; extern MCLGfx gfx; diff --git a/avr/cores/megacommand/MCL/MCLMemory.h b/avr/cores/megacommand/MCL/MCLMemory.h index 8866cdc0c..847d142d0 100644 --- a/avr/cores/megacommand/MCL/MCLMemory.h +++ b/avr/cores/megacommand/MCL/MCLMemory.h @@ -12,6 +12,8 @@ constexpr size_t GRID_WIDTH = 16; constexpr size_t GRID_LENGTH = 128; constexpr size_t GRID_SLOT_BYTES = 4096; +constexpr size_t PRJ_NAME_LEN = 14; + constexpr size_t NUM_SLOTS = GRID_WIDTH * NUM_GRIDS; constexpr size_t NUM_MD_TRACKS = 16; @@ -35,7 +37,8 @@ constexpr size_t NUM_INSTRUMENT_TRACKS = (NUM_MD_TRACKS + NUM_EXT_TRACKS); constexpr size_t NUM_AUX_TRACKS = 4; -constexpr size_t GRIDCHAIN_TRACK_NUM = 11; +constexpr size_t GRIDCHAIN_TRACK_NUM = 10; +constexpr size_t PERF_TRACK_NUM = 11; constexpr size_t MDFX_TRACK_NUM = 12; //position of MDFX track in grid constexpr size_t MDLFO_TRACK_NUM = 13; //position of MDLFO track in grid constexpr size_t MDROUTE_TRACK_NUM = 14; //position of MDROUTE track in grid @@ -43,6 +46,9 @@ constexpr size_t MDTEMPO_TRACK_NUM = 15; //position of MDTEMPO track in grid constexpr size_t NUM_LFO_TRACKS = 1; +constexpr size_t NUM_PERF_PARAMS = 16; +constexpr size_t NUM_SCENES = 8; + // as of commit 33e243afc758081dc6eb244e42ae61e1e0de09c0 // the track sizes are: // GridTrack 7 @@ -68,6 +74,7 @@ constexpr size_t MDLFO_TRACK_LEN = 226; constexpr size_t MDROUTE_TRACK_LEN = 25; constexpr size_t MDFX_TRACK_LEN = 43; constexpr size_t MDTEMPO_TRACK_LEN = 11; +constexpr size_t PERF_TRACK_LEN = 491; constexpr size_t GRIDCHAIN_TRACK_LEN = 551; //Use these to produce compiler errors that probes the sizes! @@ -90,17 +97,18 @@ constexpr size_t BANK1_AUX_TRACKS_START = BANK1_MD_TRACKS_START + GRID1_TRACK_LE // AUX Tracks constexpr size_t BANK1_GRIDCHAIN_TRACK_START = BANK1_AUX_TRACKS_START; -constexpr size_t BANK1_MDLFO_TRACK_START = BANK1_GRIDCHAIN_TRACK_START + GRIDCHAIN_TRACK_LEN; +constexpr size_t BANK1_PERF_TRACK_START = BANK1_GRIDCHAIN_TRACK_START + GRIDCHAIN_TRACK_LEN; +constexpr size_t BANK1_MDLFO_TRACK_START = BANK1_PERF_TRACK_START + PERF_TRACK_LEN; constexpr size_t BANK1_MDROUTE_TRACK_START = BANK1_MDLFO_TRACK_START + MDLFO_TRACK_LEN; constexpr size_t BANK1_MDFX_TRACK_START = BANK1_MDROUTE_TRACK_START + MDROUTE_TRACK_LEN; constexpr size_t BANK1_MDTEMPO_TRACK_START = BANK1_MDFX_TRACK_START + MDFX_TRACK_LEN; // 6x A4 tracks -constexpr size_t BANK1_A4_TRACKS_START = BANK1_MDTEMPO_TRACK_START + MDTEMPO_TRACK_LEN; +constexpr size_t BANK1_A4_TRACKS_START = BANK1_MDTEMPO_TRACK_START + MDTEMPO_TRACK_LEN;; // 512x file entries (16 bytes each), stored in Bank3 -constexpr size_t NUM_FILE_ENTRIES = 512; -constexpr size_t FILE_ENTRY_SIZE = 16; -constexpr size_t BANK1_FILE_ENTRIES_START = 0x0000; -constexpr size_t BANK1_FILE_ENTRIES_END = 0x6000; +constexpr size_t NUM_FILE_ENTRIES = 256; +constexpr size_t FILE_ENTRY_SIZE = 32; +constexpr size_t BANK3_FILE_ENTRIES_START = 0x0000; +constexpr size_t BANK3_FILE_ENTRIES_END = 0x2000; // At 0xCAF4 diff --git a/avr/cores/megacommand/MCL/MCLMenus.cpp b/avr/cores/megacommand/MCL/MCLMenus.cpp index 96a950723..442cf6b83 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.cpp +++ b/avr/cores/megacommand/MCL/MCLMenus.cpp @@ -28,42 +28,6 @@ uint8_t opt_import_count = 16; void new_proj_handler() { proj.new_project_prompt(); } -const Page *const menu_target_pages[] PROGMEM = { - nullptr, - - // 1 - load_proj_page - (Page *)&load_proj_page, - (Page *)nullptr, - //(Page *)&convert_proj_page, - (Page *)&midi_config_page, - (Page *)&md_config_page, - (Page *)&chain_config_page, - (Page *)&aux_config_page, - - // 7 - (Page *)&mcl_config_page, - - // 8 - ram_config_page - (Page *)&ram_config_page, - - // 9 - (Page *)&poly_page, - // 10 - (Page *)&arp_page, - // 11 - (Page *)&md_import_page, - // 12 - (Page *)&midiport_menu_page, - // 13 - (Page *)&midiprogram_menu_page, - // 14 - (Page *)&midiclock_menu_page, - // 15 - (Page *)&midiroute_menu_page, - // 16 - (Page *)&midimachinedrum_menu_page -}; - const uint8_t *const menu_target_param[] PROGMEM = { nullptr, @@ -90,7 +54,7 @@ const uint8_t *const menu_target_param[] PROGMEM = { &opt_copy, &opt_clear, &opt_paste, &opt_shift, &opt_reverse, // 30 - &opt_clear_step, + &mcl_cfg.rec_automation, // 31 &grid_page.grid_select_apply, &mcl_cfg.load_mode, &slot.link.loops, @@ -116,7 +80,7 @@ const uint8_t *const menu_target_param[] PROGMEM = { // 49 &mcl_cfg.uart2_prg_mode, // 50 - &grid_page.insert_rows, + &mcl_cfg.seq_dev, // 51 &mcl_cfg.midi_forward_2, // 52 @@ -130,7 +94,11 @@ const uint8_t *const menu_target_param[] PROGMEM = { // 56 &mcl_cfg.midi_ctrl_port, // 57 - &mcl_cfg.md_trig_channel + &mcl_cfg.md_trig_channel, + // 58 + &perf_page.page_mode, + // 59 + &perf_page.perf_id, }; const menu_function_t menu_target_functions[] PROGMEM = { @@ -154,12 +122,12 @@ const menu_function_t menu_target_functions[] PROGMEM = { // 14 seq_menu_handler, // 15 - opt_clear_step_locks_handler, - opt_copy_step_handler_cb, - opt_paste_step_handler, - opt_mute_step_handler, + nullptr, + nullptr, + nullptr, + nullptr, // 19 - step_menu_handler, + nullptr, // 20 rename_row, // 21 @@ -187,26 +155,27 @@ const menu_function_t menu_target_functions[] PROGMEM = { usb_disk_mode, // 29 mcl_setup, + // 30 + rename_perf, }; +MenuPage aux_config_page(&config_param1, &config_param6); -MenuPage<1> aux_config_page(&config_param1, &config_param6); - -MenuPage<4> boot_menu_page(&options_param1, &options_param2); -MenuPage<2> start_menu_page(&options_param1, &options_param2); -MenuPage<6> system_page(&options_param1, &options_param2); -MenuPage<5> midi_config_page(&config_param1, &config_param3); +MenuPage boot_menu_page(&options_param1, &options_param2); +MenuPage start_menu_page(&options_param1, &options_param2); +MenuPage system_page(&options_param1, &options_param2); +MenuPage midi_config_page(&config_param1, &config_param3); -MenuPage<3> md_config_page(&config_param1, &config_param4); -MenuPage<3> chain_config_page(&config_param1, &config_param6); -MenuPage<1> mcl_config_page(&config_param1, &config_param5); -MenuPage<1> ram_config_page(&config_param1, &config_param7); -MenuPage<4> md_import_page(&config_param1, &config_param8); +MenuPage md_config_page(&config_param1, &config_param4); +MenuPage chain_config_page(&config_param1, &config_param6); +MenuPage mcl_config_page(&config_param1, &config_param5); +MenuPage ram_config_page(&config_param1, &config_param7); +MenuPage md_import_page(&config_param1, &config_param8); -MenuPage<5> midiport_menu_page(&config_param1, &config_param9); -MenuPage<3> midiprogram_menu_page(&config_param1, &config_param10); -MenuPage<4> midiclock_menu_page(&config_param1, &config_param11); -MenuPage<4> midiroute_menu_page(&config_param1, &config_param12); -MenuPage<3> midimachinedrum_menu_page(&config_param1, &config_param13); +MenuPage midiport_menu_page(&config_param1, &config_param9); +MenuPage midiprogram_menu_page(&config_param1, &config_param10); +MenuPage midiclock_menu_page(&config_param1, &config_param11); +MenuPage midiroute_menu_page(&config_param1, &config_param12); +MenuPage midimachinedrum_menu_page(&config_param1, &config_param13); MCLEncoder input_encoder1(0, 127, ENCODER_RES_SYS); MCLEncoder input_encoder2(0, 127, ENCODER_RES_SYS); @@ -214,15 +183,12 @@ MCLEncoder input_encoder2(0, 127, ENCODER_RES_SYS); TextInputPage text_input_page(&input_encoder1, &input_encoder2); MCLEncoder file_menu_encoder(0, 4, ENCODER_RES_PAT); -MenuPage<7> file_menu_page(&config_param1, &file_menu_encoder); +MenuPage file_menu_page(&config_param1, &file_menu_encoder); MCLEncoder seq_menu_value_encoder(0, 16, ENCODER_RES_PAT); MCLEncoder seq_menu_entry_encoder(0, 9, ENCODER_RES_PAT); -MenuPage<20> seq_menu_page(&seq_menu_value_encoder, &seq_menu_entry_encoder); - -MCLEncoder step_menu_value_encoder(0, 16, ENCODER_RES_PAT); -MCLEncoder step_menu_entry_encoder(0, 9, ENCODER_RES_PAT); -MenuPage<4> step_menu_page(&step_menu_value_encoder, &step_menu_entry_encoder); +MenuPage seq_menu_page(&seq_menu_value_encoder, &seq_menu_entry_encoder); +MenuPage perf_menu_page(&seq_menu_value_encoder, &seq_menu_entry_encoder); MCLEncoder grid_slot_param1(0, 7, ENCODER_RES_PAT); MCLEncoder grid_slot_param2(0, 16, ENCODER_RES_PAT); @@ -230,4 +196,6 @@ MenuPage grid_slot_page(&grid_slot_param1, &grid_slot_param2); MCLEncoder wavdesign_menu_value_encoder(0, 16, ENCODER_RES_PAT); MCLEncoder wavdesign_menu_entry_encoder(0, 4, ENCODER_RES_PAT); -MenuPage<3> wavdesign_menu_page(&wavdesign_menu_value_encoder, &wavdesign_menu_entry_encoder); +MenuPage wavdesign_menu_page(&wavdesign_menu_value_encoder, &wavdesign_menu_entry_encoder); + + diff --git a/avr/cores/megacommand/MCL/MCLMenus.h b/avr/cores/megacommand/MCL/MCLMenus.h index 8425d5654..fc25de8cb 100644 --- a/avr/cores/megacommand/MCL/MCLMenus.h +++ b/avr/cores/megacommand/MCL/MCLMenus.h @@ -33,22 +33,50 @@ extern MCLEncoder config_param13; extern void new_proj_handler(); -extern MenuPage<4> boot_menu_page; -extern MenuPage<2> start_menu_page; -extern MenuPage<6> system_page; -extern MenuPage<5> midi_config_page; -extern MenuPage<3> md_config_page; -extern MenuPage<1> mcl_config_page; -extern MenuPage<3> chain_config_page; -extern MenuPage<1> aux_config_page; -extern MenuPage<1> ram_config_page; -extern MenuPage<4> md_import_page; - -extern MenuPage<5> midiport_menu_page; -extern MenuPage<3> midiprogram_menu_page; -extern MenuPage<4> midiclock_menu_page; -extern MenuPage<4> midiroute_menu_page; -extern MenuPage<3> midimachinedrum_menu_page; +constexpr size_t boot_menu_page_N = 4; +extern MenuPage boot_menu_page; + +constexpr size_t start_menu_page_N = 2; +extern MenuPage start_menu_page; + +constexpr size_t system_menu_page_N = 6; +extern MenuPage system_page; + +constexpr size_t midi_config_page_N = 5; +extern MenuPage midi_config_page; + +constexpr size_t md_config_page_N = 2; +extern MenuPage md_config_page; + +constexpr size_t mcl_config_page_N = 1; +extern MenuPage mcl_config_page; + +constexpr size_t chain_config_page_N = 3; +extern MenuPage chain_config_page; + +constexpr size_t aux_config_page_N = 1; +extern MenuPage aux_config_page; + +constexpr size_t ram_config_page_N = 1; +extern MenuPage ram_config_page; + +constexpr size_t md_import_page_N = 4; +extern MenuPage md_import_page; + +constexpr size_t midiport_menu_page_N = 5; +extern MenuPage midiport_menu_page; + +constexpr size_t midiprogram_menu_page_N = 3; +extern MenuPage midiprogram_menu_page; + +constexpr size_t midiclock_menu_page_N = 4; +extern MenuPage midiclock_menu_page; + +constexpr size_t midiroute_menu_page_N = 4; +extern MenuPage midiroute_menu_page; + +constexpr size_t midimachinedrum_menu_page_N = 3; +extern MenuPage midimachinedrum_menu_page; extern MCLEncoder input_encoder1; extern MCLEncoder input_encoder2; @@ -56,25 +84,30 @@ extern MCLEncoder input_encoder2; extern TextInputPage text_input_page; extern MCLEncoder file_menu_encoder; -extern MenuPage<7> file_menu_page; + +constexpr size_t file_menu_page_N = 7; +extern MenuPage file_menu_page; extern MCLEncoder seq_menu_value_encoder; extern MCLEncoder seq_menu_entry_encoder; -extern MenuPage<20> seq_menu_page; -extern MCLEncoder step_menu_value_encoder; -extern MCLEncoder step_menu_entry_encoder; -extern MenuPage<4> step_menu_page; +constexpr size_t seq_menu_page_N = 24; +extern MenuPage seq_menu_page; extern MCLEncoder grid_slot_param1; extern MCLEncoder grid_slot_param2; -constexpr size_t grid_slot_page_N = 11; +constexpr size_t grid_slot_page_N = 9; extern MenuPage grid_slot_page; extern MCLEncoder wavdesign_menu_value_encoder; extern MCLEncoder wavdesign_menu_entry_encoder; -extern MenuPage<3> wavdesign_menu_page; + +constexpr size_t wavdesign_menu_page_N = 3; +extern MenuPage wavdesign_menu_page; + +constexpr size_t perf_menu_page_N = 2; +extern MenuPage perf_menu_page; extern uint8_t opt_import_src; extern uint8_t opt_import_dest; diff --git a/avr/cores/megacommand/MCL/MCLSeq.cpp b/avr/cores/megacommand/MCL/MCLSeq.cpp index b31724b5d..a1abed7ce 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.cpp +++ b/avr/cores/megacommand/MCL/MCLSeq.cpp @@ -12,14 +12,11 @@ void MCLSeq::setup() { md_arp_tracks[i].track_number = i; } #ifdef LFO_TRACKS + + lfo_tracks[0].load_tables(); //Only needs to be done once + for (uint8_t i = 0; i < num_lfo_tracks; i++) { lfo_tracks[i].track_number = i; - if (i == 0) { - lfo_tracks[i].params[0].dest = 17; - lfo_tracks[i].params[1].dest = 18; - lfo_tracks[i].params[0].param = 7; - lfo_tracks[i].params[1].param = 7; - } } #endif #ifdef EXT_TRACKS @@ -39,12 +36,15 @@ void MCLSeq::setup() { aux_tracks[i].speed = SEQ_SPEED_1X; } + mdfx_track.length = 16; + mdfx_track.speed = SEQ_SPEED_1X; + enable(); MidiClock.addOnMidiStopCallback( this, (midi_clock_callback_ptr_t)&MCLSeq::onMidiStopCallback); - MidiClock.addOnMidiStartCallback( - this, (midi_clock_callback_ptr_t)&MCLSeq::onMidiStartCallback); + // MidiClock.addOnMidiStartCallback( + // this, (midi_clock_callback_ptr_t)&MCLSeq::onMidiStartCallback); MidiClock.addOnMidiStartImmediateCallback( this, (midi_clock_callback_ptr_t)&MCLSeq::onMidiStartImmediateCallback); @@ -53,39 +53,13 @@ void MCLSeq::setup() { midi_events.setup_callbacks(); }; -void MCLSeq::enable() { - if (state) { - return; - } - MidiClock.addOn192Callback(this, (midi_clock_callback_ptr_t)&MCLSeq::seq); - state = true; -} -void MCLSeq::disable() { - if (!state) { - return; - } - MidiClock.removeOn192Callback(this, (midi_clock_callback_ptr_t)&MCLSeq::seq); - state = false; -} // restore kit params void MCLSeq::update_kit_params() { - for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { - mcl_seq.md_tracks[n].update_kit_params(); - } #ifdef LFO_TRACKS - for (uint8_t n = 0; n < NUM_LFO_TRACKS; n++) { - mcl_seq.lfo_tracks[n].update_kit_params(); - } #endif } void MCLSeq::update_params() { - for (uint8_t i = 0; i < num_md_tracks; i++) { - md_tracks[i].update_params(); - } #ifdef LFO_TRACKS - for (uint8_t i = 0; i < num_lfo_tracks; i++) { - lfo_tracks[i].update_params_offset(); - } #endif } @@ -132,6 +106,7 @@ void MCLSeq::onMidiStartImmediateCallback() { for (uint8_t i = 0; i < NUM_AUX_TRACKS; i++) { aux_tracks[i].reset(); } + mdfx_track.reset(); #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { @@ -145,18 +120,14 @@ void MCLSeq::onMidiStartImmediateCallback() { sei(); - for (uint8_t i = 0; i < num_md_tracks; i++) { - md_tracks[i].update_params(); - } - #ifdef LFO_TRACKS - for (uint8_t i = 0; i < num_lfo_tracks; i++) { - lfo_tracks[i].update_params_offset(); - } #endif seq_rec_play(); MidiUartParent::handle_midi_lock = _midi_lock_tmp; + if (SeqPage::recording) { + oled_display.textbox("REC", ""); + } } void MCLSeq::onMidiStartCallback() {} @@ -172,21 +143,20 @@ void MCLSeq::onMidiStopCallback() { } } #endif + MD.reset_dsp_params(); + for (uint8_t i = 0; i < num_md_tracks; i++) { - md_tracks[i].reset_params(); md_tracks[i].locks_slides_recalc = 255; for (uint8_t c = 0; c < NUM_LOCKS; c++) { md_tracks[i].locks_slide_data[c].init(); } } #ifdef LFO_TRACKS - for (uint8_t i = 0; i < num_lfo_tracks; i++) { - lfo_tracks[i].reset_params_offset(); - } #endif } void MCLSeq::seq() { + if (!state) { return; } MidiUartParent *uart; MidiUartParent *uart2; @@ -264,19 +234,21 @@ void MCLSeq::seq() { MD.parallelTrig(MDSeqTrack::md_trig_mask, uart); } + mdfx_track.seq(); + if (MDSeqTrack::load_machine_cache) { - MD.loadMachinesCache(MDSeqTrack::load_machine_cache); - MD.undokit_sync(); + MD.setKitName(grid_task.kit_names[0], uart); + MD.loadMachinesCache(MDSeqTrack::load_machine_cache, uart); } - // Arp for (uint8_t i = 0; i < NUM_AUX_TRACKS; i++) { aux_tracks[i].seq(); } + // Arp #ifdef LFO_TRACKS for (uint8_t i = 0; i < num_lfo_tracks; i++) { - lfo_tracks[i].seq(uart); + lfo_tracks[i].seq(uart, uart2); } #endif @@ -303,7 +275,9 @@ void MCLSeq::seq() { } } -void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) {} +void MCLSeqMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { + mixer_page.onNoteOnCallback_Midi(msg); +} void MCLSeqMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) {} @@ -315,58 +289,79 @@ void MCLSeqMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { uint8_t track_param; MD.parseCC(channel, param, &track, &track_param); - if (track > 15) { return; } + if (track > 15) { + return; + } + + if (mcl.currentPage() == MIXER_PAGE) { + mixer_page.onControlChangeCallback_Midi(track, track_param, value); + } if (track_param == 32) { // Mute mcl_seq.md_tracks[track].mute_state = value > 0; + if (mixer_page.current_mute_set != 255) { + if (value > 0) { + CLEAR_BIT16(mixer_page.mute_sets[0].mutes[mixer_page.current_mute_set], + track); + } else { + SET_BIT16(mixer_page.mute_sets[0].mutes[mixer_page.current_mute_set], + track); + } + } } if (track_param > 23) { return; } // ignore level/mute + perf_page.learn_param(track, track_param, value); + lfo_page.learn_param(track, track_param, value); + if (!update_params) { return; } - mcl_seq.md_tracks[track].update_param(track_param, value); -#ifdef LFO_TRACKS - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].check_and_update_params_offset(track + 1, track_param, - value); - } -#endif } void MCLSeqMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t param = msg[1]; uint8_t value = msg[2]; -#ifdef EXT_TRACKS - for (uint8_t n = 0; n < NUM_EXT_TRACKS; n++) { - if (mcl_seq.ext_tracks[n].channel == channel) { - if (param == midi_active_peering.get_device(UART2_PORT)->get_mute_cc()) { - if (value > 0) { - mcl_seq.ext_tracks[n].mute_state = SEQ_MUTE_ON; - mcl_seq.ext_tracks[n].buffer_notesoff(); - } else { - mcl_seq.ext_tracks[n].mute_state = SEQ_MUTE_OFF; - } + + if (param == midi_active_peering.get_device(UART2_PORT)->get_mute_cc()) { + for (uint8_t n = 0; n < NUM_EXT_TRACKS; n++) { + if (mcl_seq.ext_tracks[n].channel != channel) { + continue; + } + mcl_seq.ext_tracks[n].mute_state = value > 0; + if (mixer_page.current_mute_set == 255) { + continue; + } + if (value > 0) { + CLEAR_BIT16( + mixer_page.mute_sets[1].mutes[mixer_page.current_mute_set], n); + mcl_seq.ext_tracks[n].buffer_notesoff(); } else { - mcl_seq.ext_tracks[n].update_param(param, value); + SET_BIT16( + mixer_page.mute_sets[1].mutes[mixer_page.current_mute_set], n); } } + return; } -#endif + + perf_page.learn_param(channel + 16 + 4, param, value); + lfo_page.learn_param(channel + 16 + 4, param, value); + } void MCLSeqMidiEvents::setup_callbacks() { if (state) { return; } - /* + Midi.addOnNoteOnCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOnCallback_Midi); -` Midi.addOnNoteOffCallback( - this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); - */ + /* + Midi.addOnNoteOffCallback( + this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); + */ update_params = true; Midi.addOnControlChangeCallback( this, @@ -384,9 +379,10 @@ void MCLSeqMidiEvents::remove_callbacks() { if (!state) { return; } - /* + Midi.removeOnNoteOnCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOnCallback_Midi); + /* Midi.removeOnNoteOffCallback( this, (midi_callback_ptr_t)&MCLSeqMidiEvents::onNoteOffCallback_Midi); */ diff --git a/avr/cores/megacommand/MCL/MCLSeq.h b/avr/cores/megacommand/MCL/MCLSeq.h index 9b26ef3fe..869441711 100644 --- a/avr/cores/megacommand/MCL/MCLSeq.h +++ b/avr/cores/megacommand/MCL/MCLSeq.h @@ -2,11 +2,16 @@ #pragma once -#include "LFOSeqTrack.h" +#include "MCLMemory.h" +#include "MidiClock.h" +#include "Midi.h" + #include "MDSeqTrack.h" -#include "ExtSeqTrack.h" +#include "LFOSeqTrack.h" #include "ArpSeqTrack.h" -//#include "MDTrack.h" +#include "ExtSeqTrack.h" +#include "MDFXseqTrack.h" + #define SEQ_MUTE_ON 1 #define SEQ_MUTE_OFF 0 @@ -55,14 +60,18 @@ class MCLSeq : public ClockCallback { static constexpr uint8_t num_lfo_tracks = NUM_LFO_TRACKS; #endif - SeqTrack aux_tracks[NUM_AUX_TRACKS]; + SeqTrackBase aux_tracks[NUM_AUX_TRACKS]; + + MDFXSeqTrack mdfx_track; MCLSeqMidiEvents midi_events; + bool state = false; + void enable() { state = true; } + void disable() { state = false; } + void setup(); - void enable(); - void disable(); uint8_t find_ext_track(uint8_t channel); @@ -76,4 +85,3 @@ class MCLSeq : public ClockCallback { }; extern MCLSeq mcl_seq; - diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.cpp b/avr/cores/megacommand/MCL/MCLSysConfig.cpp index 742f275e4..0564bbd4c 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.cpp +++ b/avr/cores/megacommand/MCL/MCLSysConfig.cpp @@ -134,14 +134,14 @@ bool MCLSysConfig::cfg_init() { midi_forward_2 = 0; midi_forward_usb = 0; - auto_save = 1; + rec_automation = 1; auto_normalize = 1; load_mode = LOAD_MANUAL; chain_queue_length = 1; chain_load_quant = 16; ram_page_mode = 0; track_select = 1; - track_type_select = 0b00000101; + track_type_select = 0b00000011; uart2_device = 0; uart_cc_loopback = 0; uart2_prg_mode = 0; @@ -150,6 +150,7 @@ bool MCLSysConfig::cfg_init() { midi_transport_send = 0; midi_ctrl_port = 1; md_trig_channel = 0; + seq_dev = 0; cfgfile.close(); ret = write_cfg(); if (!ret) { diff --git a/avr/cores/megacommand/MCL/MCLSysConfig.h b/avr/cores/megacommand/MCL/MCLSysConfig.h index 9fcffa77d..3c785099f 100644 --- a/avr/cores/megacommand/MCL/MCLSysConfig.h +++ b/avr/cores/megacommand/MCL/MCLSysConfig.h @@ -4,7 +4,7 @@ #define MCLSYSCONFIG_H__ #include "SdFat.h" -#define CONFIG_VERSION 4006 +#define CONFIG_VERSION 4007 #define MIDI_OMNI_MODE 17 #define MIDI_LOCAL_MODE 0 @@ -48,7 +48,7 @@ class MCLSysConfigData { uint8_t midi_forward_2; uint8_t midi_forward_usb; - uint8_t auto_save; + uint8_t rec_automation; uint8_t load_mode; uint8_t chain_queue_length; uint8_t chain_load_quant; @@ -64,6 +64,7 @@ class MCLSysConfigData { uint8_t midi_transport_send; uint8_t midi_ctrl_port; uint8_t md_trig_channel; + uint8_t seq_dev; }; class MCLSysConfig : public MCLSysConfigData { diff --git a/avr/cores/megacommand/MCL/MCL_impl.h b/avr/cores/megacommand/MCL/MCL_impl.h index 05d7b4652..c8182f87e 100644 --- a/avr/cores/megacommand/MCL/MCL_impl.h +++ b/avr/cores/megacommand/MCL/MCL_impl.h @@ -1,6 +1,6 @@ #pragma once -#include "MCL.h" +#include "mcl.h" #include "new.h" #include "A4.h" @@ -35,6 +35,7 @@ #ifdef SOUND_PAGE #include "SoundBrowserPage.h" +#include "SampleBrowserPage.h" #endif #ifdef LOUDNESS_PAGE @@ -57,7 +58,6 @@ #include "AuxPages.h" #include "GridPages.h" -#include "GridEncoder.h" #include "MCLEncoder.h" #include "Grid.h" @@ -77,6 +77,7 @@ #include "MDRouteTrack.h" #include "MDTempoTrack.h" #include "GridChainTrack.h" +#include "PerfTrack.h" #include "ArpSeqTrack.h" #include "EmptyTrack.h" diff --git a/avr/cores/megacommand/MCL/MDFXSeqTrack.h b/avr/cores/megacommand/MCL/MDFXSeqTrack.h new file mode 100644 index 000000000..363c07eb6 --- /dev/null +++ b/avr/cores/megacommand/MCL/MDFXSeqTrack.h @@ -0,0 +1,34 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef MDFXSEQTRACK_H__ +#define MDFXSEQTRACK_H__ + +#include "MCLMemory.h" +// #include "MidiActivePeering.h" +#include "MidiUartParent.h" +#include "WProgram.h" + +class MDFXSeqTrack : public SeqTrackBase { + +public: + MDFXSeqTrack() { SeqTrackBase::reset(); } + + ALWAYS_INLINE() void seq() { + uint8_t timing_mid = get_timing_mid(); + mod12_counter++; + if (mod12_counter == timing_mid) { + mod12_counter = 0; + step_count_inc(); + } + if (count_down) { + count_down--; + if (count_down == 0) { + MDSeqTrack::load_machine_cache |= ((uint32_t) 0b1111 << 16); + reset(); + mod12_counter = 0; + } + } + + } +}; +#endif /* MDFXSEQTRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/MDFXTrack.cpp b/avr/cores/megacommand/MCL/MDFXTrack.cpp index ad234cf96..a2fed0350 100644 --- a/avr/cores/megacommand/MCL/MDFXTrack.cpp +++ b/avr/cores/megacommand/MCL/MDFXTrack.cpp @@ -7,12 +7,23 @@ void MDFXTrack::paste_track(uint8_t src_track, uint8_t dest_track, } void MDFXTrack::transition_send(uint8_t tracknumber, uint8_t slotnumber) { - send_fx(); +} + +void MDFXTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, + uint8_t slotnumber) { + GridTrack::transition_load(tracknumber, seq_track, slotnumber); + // load_seq_data(seq_track); +} + +bool MDFXTrack::transition_cache(uint8_t tracknumber, uint8_t slotnumber) { + bool send = true; + MD.assignFXParamsBulk(reverb, send); + return true; } uint16_t MDFXTrack::calc_latency(uint8_t tracknumber) { bool send = false; - return send_fx(send); + return MD.assignFXParamsBulk(reverb, send); } uint16_t MDFXTrack::send_fx(bool send) { @@ -42,6 +53,10 @@ void MDFXTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { place_fx_in_kit(); } +void MDFXTrack::load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) { + load_link_data(seq_track); +} + void MDFXTrack::place_fx_in_kit() { DEBUG_PRINTLN("place"); memcpy(MD.kit.reverb, reverb, sizeof(reverb) * 4); diff --git a/avr/cores/megacommand/MCL/MDFXTrack.h b/avr/cores/megacommand/MCL/MDFXTrack.h index 4b044c912..7dbe03752 100644 --- a/avr/cores/megacommand/MCL/MDFXTrack.h +++ b/avr/cores/megacommand/MCL/MDFXTrack.h @@ -44,11 +44,15 @@ class MDFXTrack : public AUXTrack, public MDFXData { void paste_track(uint8_t src_track, uint8_t dest_track, SeqTrack *seq_track); bool store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track = nullptr, uint8_t merge = 0, bool online = false, Grid *grid = nullptr); + void transition_load(uint8_t tracknumber, SeqTrack *seq_track, + uint8_t slotnumber); + bool transition_cache(uint8_t tracknumber, uint8_t slotnumber); void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); + void load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track); virtual uint16_t get_track_size() { return sizeof(MDFXTrack); } - virtual uint32_t get_region() { return BANK1_MDFX_TRACK_START; } + virtual uint16_t get_region() { return BANK1_MDFX_TRACK_START; } virtual uint8_t get_model() { return MDFX_TRACK_TYPE; } virtual uint8_t get_device_type() { return MDFX_TRACK_TYPE; } diff --git a/avr/cores/megacommand/MCL/MDLFOTrack.h b/avr/cores/megacommand/MCL/MDLFOTrack.h index ccb3e8d9c..61c24ccf1 100644 --- a/avr/cores/megacommand/MCL/MDLFOTrack.h +++ b/avr/cores/megacommand/MCL/MDLFOTrack.h @@ -31,7 +31,7 @@ class MDLFOTrack : public AUXTrack { void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); virtual uint16_t get_track_size() { return sizeof(MDLFOTrack); } - virtual uint32_t get_region() { return BANK1_MDLFO_TRACK_START; } + virtual uint16_t get_region() { return BANK1_MDLFO_TRACK_START; } virtual uint8_t get_model() { return MDLFO_TRACK_TYPE; } virtual uint8_t get_device_type() { return MDLFO_TRACK_TYPE; } diff --git a/avr/cores/megacommand/MCL/MDRouteTrack.h b/avr/cores/megacommand/MCL/MDRouteTrack.h index 6b0cfeb53..08f08fd60 100644 --- a/avr/cores/megacommand/MCL/MDRouteTrack.h +++ b/avr/cores/megacommand/MCL/MDRouteTrack.h @@ -36,7 +36,7 @@ class MDRouteTrack : public AUXTrack, public RouteData { void load_routes(); virtual uint16_t get_track_size() { return sizeof(MDRouteTrack); } - virtual uint32_t get_region() { return BANK1_MDROUTE_TRACK_START; } + virtual uint16_t get_region() { return BANK1_MDROUTE_TRACK_START; } virtual uint8_t get_model() { return MDROUTE_TRACK_TYPE; } virtual uint8_t get_device_type() { return MDROUTE_TRACK_TYPE; } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.cpp b/avr/cores/megacommand/MCL/MDSeqTrack.cpp index 3b0867139..c673d4d21 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.cpp +++ b/avr/cores/megacommand/MCL/MDSeqTrack.cpp @@ -1,8 +1,8 @@ #include "MCL_impl.h" -uint16_t MDSeqTrack::sync_cursor = 0; +uint16_t MDSeqTrack::gui_update = 0; uint16_t MDSeqTrack::md_trig_mask = 0; -uint16_t MDSeqTrack::load_machine_cache = 0; +uint32_t MDSeqTrack::load_machine_cache = 0; void MDSeqTrack::set_length(uint8_t len, bool expand) { uint8_t old_length = length; @@ -27,26 +27,31 @@ void MDSeqTrack::set_length(uint8_t len, bool expand) { step_count = step; CLEAR_LOCK(); - if (expand && old_length <= 16 && length > 16) { - for (uint8_t n = 16; n < length; n++) { + if (expand && old_length <= 16 && length >= 16) { + for (uint8_t n = old_length; n < length; n++) { if ((*(int *)&(steps[n])) != 0) { expand = false; - break; + return; } } - if (expand) { MDSeqStep empty_step; memset(&empty_step, 0, sizeof(empty_step)); - for (uint8_t y = 1; y < 4; y++) { - for (uint8_t n = 0; n < 16; n++) { - copy_step(n, &empty_step); - paste_step(n + y * 16, &empty_step); - } + uint8_t a = 0; + for (uint8_t n = old_length; n < 64; n++) { + copy_step(a++, &empty_step); + paste_step(n, &empty_step); + if (a == old_length) { a = 0; } } - } } } +void MDSeqTrack::store_mute_state() { + for (uint8_t n = 0; n < NUM_MD_STEPS; n++) { + if (IS_BIT_SET64(mute_mask, n)) { set_step(n,MASK_PATTERN, 0); set_step(n,MASK_LOCK, 0); } + } + clear_mutes(); +} + void MDSeqTrack::set_speed(uint8_t new_speed, uint8_t old_speed, bool timing_adjust) { if (old_speed == 255) { @@ -86,7 +91,7 @@ void MDSeqTrack::load_cache() { MD.insertMachineInKit(track_number, &(t.machine),false); t.load_seq_data((SeqTrack *)this); - SET_BIT16(load_machine_cache, track_number); + SET_BIT32(load_machine_cache, track_number); } void MDSeqTrack::seq(MidiUartParent *uart_) { @@ -114,13 +119,20 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { if (count_down == 0) { reset(); mod12_counter = 0; - SET_BIT16(sync_cursor, track_number); + SET_BIT16(gui_update,track_number); } else if (count_down < track_number / 4 + 1) { goto end; } } + if (record_mutes) { + uint8_t u = 0; + uint8_t q = 0; + uint8_t s = get_quantized_step(u, q); + SET_BIT64(mute_mask, s); + } + if ((mute_state == SEQ_MUTE_OFF) && (ignore_step != step_count)) { @@ -149,14 +161,14 @@ void MDSeqTrack::seq(MidiUartParent *uart_) { } auto &step = steps[current_step]; - bool send_trig = trig_conditional(step.cond_id); - if (send_trig || !step.cond_plock) { + uint8_t send_trig = trig_conditional(step.cond_id); + if (send_trig == TRIG_TRUE || (!step.cond_plock && send_trig != TRIG_ONESHOT)) { send_parameter_locks_inline(current_step, step.trig, lock_idx); if (step.slide) { locks_slides_recalc = current_step; locks_slides_idx = lock_idx; } - if (send_trig && step.trig) { + if (send_trig == TRIG_TRUE && step.trig) { send_trig_inline(); } } @@ -177,58 +189,6 @@ bool MDSeqTrack::is_param(uint8_t param_id) { return false; } -void MDSeqTrack::update_param(uint8_t param_id, uint8_t value) { - bool match = false; - for (uint8_t c = 0; c < NUM_LOCKS && match == false; c++) { - if (locks_params[c] > 0) { - if (locks_params[c] - 1 == param_id) { - locks_params_orig[c] = value; - match = true; - } - } - } -} - -void MDSeqTrack::update_kit_params() { - for (uint8_t c = 0; c < NUM_LOCKS; c++) { - if (locks_params[c] > 0) { - uint8_t param_id = locks_params[c] - 1; - MD.kit.params[track_number][param_id] = locks_params_orig[c]; - } - } -} - -void MDSeqTrack::update_params() { - for (uint8_t c = 0; c < NUM_LOCKS; c++) { - if (locks_params[c] > 0) { - uint8_t param_id = locks_params[c] - 1; - locks_params_orig[c] = MD.kit.params[track_number][param_id]; - } - } -} - -void MDSeqTrack::reset_params() { - MDTrack md_track; - - md_track.get_machine_from_kit(track_number); - bool re_assign = false; - for (uint8_t c = 0; c < NUM_LOCKS; c++) { - if (locks_params[c] > 0) { - uint8_t param = locks_params[c] - 1; - if (param > 23) { - DEBUG_PRINTLN("param out of bounds"); - return; - } - re_assign = true; - md_track.machine.params[param] = locks_params_orig[c]; - } - } - if (re_assign) { - DEBUG_PRINTLN("re-assign machine"); - MD.assignMachineBulk(track_number, &md_track.machine, 255, 1, true); - } -} - void MDSeqTrack::recalc_slides() { if (locks_slides_recalc == 255) { return; @@ -248,8 +208,8 @@ void MDSeqTrack::recalc_slides() { cur_mask <<= 1; } - if (find_mask == 0) { goto end; } auto lockidx = locks_slides_idx; + if (find_mask == 0) { goto end; } find_next_locks(lockidx, step, find_mask); for (uint8_t c = 0; c < NUM_LOCKS; c++) { @@ -303,7 +263,7 @@ void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { mask &= ~cur_mask; // all targets hit? } else if (steps[next_step].trig) { - locks_slide_next_lock_val[i] = locks_params_orig[i]; + locks_slide_next_lock_val[i] = MD.kit.params[track_number][locks_params[i] - 1]; locks_slide_next_lock_step[i] = next_step; mask &= ~cur_mask; } @@ -327,7 +287,7 @@ void MDSeqTrack::find_next_locks(uint8_t curidx, uint8_t step, uint8_t mask) { void MDSeqTrack::get_mask(uint64_t *_pmask, uint8_t mask_type) const { *_pmask = 0; - for (int i = 0; i < NUM_MD_STEPS; i++) { + for (uint8_t i = 0; i < NUM_MD_STEPS; i++) { bool set_bit = false; switch (mask_type) { case MASK_PATTERN: @@ -351,7 +311,7 @@ void MDSeqTrack::get_mask(uint64_t *_pmask, uint8_t mask_type) const { } break; case MASK_MUTE: - if (IS_BIT_SET64(oneshot_mask, i)) { + if (IS_BIT_SET64(mute_mask, i)) { set_bit = true; } break; @@ -369,7 +329,7 @@ bool MDSeqTrack::get_step(uint8_t step, uint8_t mask_type) const { case MASK_LOCK: return steps[step].locks_enabled; case MASK_MUTE: - return IS_BIT_SET64(oneshot_mask, step); + return IS_BIT_SET64(mute_mask, step); case MASK_SLIDE: return steps[step].slide; default: @@ -387,9 +347,9 @@ void MDSeqTrack::set_step(uint8_t step, uint8_t mask_type, bool val) { break; case MASK_MUTE: if (val) { - SET_BIT64(oneshot_mask, step); + SET_BIT64(mute_mask, step); } else { - CLEAR_BIT64(oneshot_mask, step); + CLEAR_BIT64(mute_mask, step); } break; case MASK_SLIDE: @@ -421,15 +381,16 @@ void MDSeqTrack::send_parameter_locks_inline(uint8_t step, bool trig, send_param = locks[lock_idx]; send = true; } else if (trig) { - send_param = locks_params_orig[c]; + send_param = MD.kit.params[track_number][locks_params[c] - 1]; send = true; } } lock_idx += lock_bit; if (send) { - MD.setTrackParam_inline(track_number, locks_params[c] - 1, send_param, - uart); - } + uint8_t p = locks_params[c] - 1; + bool update_kit = false; + MD.setTrackParam_inline(track_number, p, send_param, uart, update_kit); + } } } @@ -462,83 +423,22 @@ void MDSeqTrack::send_trig_inline() { SET_BIT16(MDSeqTrack::md_trig_mask, track_number); } -bool MDSeqTrack::trig_conditional(uint8_t condition) { - bool send_trig = false; - if (IS_BIT_SET64(oneshot_mask, step_count)) { - return false; +uint8_t MDSeqTrack::trig_conditional(uint8_t condition) { + + bool send_trig = TRIG_FALSE; + if (IS_BIT_SET64(oneshot_mask, step_count) || IS_BIT_SET64(mute_mask, step_count)) { + return TRIG_ONESHOT; } - switch (condition) { - case 0: - case 1: - send_trig = true; - break; - case 2: - if (!IS_BIT_SET(iterations_8, 0)) { - send_trig = true; - } - break; - case 3: - if ((iterations_6 == 3) || (iterations_6 == 6)) { - send_trig = true; - } - break; - case 6: - if (iterations_6 == 6) { - send_trig = true; - } - break; - case 4: - if ((iterations_8 == 4) || (iterations_8 == 8)) { - send_trig = true; - } - break; - case 8: - if ((iterations_8 == 8)) { - send_trig = true; - } - break; - case 5: - if (iterations_5 == 5) { - send_trig = true; - } - break; - case 7: - if (iterations_7 == 7) { - send_trig = true; - } - break; - case 9: - if (get_random_byte() <= 13) { - send_trig = true; - } - break; - case 10: - if (get_random_byte() <= 32) { - send_trig = true; - } - break; - case 11: - if (get_random_byte() <= 64) { - send_trig = true; - } - break; - case 12: - if (get_random_byte() <= 96) { - send_trig = true; - } - break; - case 13: - if (get_random_byte() <= 115) { - send_trig = true; - } - break; - case 14: + if (condition == 14) { if (!IS_BIT_SET64(oneshot_mask, step_count)) { SET_BIT64(oneshot_mask, step_count); - send_trig = true; + send_trig = TRIG_TRUE; } } - return send_trig; + else { + send_trig = SeqTrack::conditional(condition); + } + return send_trig; } uint8_t MDSeqTrack::get_track_lock_implicit(uint8_t step, uint8_t param) { @@ -568,7 +468,6 @@ bool MDSeqTrack::set_track_locks(uint8_t step, uint8_t track_param, for (uint8_t c = 0; c < NUM_LOCKS && match == 255; c++) { if (locks_params[c] == 0) { locks_params[c] = track_param + 1; - locks_params_orig[c] = MD.kit.params[track_number][track_param]; match = c; } } @@ -607,38 +506,13 @@ bool MDSeqTrack::set_track_locks_i(uint8_t step, uint8_t lockidx, return true; } -uint8_t MDSeqTrack::get_quantized_step() { - uint8_t timing_mid = get_timing_mid(); - - int8_t mod12 = mod12_counter - 1; - - uint8_t step = step_count; - - if ((step == 0) && (mod12 < 0)) { - mod12 += timing_mid; - step = length - 1; - } - - uint8_t utiming = mod12 + timing_mid; - - if (mcl_cfg.rec_quant) { - if (mod12 > timing_mid / 2) { - step++; - if (step == length) { - step = 0; - } - } - } - return step; -} - void MDSeqTrack::record_track_locks(uint8_t track_param, uint8_t value) { if (step_count >= length) { return; } - - set_track_locks(get_quantized_step(), track_param, value); + uint8_t utiming = 0; + set_track_locks(get_quantized_step(utiming), track_param, value); } void MDSeqTrack::set_track_pitch(uint8_t step, uint8_t pitch) { @@ -650,7 +524,8 @@ void MDSeqTrack::record_track_pitch(uint8_t pitch) { if (step_count >= length) { return; } - set_track_pitch(get_quantized_step(), pitch); + uint8_t utiming = 0; + set_track_pitch(get_quantized_step(utiming), pitch); } void MDSeqTrack::record_track(uint8_t velocity) { @@ -658,29 +533,10 @@ void MDSeqTrack::record_track(uint8_t velocity) { if (step_count >= length) { return; } - uint8_t timing_mid = get_timing_mid(); - - int8_t mod12 = mod12_counter - 1; + uint8_t utiming = 0; + uint8_t step = get_quantized_step(utiming); + ignore_step = step; - uint8_t step = step_count; - - if ((step == 0) && (mod12 < 0)) { - mod12 += timing_mid; - step = length - 1; - } - - uint8_t utiming = mod12 + timing_mid; - - if (mcl_cfg.rec_quant) { - if (mod12 > timing_mid / 2) { - step++; - if (step == length) { - step = 0; - } - ignore_step = step; - } - utiming = timing_mid; - } set_track_step(step, utiming, velocity); } @@ -786,7 +642,7 @@ void MDSeqTrack::clear_param_locks(uint8_t param_id) { } } - MD.setTrackParam(track_number, param_id, locks_params_orig[match]); + MD.setTrackParam(track_number, param_id, MD.kit.params[track_number][locks_params[match] - 1]); } @@ -816,16 +672,26 @@ uint8_t MDSeqTrack::get_step_locks(uint8_t step) { return steps[step].locks_enabled ? steps[step].locks : 0; } +void MDSeqTrack::clear_mute() { + mute_mask = 0; +} + +void MDSeqTrack::clear_mutes() { + oneshot_mask = 0; + mute_mask = 0; +} + void MDSeqTrack::clear_conditional() { for (uint8_t c = 0; c < NUM_MD_STEPS; c++) { steps[c].cond_id = 0; steps[c].cond_plock = 0; timing[c] = 0; } - oneshot_mask = 0; + clear_mutes(); + ignore_step = 255; } -void MDSeqTrack::clear_locks(bool reset_params_) { +void MDSeqTrack::clear_locks() { // Need to buffer this, as we dont want sequencer interrupt // to access it whilst we're cleaning up DEBUG_DUMP("Clear these locks"); @@ -834,24 +700,21 @@ void MDSeqTrack::clear_locks(bool reset_params_) { } memset(locks, 0, sizeof(locks)); - if (reset_params_) { - reset_params(); - } cur_event_idx = 0; } -void MDSeqTrack::clear_track(bool locks, bool reset_params_) { +void MDSeqTrack::clear_track(bool locks) { clear_conditional(); if (locks) { DEBUG_DUMP("clear locks"); - clear_locks(reset_params_); + clear_locks(); } memset(steps, 0, sizeof(steps)); } void MDSeqTrack::merge_from_md(uint8_t track_number, MDPattern *pattern) { DEBUG_PRINT_FN(); - for (int i = 0; i < 24; i++) { + for (uint8_t i = 0; i < 24; i++) { if (!IS_BIT_SET32(pattern->lockPatterns[track_number], i)) { continue; } @@ -859,7 +722,7 @@ void MDSeqTrack::merge_from_md(uint8_t track_number, MDPattern *pattern) { if (idx < 0) { continue; } - for (int s = 0; s < 64; s++) { + for (uint8_t s = 0; s < 64; s++) { int8_t lockval = pattern->locks[idx][s]; if (lockval >= 0 && IS_BIT_SET64(pattern->trigPatterns[track_number], s)) { @@ -933,6 +796,7 @@ void MDSeqTrack::modify_track(uint8_t dir) { memmove(timing, timing + 1, length - 1); steps[length - 1] = step_buf; timing[length - 1] = timing_buf; + ROTATE_LEFT(mute_mask, length); break; } case DIR_RIGHT: { @@ -949,14 +813,16 @@ void MDSeqTrack::modify_track(uint8_t dir) { memmove(timing + 1, timing, length - 1); steps[0] = step_buf; timing[0] = timing_buf; + ROTATE_RIGHT(mute_mask,length); break; } case DIR_REVERSE: { uint8_t rev_locks[NUM_MD_LOCK_SLOTS]; memcpy(rev_locks, locks, sizeof(locks)); uint16_t l = 0, r = 0; + //mute_mask = 0; //unimplemented // reverse steps & locks - for (int i = 0; i <= length / 2; ++i) { + for (uint8_t i = 0; i <= length / 2; ++i) { int j = length - i - 1; if (j < i) { break; @@ -973,6 +839,12 @@ void MDSeqTrack::modify_track(uint8_t dir) { timing_buf = timing[i]; timing[i] = timing[j]; timing[j] = timing_buf; + bool a = IS_BIT_SET64(mute_mask, i); + bool b = IS_BIT_SET64(mute_mask, j); + if (a) { SET_BIT64(mute_mask, j); } + else { CLEAR_BIT64(mute_mask,j); } + if (b) { SET_BIT64(mute_mask, i); } + else { CLEAR_BIT64(mute_mask,i); } } break; } diff --git a/avr/cores/megacommand/MCL/MDSeqTrack.h b/avr/cores/megacommand/MCL/MDSeqTrack.h index 5cc778faf..236b2d411 100644 --- a/avr/cores/megacommand/MCL/MDSeqTrack.h +++ b/avr/cores/megacommand/MCL/MDSeqTrack.h @@ -4,8 +4,9 @@ #define MDSEQTRACK_H__ #include "MD.h" -#include "MDSeqTrackData.h" #include "SeqTrack.h" +#include "MDSeqTrackData.h" +#include "DeviceTrack.h" #define UART1_PORT 1 @@ -18,17 +19,19 @@ class MDTrack; class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { public: + uint64_t oneshot_mask; - uint8_t locks_params_orig[NUM_LOCKS]; + uint64_t mute_mask; - static uint16_t sync_cursor; + static uint16_t gui_update; static uint16_t md_trig_mask; - static uint16_t load_machine_cache; + static uint32_t load_machine_cache; MDSeqTrack() : SeqSlideTrack() { active = MD_TRACK_TYPE; } ALWAYS_INLINE() void reset() { - SeqTrack::reset(); + SeqSlideTrack::reset(); oneshot_mask = 0; + record_mutes = false; } void get_mask(uint64_t *_pmask, uint8_t mask_type) const; @@ -43,7 +46,7 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { void send_trig(); void send_trig_inline(); - bool trig_conditional(uint8_t condition); + uint8_t trig_conditional(uint8_t condition); void send_parameter_locks(uint8_t step, bool trig, uint16_t lock_idx = 0xFFFF); void send_parameter_locks_inline(uint8_t step, bool trig, uint16_t lock_idx); void get_step_locks(uint8_t step, uint8_t *params, bool ignore_locks_disabled = false); @@ -62,10 +65,11 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { uint8_t get_track_lock(uint8_t step, uint8_t lockidx); uint8_t get_track_lock_implicit(uint8_t step, uint8_t param); - uint8_t get_quantized_step(); void record_track(uint8_t velocity); void record_track_locks(uint8_t track_param, uint8_t value); void record_track_pitch(uint8_t pitch); + void clear_mute(); + void clear_mutes(); void clear_slide_data(); void clear_step_locks(uint8_t step); // disable the step locks, but not remove them. so later can be re-activated. @@ -75,14 +79,11 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { uint8_t get_step_locks(uint8_t step); void clear_conditional(); void clear_step_lock(uint8_t step, uint8_t param_id); - void clear_locks(bool reset_params_ = true); - void clear_track(bool locks = true, bool reset_params_ = true); + void clear_locks(); + void clear_track(bool locks = true); void clear_param_locks(uint8_t param_id); bool is_param(uint8_t param_id); - void update_kit_params(); - void update_params(); - void update_param(uint8_t param_id, uint8_t value); - void reset_params(); + void merge_from_md(uint8_t track_number, MDPattern *pattern); void set_length(uint8_t len, bool expand = false); @@ -96,6 +97,8 @@ class MDSeqTrack : public MDSeqTrackData, public SeqSlideTrack { void set_speed(uint8_t new_speed, uint8_t old_speed = 255, bool timing_adjust = true); + void store_mute_state(); + void copy_step(uint8_t n, MDSeqStep *step); void paste_step(uint8_t n, MDSeqStep *step); void load_cache(); diff --git a/avr/cores/megacommand/MCL/MDTempoTrack.cpp b/avr/cores/megacommand/MCL/MDTempoTrack.cpp index cd14a438d..d007e79cd 100644 --- a/avr/cores/megacommand/MCL/MDTempoTrack.cpp +++ b/avr/cores/megacommand/MCL/MDTempoTrack.cpp @@ -13,6 +13,10 @@ uint16_t MDTempoTrack::send_tempo(bool send) { return MD.setTempo(tempo, send); } +void MDTempoTrack::load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) { + load_link_data(seq_track); +} + void MDTempoTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { load_link_data(seq_track); send_tempo(); @@ -23,7 +27,7 @@ void MDTempoTrack::get_tempo() { if (MidiClock.uart_clock_recv == &MidiUart) { uint16_t tp; if (MD.get_tempo(tp)) { - tempo = (float)tp / 24.0; + tempo = (float)tp * 0.0416667; return; } } diff --git a/avr/cores/megacommand/MCL/MDTempoTrack.h b/avr/cores/megacommand/MCL/MDTempoTrack.h index b97487909..cdcbbdb72 100644 --- a/avr/cores/megacommand/MCL/MDTempoTrack.h +++ b/avr/cores/megacommand/MCL/MDTempoTrack.h @@ -27,9 +27,10 @@ class MDTempoTrack : public AUXTrack, public TempoData { bool online = false, Grid *grid = nullptr); void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); + void load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track); virtual uint16_t get_track_size() { return sizeof(MDTempoTrack); } - virtual uint32_t get_region() { return BANK1_MDTEMPO_TRACK_START; } + virtual uint16_t get_region() { return BANK1_MDTEMPO_TRACK_START; } virtual uint8_t get_model() { return MDTEMPO_TRACK_TYPE; } virtual uint8_t get_device_type() { return MDTEMPO_TRACK_TYPE; } diff --git a/avr/cores/megacommand/MCL/MDTrack.cpp b/avr/cores/megacommand/MCL/MDTrack.cpp index 054e935c7..7004dde62 100644 --- a/avr/cores/megacommand/MCL/MDTrack.cpp +++ b/avr/cores/megacommand/MCL/MDTrack.cpp @@ -78,6 +78,11 @@ void MDTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { load_seq_data(seq_track); } +void MDTrack::load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) { + DEBUG_PRINTLN("load immediate"); + load_seq_data(seq_track); +} + void MDTrack::get_machine_from_kit(uint8_t tracknumber) { // trackName[0] = '\0'; memcpy(machine.params, MD.kit.params[tracknumber], 24); @@ -113,9 +118,8 @@ void MDTrack::load_seq_data(SeqTrack *seq_track) { memcpy(md_seq_track->data(), seq_data.data(), sizeof(seq_data)); load_link_data(seq_track); - md_seq_track->oneshot_mask = 0; + md_seq_track->clear_mutes(); md_seq_track->set_length(md_seq_track->length); - md_seq_track->update_params(); } void MDTrack::scale_seq_vol(float scale) { @@ -158,6 +162,7 @@ bool MDTrack::store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track, uint32_t len; MDSeqTrack *md_seq_track = (MDSeqTrack *)seq_track; + md_seq_track->store_mute_state(); if (column != 255 && online == true) { get_machine_from_kit(column); diff --git a/avr/cores/megacommand/MCL/MDTrack.h b/avr/cores/megacommand/MCL/MDTrack.h index ca72ceb31..b7ea5ab3a 100644 --- a/avr/cores/megacommand/MCL/MDTrack.h +++ b/avr/cores/megacommand/MCL/MDTrack.h @@ -91,6 +91,9 @@ class MDTrack : public DeviceTrack { SeqTrack *seq_track = nullptr, uint8_t merge = 0, bool online = false, Grid *grid = nullptr); void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); + + void load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track); + void paste_track(uint8_t src_track, uint8_t dest_track, SeqTrack *seq_track); // scale machine track vol by percentage void scale_vol(float scale); @@ -127,7 +130,7 @@ class MDTrack : public DeviceTrack { } virtual uint16_t get_track_size() { return sizeof(MDTrack); } - virtual uint32_t get_region() { return BANK1_MD_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_MD_TRACKS_START; } virtual void on_copy(int16_t s_col, int16_t d_col, bool destination_same); virtual uint8_t get_model() { return machine.get_model(); } virtual uint8_t get_device_type() { return MD_TRACK_TYPE; } @@ -142,7 +145,7 @@ class MDTrackChunk : public DeviceTrackChunk { virtual uint16_t get_seq_data_size() { return sizeof(MDSeqTrackData); } virtual uint8_t get_model() { return MD_TRACK_TYPE; } virtual uint16_t get_track_size() { return GRID1_TRACK_LEN; } - virtual uint32_t get_region() { return BANK1_MD_TRACKS_START; } + virtual uint16_t get_region() { return BANK1_MD_TRACKS_START; } virtual uint8_t get_device_type() { return MD_TRACK_TYPE; } virtual void *get_sound_data_ptr() { return nullptr; } diff --git a/avr/cores/megacommand/MCL/MDTrackSelect.cpp b/avr/cores/megacommand/MCL/MDTrackSelect.cpp index b830fce42..c5cec1935 100644 --- a/avr/cores/megacommand/MCL/MDTrackSelect.cpp +++ b/avr/cores/megacommand/MCL/MDTrackSelect.cpp @@ -45,39 +45,80 @@ void MDTrackSelect::end() { DEBUG_PRINTLN(sysex->get_recordLen()); DEBUG_PRINTLN(msg_rd); if (sysex->get_recordLen() == 8) { + bool is_md_device = SeqPage::midi_device == &MD && (mcl.currentPage() != SEQ_EXTSTEP_PAGE); bool expand = true; + bool is_seq_page = mcl.isSeqPage(); reset_undo(); uint8_t length = sysex->getByte(6); uint8_t new_speed = sysex->getByte(7); - if (GUI.currentPage() == &seq_step_page) { - if (seq_step_page.recording) { + if (is_seq_page) { + if (SeqPage::recording) { goto update_pattern; } uint8_t b = sysex->getByte(3); MD.currentTrack = b & 0xF; - mcl_seq.md_tracks[MD.currentTrack].set_length(length, expand); - mcl_seq.md_tracks[MD.currentTrack].set_speed(new_speed); - seq_step_page.config_encoders(); + uint8_t n = is_md_device ? MD.currentTrack : last_ext_track; + SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[n] + : (SeqTrack *)&mcl_seq.ext_tracks[n]; + + if (is_md_device) { + mcl_seq.md_tracks[n].set_length(length, expand); + mcl_seq.md_tracks[n].set_speed(new_speed); + } + else{ + mcl_seq.ext_tracks[n].set_length(length, expand); + mcl_seq.ext_tracks[n].set_speed(new_speed); + if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { seq_extparam4.cur = length; } + } + SeqPage *seq_page = (SeqPage*) GUI.currentPage(); + seq_page->config_encoders(); } else { update_pattern: uint8_t old_speeds[16]; uint8_t old_mutes[16]; - for (uint8_t n = 0; n < 16; n++) { - mcl_seq.md_tracks[n].set_length(length, expand); - old_speeds[n] = mcl_seq.md_tracks[n].speed; + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + for (uint8_t n = 0; n < len; n++) { + SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[n] + : (SeqTrack *)&mcl_seq.ext_tracks[n]; + + if (is_md_device) { + mcl_seq.md_tracks[n].set_length(length, expand); + } + else{ + mcl_seq.ext_tracks[n].set_length(length, expand); + } + old_speeds[n] = seq_track->speed; if (old_speeds[n] == new_speed) { old_speeds[n] = 255; continue; } - old_mutes[n] = mcl_seq.md_tracks[n].mute_state; - mcl_seq.md_tracks[n].set_speed(new_speed, 255, false); - mcl_seq.md_tracks[n].mute_state = SEQ_MUTE_ON; + + old_mutes[n] = seq_track->mute_state; + if (is_md_device) { + mcl_seq.md_tracks[n].set_speed(new_speed, 255, false); + } + else { + mcl_seq.ext_tracks[n].set_speed(new_speed, 255, false); + if (last_ext_track == n) { seq_extparam4.cur = length; } + } + seq_track->mute_state = SEQ_MUTE_ON; } - for (uint8_t n = 0; n < 16; n++) { + for (uint8_t n = 0; n < len; n++) { if (old_speeds[n] == 255) continue; - mcl_seq.md_tracks[n].set_speed(new_speed, old_speeds[n], true); - mcl_seq.md_tracks[n].mute_state = old_mutes[n]; + SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[n] + : (SeqTrack *)&mcl_seq.ext_tracks[n]; + if (is_md_device) { + mcl_seq.md_tracks[n].set_speed(new_speed, old_speeds[n], true); + } + else { + mcl_seq.ext_tracks[n].set_speed(new_speed, old_speeds[n], true); + } + seq_track->mute_state = old_mutes[n]; + } + if (is_seq_page) { + SeqPage *seq_page = (SeqPage*) GUI.currentPage(); + seq_page->config_encoders(); } } } else { diff --git a/avr/cores/megacommand/MCL/MNMTrack.cpp b/avr/cores/megacommand/MCL/MNMTrack.cpp index d51d7e8d2..0300a91c5 100644 --- a/avr/cores/megacommand/MCL/MNMTrack.cpp +++ b/avr/cores/megacommand/MCL/MNMTrack.cpp @@ -32,6 +32,11 @@ void MNMTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { load_seq_data(seq_track); } +void MNMTrack::load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track) { + DEBUG_PRINT_FN(); + load_seq_data(seq_track); +} + void MNMTrack::get_machine_from_kit(uint8_t tracknumber) { DEBUG_PRINT_FN(); memcpy(machine.params, MNM.kit.parameters[tracknumber], 72); diff --git a/avr/cores/megacommand/MCL/MNMTrack.h b/avr/cores/megacommand/MCL/MNMTrack.h index be536653c..bef05cb30 100644 --- a/avr/cores/megacommand/MCL/MNMTrack.h +++ b/avr/cores/megacommand/MCL/MNMTrack.h @@ -21,6 +21,7 @@ class MNMTrack : public ExtTrack { bool transition_cache(uint8_t tracknumber, uint8_t slotnumber) { return false; } virtual void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); + virtual void load_immediate_cleared(uint8_t tracknumber, SeqTrack *seq_track); void get_machine_from_kit(uint8_t tracknumber); virtual bool store_in_grid(uint8_t column, uint16_t row, SeqTrack *seq_track = nullptr, uint8_t merge = 0, diff --git a/avr/cores/megacommand/MCL/Menu.cpp b/avr/cores/megacommand/MCL/Menu.cpp index c2d0ea173..79731ff6b 100644 --- a/avr/cores/megacommand/MCL/Menu.cpp +++ b/avr/cores/megacommand/MCL/Menu.cpp @@ -15,11 +15,12 @@ void MenuBase::enable_entry(uint8_t entry_index, bool en) { bool MenuBase::is_entry_enable(uint8_t entry_index) { auto midx = entry_index / 8; auto bit = entry_index % 8; - return bit_is_set(entry_mask[midx], bit); + return IS_BIT_SET(entry_mask[midx], bit); } menu_function_t MenuBase::get_row_function(uint8_t item_n) { const menu_item_t *item = get_item(item_n); + if (item == nullptr) { return nullptr; } return (menu_function_t)pgm_read_word(menu_target_functions + item->row_function_id); } @@ -38,7 +39,7 @@ const menu_item_t *MenuBase::get_item(uint8_t item_n) { for(uint8_t idx = 0; idx < entry_cnt; ++idx) { if(is_entry_enable(idx)) { if (item_n == 0) { - return get_entry_address(idx); + return get_entry_address(idx); }else { --item_n; } @@ -58,9 +59,12 @@ const char* MenuBase::get_item_name(uint8_t item_n) { return item->name; } -LightPage *MenuBase::get_page_callback(uint8_t item_n) { +PageIndex MenuBase::get_page_callback(uint8_t item_n) { + DEBUG_PRINTLN("get page callback"); auto *item = get_item(item_n); - return (LightPage*)pgm_read_word(menu_target_pages + item->page_callback_id); + DEBUG_PRINTLN(item->page_callback_id); + if (item == nullptr) { return NULL_PAGE; } + return (PageIndex) item->page_callback_id; } uint8_t *MenuBase::get_dest_variable(uint8_t item_n) { diff --git a/avr/cores/megacommand/MCL/Menu.h b/avr/cores/megacommand/MCL/Menu.h index 8959cdbcd..3249dd2fb 100644 --- a/avr/cores/megacommand/MCL/Menu.h +++ b/avr/cores/megacommand/MCL/Menu.h @@ -1,9 +1,10 @@ #pragma once +#include "mcl.h" + #define MAX_MENU_ITEMS 16 typedef void (*menu_function_t)(); -extern const Page* const menu_target_pages[] PROGMEM; extern const menu_function_t menu_target_functions[] PROGMEM; extern const uint8_t* const menu_target_param[] PROGMEM; @@ -18,7 +19,7 @@ struct menu_item_t { uint8_t range; uint8_t number_of_options; uint8_t destination_var_id; // look up the value in menu_target_param - uint8_t page_callback_id; // look up the page callback in menu_target_pages + PageIndex page_callback_id; // look up the page callback in menu_target_pages uint8_t row_function_id; // look up the value in menu_target_functions uint8_t options_begin; }; @@ -27,7 +28,6 @@ template struct menu_t { char name[10]; menu_item_t items[N]; uint8_t exit_function_id; // look up the value in menu_target_functions - uint8_t exit_page_callback_id; }; class MenuBase { @@ -36,8 +36,8 @@ class MenuBase { uint8_t entry_mask[4]; menu_option_t* custom_options; - MenuBase() { - memset(entry_mask, 0xFF, sizeof(entry_mask)); + MenuBase() { + memset(entry_mask, 0xFF, sizeof(entry_mask)); custom_options = nullptr; } @@ -56,7 +56,7 @@ class MenuBase { uint8_t get_option_range(uint8_t item_n); uint8_t get_number_of_options(uint8_t item_n); uint8_t get_options_offset(uint8_t item_n); - LightPage *get_page_callback(uint8_t item_n); + PageIndex get_page_callback(uint8_t item_n); uint8_t get_number_of_items(); const menu_item_t *get_item(uint8_t item_n); const char* get_item_name(uint8_t item_n); diff --git a/avr/cores/megacommand/MCL/MenuPage.cpp b/avr/cores/megacommand/MCL/MenuPage.cpp index 5fe13bda6..fc49906fc 100644 --- a/avr/cores/megacommand/MCL/MenuPage.cpp +++ b/avr/cores/megacommand/MCL/MenuPage.cpp @@ -10,12 +10,14 @@ void MenuPageBase::init() { DEBUG_PRINT("R.Size() = "); DEBUG_PRINTLN(R.Size()); R.restore_menu_layout_deps(); - gen_menu_row_names(); ((MCLEncoder *)encoders[1])->max = get_menu()->get_number_of_items() - 1; + if (((MCLEncoder *)encoders[1])->cur > ((MCLEncoder *)encoders[1])->max) { ((MCLEncoder *)encoders[1])->cur = 0; + cur_row = 0; } + ((MCLEncoder *)encoders[0])->max = get_menu()->get_option_range(encoders[1]->cur) - 1; ((MCLEncoder *)encoders[0])->min = @@ -29,6 +31,19 @@ void MenuPageBase::init() { encoders[1]->old = encoders[1]->cur; } +void MenuPageBase::gen_menu_device_names() { + MenuBase *m = get_menu(); + menu_option_t *p = (menu_option_t *)R.Allocate(sizeof(menu_option_t) * NUM_DEVS); + m->set_custom_options(p); + + for (uint8_t n = 0; n < NUM_DEVS; n++) { + p->pos = n + 1; + strcpy(p->name,midi_active_peering.get_device(n + 1)->name); + p++; + } + +} + void MenuPageBase::gen_menu_row_names() { MenuBase *m = get_menu(); menu_option_t *p = (menu_option_t *)R.Allocate(sizeof(menu_option_t) * 128); @@ -105,7 +120,7 @@ void MenuPageBase::draw_item(uint8_t item_n, uint8_t row) { uint8_t number_of_options = get_menu()->get_number_of_options(item_n); if (get_menu()->get_option_range(item_n) > 0) { - oled_display.print(" "); + oled_display.print(F(" ")); uint8_t *pdest = get_menu()->get_dest_variable(item_n); const char *option_name = get_menu()->get_option_name(item_n, *pdest); if (option_name == NULL) { @@ -166,31 +181,28 @@ void MenuPageBase::display() { bool MenuPageBase::enter() { DEBUG_PRINT_FN(); void (*row_func)() = get_menu()->get_row_function(encoders[1]->cur); - LightPage *page_callback = get_menu()->get_page_callback(encoders[1]->cur); - if (page_callback != NULL) { - DEBUG_PRINTLN("pushing page"); + PageIndex page_callback = get_menu()->get_page_callback(encoders[1]->cur); + if (page_callback != NULL_PAGE) { + DEBUG_PRINTLN("menu pushing page"); DEBUG_PRINTLN((uint16_t)page_callback); - GUI.pushPage(page_callback); + mcl.pushPage(page_callback); return true; } if (row_func != NULL) { DEBUG_PRINTLN(F("calling callback func")); (*row_func)(); - return false; + return true; } + return false; } bool MenuPageBase::exit() { - // Page *exit_page_callback = get_menu()->get_exit_page_callback(); - DEBUG_PRINTLN("calling exit func"); + if (GUI.currentPage() != this) { return; } void (*exit_func)() = get_menu()->get_exit_function(); if (exit_func != NULL) { - (*exit_func)(); - // + (*exit_func)(); } - // if (exit_page_callback != NULL) { - GUI.popPage(); - //} + mcl.popPage(); } bool MenuPageBase::handleEvent(gui_event_t *event) { @@ -230,6 +242,7 @@ bool MenuPageBase::handleEvent(gui_event_t *event) { if (EVENT_PRESSED(event, Buttons.BUTTON4)) { GUI.ignoreNextEvent(event->source); YES: + DEBUG_PRINTLN("YES"); enter(); return true; } diff --git a/avr/cores/megacommand/MCL/MenuPage.h b/avr/cores/megacommand/MCL/MenuPage.h index e9b208e9a..4f8975e58 100644 --- a/avr/cores/megacommand/MCL/MenuPage.h +++ b/avr/cores/megacommand/MCL/MenuPage.h @@ -32,6 +32,7 @@ class MenuPageBase : public LightPage { void select_item(uint8_t item = 0) { cur_row = 0; encoders[1]->cur = 0; + encoders[1]->old = 0; } void loop(); void display(); @@ -39,6 +40,7 @@ class MenuPageBase : public LightPage { void init(); bool enter(); bool exit(); + void gen_menu_device_names(); void gen_menu_row_names(); virtual bool handleEvent(gui_event_t *event); diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.cpp b/avr/cores/megacommand/MCL/MidiActivePeering.cpp index 94063748e..8432312ee 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.cpp +++ b/avr/cores/megacommand/MCL/MidiActivePeering.cpp @@ -1,10 +1,13 @@ #include "MCL_impl.h" #include "ResourceManager.h" -void GenericMidiDevice::init_grid_devices() { +void GenericMidiDevice::init_grid_devices(uint8_t device_idx) { uint8_t grid_idx = 1; + GridDeviceTrack gdt; + for (uint8_t i = 0; i < NUM_EXT_TRACKS; i++) { - add_track_to_grid(grid_idx, i, &(mcl_seq.ext_tracks[i]), EXT_TRACK_TYPE); + gdt.init(EXT_TRACK_TYPE, GROUP_DEV, device_idx, &(mcl_seq.ext_tracks[i])); + add_track_to_grid(grid_idx, i, &gdt); } } @@ -78,7 +81,7 @@ void MidiActivePeering::disconnect(uint8_t port) { if (midi_active_peering.get_device(port)->asElektronDevice()) { turbo_light.set_speed(0, pmidi); } - drivers[i]->disconnect(); + drivers[i]->disconnect(port - 1); } } } @@ -95,7 +98,7 @@ void MidiActivePeering::force_connect(uint8_t port, MidiDevice *driver) { pmidi->device.set_name(driver->name); pmidi->device.set_id(driver->id); } - driver->init_grid_devices(); + driver->init_grid_devices(port - 1); *connected_dev = driver; } @@ -121,7 +124,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, DEBUG_PRINTLN("disconnecting"); for (size_t i = 0; i < nr_drivers; ++i) { if (drivers[i]->connected) - drivers[i]->disconnect(); + drivers[i]->disconnect(port - 1); } // reset MidiID to none pmidi->device.init(); @@ -140,7 +143,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, oled_display.drawBitmap(14, 8, icon, 34, 42, WHITE); } mcl_gui.delay_progress(0); - for (int probe_retry = 0; probe_retry < 6 && !probe_success; + for (uint8_t probe_retry = 0; probe_retry < 6 && !probe_success; ++probe_retry) { DEBUG_PRINTLN("probing..."); probe_success = drivers[i]->probe(); @@ -152,7 +155,7 @@ static void probePort(uint8_t port, MidiDevice *drivers[], size_t nr_drivers, if (probe_success) { pmidi->device.set_id(drivers[i]->id); pmidi->device.set_name(drivers[i]->name); - drivers[i]->init_grid_devices(); + drivers[i]->init_grid_devices(port - 1); *active_device = drivers[i]; //Re-enable MidiClock/Transport recv midi_setup.cfg_clock_recv(); @@ -184,10 +187,12 @@ void MidiActivePeering::run() { resource_loaded = false; //Setting USB turbo speed too early can cause OS upload to fail +#ifndef DEBUGMODE if (turbo_light.tmSpeeds[turbo_light.lookup_speed(mcl_cfg.usb_turbo)] != MidiUartUSB.speed && slowclock > 4000 && usb_set_speed) { turbo_light.set_speed(turbo_light.lookup_speed(mcl_cfg.usb_turbo), MidiUSB.uart); usb_set_speed = false; } +#endif probePort(UART1_PORT, port1_drivers, countof(port1_drivers), &connected_midi_devices[0], resource_buf); diff --git a/avr/cores/megacommand/MCL/MidiActivePeering.h b/avr/cores/megacommand/MCL/MidiActivePeering.h index 474d17ee2..e512693ba 100644 --- a/avr/cores/megacommand/MCL/MidiActivePeering.h +++ b/avr/cores/megacommand/MCL/MidiActivePeering.h @@ -33,7 +33,7 @@ class GenericMidiDevice : public MidiDevice { public: GenericMidiDevice(); virtual bool probe() { return true; } - void init_grid_devices(); + void init_grid_devices(uint8_t device_idx); }; class NullMidiDevice : public MidiDevice { diff --git a/avr/cores/megacommand/MCL/MidiDeviceGrid.h b/avr/cores/megacommand/MCL/MidiDeviceGrid.h new file mode 100644 index 000000000..73c465613 --- /dev/null +++ b/avr/cores/megacommand/MCL/MidiDeviceGrid.h @@ -0,0 +1,65 @@ +#pragma once + +#include "Grid.h" + +#define EMPTY_TRACK_TYPE 0 + +enum GridGroup { + GROUP_DEV, + GROUP_PERF, + GROUP_AUX, + GROUP_TEMPO, +}; + +class SeqTrack; + +class GridDeviceTrack { +public: + uint8_t device_idx; + uint8_t track_type; + GridGroup group_type; + uint8_t mem_slot_idx; + SeqTrack *seq_track; + + GridDeviceTrack() { + init(); + } + + void init(uint8_t _track_type = EMPTY_TRACK_TYPE, GridGroup _group_type = GROUP_DEV, uint8_t _device_idx = 255, SeqTrack *_seq_track = nullptr, uint8_t _mem_slot_idx = 255) { + track_type = _track_type; + group_type = _group_type; + mem_slot_idx = _mem_slot_idx; + seq_track = _seq_track; + device_idx = _device_idx; + } + + SeqTrack *get_seq_track() { return seq_track; } + bool isActive() { return track_type != EMPTY_TRACK_TYPE; } +}; + + +class MidiDeviceGrid : public Grid { + + public: + GridDeviceTrack tracks[GRID_WIDTH]; + + void add_track(uint8_t track_idx, GridDeviceTrack *gdt) { + if (gdt->mem_slot_idx == 255) { gdt->mem_slot_idx = track_idx; } + DEBUG_PRINTLN("adding device track"); + DEBUG_PRINTLN(track_idx); + DEBUG_PRINTLN(gdt->track_type); + DEBUG_PRINTLN(gdt->mem_slot_idx); + memcpy(tracks + track_idx, gdt, sizeof(GridDeviceTrack)); + } + void cleanup(uint8_t device_idx) { + for (uint8_t n = 0; n < GRID_WIDTH; n++) { + if (tracks[n].device_idx == device_idx) { tracks[n].init(); } + } + } + + void init() { + for (uint8_t n = 0; n < GRID_WIDTH; n++) { + tracks[n].init(); + } + } +}; diff --git a/avr/cores/megacommand/MCL/MixerPage.cpp b/avr/cores/megacommand/MCL/MixerPage.cpp index 143810dec..2816a9c98 100644 --- a/avr/cores/megacommand/MCL/MixerPage.cpp +++ b/avr/cores/megacommand/MCL/MixerPage.cpp @@ -1,4 +1,5 @@ #include "MCL_impl.h" +#include "ResourceManager.h" #define FADER_LEN 18 #define FADE_RATE 16 @@ -10,61 +11,78 @@ void MixerPage::set_display_mode(uint8_t param) { } } -static void oled_draw_routing() { - for (int i = 0; i < 16; ++i) { - // draw routing - if (note_interface.is_note(i)) { - - oled_display.fillRect(0 + i * 8, 2, 6, 6, WHITE); - } - - else if (mcl_cfg.routing[i] == 6) { - - oled_display.fillRect(0 + i * 8, 2, 6, 6, BLACK); - oled_display.drawRect(0 + i * 8, 2, 6, 6, WHITE); - - } +void MixerPage::oled_draw_mutes() { + bool is_md_device = (midi_device == &MD); - else { + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + uint8_t fader_x = 0; - oled_display.fillRect(0 + i * 8, 2, 6, 6, BLACK); - oled_display.drawLine(+i * 8, 5, 5 + (i * 8), 5, WHITE); + for (uint8_t i = 0; i < len; ++i) { + // draw routing + SeqTrack *seq_track = is_md_device ? (SeqTrack *)&mcl_seq.md_tracks[i] + : (SeqTrack *)&mcl_seq.ext_tracks[i]; + + uint8_t mute_state = + preview_mute_set != 255 + ? IS_BIT_SET16(mute_sets[!is_md_device].mutes[preview_mute_set], i) + : seq_track->mute_state == SEQ_MUTE_OFF; + + // if (note_interface.is_note(i)) { + // oled_display.fillRect(fader_x, 2, 6, 6, WHITE); + // } else if (mute_state) { + // No Mute (SEQ_MUTE_OFF) + oled_display.fillRect(fader_x, 2, 6, 6, BLACK); + if (mute_state) { + oled_display.drawRect(fader_x, 2, 6, 6, WHITE); + } else { + oled_display.drawLine(fader_x, 5, 5 + (i * 8), 5, WHITE); } + fader_x += 8; } } void MixerPage::setup() { - encoders[0]->handler = encoder_level_handle; - encoders[1]->handler = encoder_filtf_handle; - encoders[2]->handler = encoder_filtw_handle; - encoders[3]->handler = encoder_filtq_handle; - if (route_page.encoders[0]->cur == 0) { - route_page.encoders[0]->cur = 2; - } - oled_display.clearDisplay(); + /* +encoders[0]->handler = encoder_level_handle; +encoders[1]->handler = encoder_filtf_handle; +encoders[2]->handler = encoder_filtw_handle; +encoders[3]->handler = encoder_filtq_handle; +*/ } void MixerPage::init() { level_pressmode = 0; + /* for (uint8_t i = 0; i < 4; i++) { encoders[i]->cur = 64; encoders[i]->old = 64; } + */ + MD.set_key_repeat(0); trig_interface.on(); + MD.set_trigleds(0, TRIGLED_OVERLAY); + preview_mute_set = 255; bool switch_tracks = false; - midi_events.setup_callbacks(); oled_display.clearDisplay(); - oled_draw_routing(); set_display_mode(MODEL_LEVEL); first_track = 255; redraw_mask = -1; + show_mixer_menu = 0; + memset(perf_locks_temp, 255, sizeof(perf_locks_temp)); + // populate_mute_set(); + draw_encoders = false; + redraw_mutes = true; + R.Clear(); + R.use_icons_knob(); + // R.use_machine_param_names(); } void MixerPage::cleanup() { // md_exploit.off(); oled_display.clearDisplay(); + MD.set_key_repeat(1); + disable_record_mutes(); trig_interface.off(); - midi_events.remove_callbacks(); } void MixerPage::set_level(int curtrack, int value) { @@ -73,33 +91,83 @@ void MixerPage::set_level(int curtrack, int value) { // in_sysex = 0; } -void MixerPage::loop() {} +void MixerPage::load_perf_locks(uint8_t state) { + for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { + uint8_t val = perf_locks[state][n]; + if (val < 128) { + encoders[n]->cur = val; + encoders[n]->old = val; + ((PerfEncoder *)encoders[n])->send(); + } + } +} + +void MixerPage::loop() { + constexpr int timeout = 1500; + perf_page.func_enc_check(); + bool old_draw_encoders = draw_encoders; + + if ((trig_interface.is_key_down(MDX_KEY_NO))&& preview_mute_set != 255 && + note_interface.notes_on == 0) { + for (uint8_t n = 0; n < GUI_NUM_ENCODERS; n++) { + if (encoders[n]->hasChanged()) { + if (BUTTON_DOWN(Buttons.ENCODER1 + n)) { + GUI.ignoreNextEvent(Buttons.ENCODER1 + n); + } + perf_locks[preview_mute_set][n] = encoders[n]->cur; + encoders[n]->old = encoders[n]->cur; + } + } + } + + perf_page.encoder_send(); + + if (draw_encoders && trig_interface.is_key_down(MDX_KEY_FUNC)) { + draw_encoders = true; + } else { + draw_encoders = false; + for (uint8_t n = 0; n < 4; n++) { + uint64_t mask = + ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | + ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN) | + ((uint64_t)1 << MDX_KEY_YES); + bool check = (trig_interface.cmd_key_state & mask); + + if (note_interface.notes_on || check) { + encoders_used_clock[n] = slowclock + timeout + 1; + } + if (mcl_gui.show_encoder_value(encoders[n], timeout)) { + draw_encoders = true; + } + } + } + if (draw_encoders != old_draw_encoders) { + if (!draw_encoders) { + redraw(); + } + } + + if (!draw_encoders) { + init_encoders_used_clock(timeout); + } +} void MixerPage::draw_levels() {} void encoder_level_handle(EncoderParent *enc) { + if (mixer_page.midi_device != &MD) { + return; + } + mixer_page.set_display_mode(MODEL_LEVEL); int dir = enc->getValue() - enc->old; int track_newval; - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (note_interface.is_note_on(i)) { - track_newval = MD.kit.levels[i] + dir; - if (track_newval < 0) { - track_newval = 0; - } - if (track_newval > 127) { - track_newval = 127; - } - for (uint8_t level = MD.kit.levels[i]; level < track_newval; level++) { - mixer_page.set_level(i, level); - } - for (uint8_t level = MD.kit.levels[i]; level > track_newval; level--) { - mixer_page.set_level(i, level); - } - // if ((MD.kit.levels[i] < 127) && (MD.kit.levels[i] > 0)) { + track_newval = min(max(MD.kit.levels[i] + dir, 0), 127); mixer_page.set_level(i, track_newval); SET_BIT16(mixer_page.redraw_mask, i); } @@ -108,6 +176,38 @@ void encoder_level_handle(EncoderParent *enc) { enc->old = 64; } +void send_fx(uint8_t param, EncoderParent *enc, uint8_t type) { + // for (int val = enc->old; val > enc->cur; val--) { + MD.sendFXParam(param, enc->cur, type); + // } + // for (int val = enc->old; val > enc->cur; val++) { + // MD.sendFXParam(param, val, type); + // } + PGM_P param_name = NULL; + switch (type) { + case MD_FX_ECHO: + MD.kit.delay[param] = enc->cur; + break; + case MD_FX_DYN: + MD.kit.dynamics[param] = enc->cur; + break; + case MD_FX_REV: + MD.kit.reverb[param] = enc->cur; + break; + case MD_FX_EQ: + MD.kit.eq[param] = enc->cur; + break; + } + char str[4]; + char str2[] = "-- "; + + param_name = fx_param_name(type, param); + strncpy(str, param_name, 4); + mcl_gui.put_value_at(enc->cur, str2); + oled_display.textbox(str, str2); +} + +/* void encoder_filtf_handle(EncoderParent *enc) { mixer_page.adjust_param(enc, MODEL_FLTF); } @@ -123,9 +223,14 @@ void encoder_filtq_handle(EncoderParent *enc) { void encoder_lastparam_handle(EncoderParent *enc) { mixer_page.adjust_param(enc, MD.midi_events.last_md_param); } +*/ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { + if (midi_device != &MD) { + return; + } + set_display_mode(param); int dir = enc->getValue() - enc->old; @@ -133,19 +238,7 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { for (int i = 0; i < 16; i++) { if (note_interface.is_note_on(i)) { - newval = MD.kit.params[i][param] + dir; - if (newval < 0) { - newval = 0; - } - if (newval > 127) { - newval = 127; - } - for (uint8_t value = MD.kit.params[i][param]; value < newval; value++) { - MD.setTrackParam(i, param, value, nullptr, true); - } - for (uint8_t value = MD.kit.params[i][param]; value > newval; value--) { - MD.setTrackParam(i, param, value, nullptr, true); - } + newval = min(max(MD.kit.params[i][param] + dir, 0), 127); MD.setTrackParam(i, param, newval, nullptr, true); SET_BIT16(redraw_mask, i); } @@ -157,58 +250,106 @@ void MixerPage::adjust_param(EncoderParent *enc, uint8_t param) { void MixerPage::display() { auto oldfont = oled_display.getFont(); - - uint8_t fader_level; - uint8_t meter_level; - uint8_t fader_x = 0; - constexpr uint8_t fader_y = 11; - if (oled_display.textbox_enabled) { oled_display.clearDisplay(); - oled_draw_routing(); + oled_draw_mutes(); redraw_mask = -1; } - for (int i = 0; i < 16; i++) { - if (display_mode == MODEL_LEVEL) { - fader_level = MD.kit.levels[i]; - } else { - fader_level = MD.kit.params[i][display_mode]; - } + if (redraw_mutes) { + oled_draw_mutes(); + redraw_mutes = false; + } - fader_level = ((fader_level * 0.00787) * FADER_LEN) + 0; - meter_level = ((disp_levels[i] * 0.00787) * FADER_LEN) + 0; - meter_level = min(fader_level, meter_level); + bool is_md_device = (midi_device == &MD); + constexpr uint8_t fader_y = 11; - if (IS_BIT_SET16(redraw_mask, i)) { - oled_display.fillRect(0 + i * 8, fader_y - 1, 6, FADER_LEN + 1, BLACK); - oled_display.drawRect(fader_x, fader_y + (FADER_LEN - fader_level), 6, - fader_level + 2, WHITE); - } - if (note_interface.is_note_on(i)) { - oled_display.fillRect(fader_x, fader_y + 1 + (FADER_LEN - fader_level), 6, - fader_level, WHITE); - } else { + uint8_t mute_set = preview_mute_set; - oled_display.fillRect(fader_x + 1, - fader_y + 1 + (FADER_LEN - fader_level), 4, - FADER_LEN - meter_level - 1, BLACK); - oled_display.fillRect(fader_x + 1, - fader_y + 1 + (FADER_LEN - meter_level), 4, - meter_level + 1, WHITE); + if (show_mixer_menu && seq_step_page.display_mute_mask(midi_device)) { + oled_draw_mutes(); + } else if (mute_set != 255 && mute_sets[!is_md_device].mutes[mute_set] != + seq_step_page.mute_mask) { + uint16_t mask = mute_sets[!is_md_device].mutes[mute_set]; + if (!is_md_device) { + mask &= 0b111111; } - fader_x += 8; - CLEAR_BIT16(redraw_mask, i); + MD.set_trigleds(mask, TRIGLED_EXCLUSIVE); + seq_step_page.mute_mask = mask; + oled_draw_mutes(); } + if (draw_encoders || preview_mute_set != 255) { + // oled_display.clearDisplay(); + oled_display.fillRect(0, fader_y, 128, 21, BLACK); + for (uint8_t n = 0; n < 4; n++) { + char str1[] = "A"; + str1[0] = 'A' + n; + uint8_t pos = n * 24; + bool highlight = + (preview_mute_set != 255) && (perf_locks[preview_mute_set][n] != 255); // && (trig_interface.is_key_down(MDX_KEY_NO)); + uint8_t val = + highlight ? perf_locks[preview_mute_set][n] : encoders[n]->cur; + mcl_gui.draw_encoder(24 + pos, fader_y + 4, val, highlight); + oled_display.setCursor(16 + pos, fader_y + 6); + oled_display.print(str1); + } + oled_display.display(); + } else { - uint8_t dec = MidiClock.get_tempo() / FADE_RATE; - for (uint8_t n = 0; n < 16; n++) { - if (disp_levels[n] < dec) { - disp_levels[n] = 0; - } else { - disp_levels[n] -= dec; + uint8_t fader_level; + uint8_t meter_level; + uint8_t fader_x = 0; + + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + uint8_t *levels = is_md_device ? disp_levels : ext_disp_levels; + + uint8_t dec = (uint16_t)MidiClock.get_tempo() / FADE_RATE; + + for (int i = 0; i < len; i++) { + + if (is_md_device) { + if (display_mode == MODEL_LEVEL) { + fader_level = MD.kit.levels[i]; + } else { + fader_level = MD.kit.params[i][display_mode]; + } + } else { + fader_level = 127; + } + + fader_level = ((fader_level * 0.00787) * FADER_LEN) + 0; + meter_level = ((levels[i] * 0.00787) * FADER_LEN) + 0; + meter_level = min(fader_level, meter_level); + + if (IS_BIT_SET16(redraw_mask, i)) { + oled_display.fillRect(fader_x, fader_y - 1, 6, FADER_LEN + 1, BLACK); + oled_display.drawRect(fader_x, fader_y + (FADER_LEN - fader_level), 6, + fader_level + 2, WHITE); + } + if (note_interface.is_note_on(i)) { + oled_display.fillRect(fader_x, fader_y + 1 + (FADER_LEN - fader_level), + 6, fader_level, WHITE); + } else { + + oled_display.fillRect(fader_x + 1, + fader_y + 1 + (FADER_LEN - fader_level), 4, + FADER_LEN - meter_level - 1, BLACK); + oled_display.fillRect(fader_x + 1, + fader_y + 1 + (FADER_LEN - meter_level), 4, + meter_level + 1, WHITE); + } + fader_x += 8; + + CLEAR_BIT16(redraw_mask, i); + + if (levels[i] < dec) { + levels[i] = 0; + } else { + levels[i] -= dec; + } } } + if (!redraw_mask) { oled_display.display(); } else { @@ -217,7 +358,157 @@ void MixerPage::display() { oled_display.setFont(oldfont); } +void MixerPage::record_mutes_set(bool state) { + bool is_md_device = (midi_device == &MD); + for (uint8_t i = 0; i < 16; i++) { + if (note_interface.is_note_on(i)) { + if (is_md_device) { + mcl_seq.md_tracks[i].record_mutes = state; + if (!state) + mcl_seq.md_tracks[i].clear_mute(); + } else if (i < mcl_seq.num_ext_tracks) { + mcl_seq.ext_tracks[i].record_mutes = state; + if (!state) + mcl_seq.ext_tracks[i].clear_mute(); + } + } + } +} + +void MixerPage::disable_record_mutes(bool clear) { + for (uint8_t n = 0; n < mcl_seq.num_md_tracks; n++) { + if (n < mcl_seq.num_ext_tracks) { + mcl_seq.ext_tracks[n].record_mutes = false; + if (clear) { + mcl_seq.ext_tracks[n].clear_mute(); + } + } + mcl_seq.md_tracks[n].record_mutes = false; + if (clear) { + mcl_seq.md_tracks[n].clear_mute(); + } + } + if (!seq_step_page.recording) { + clearLed2(); + } +} + +void MixerPage::populate_mute_set() { + if (current_mute_set == 255) { + return; + } + for (uint8_t dev = 0; dev < 2; dev++) { + + uint8_t len = (dev == 0) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + + for (uint8_t n = 0; n < len; n++) { + SeqTrack *seq_track = (dev == 0) ? (SeqTrack *)&mcl_seq.md_tracks[n] + : (SeqTrack *)&mcl_seq.ext_tracks[n]; + if (seq_track->mute_state == SEQ_MUTE_ON) { + CLEAR_BIT16(mute_sets[dev].mutes[current_mute_set], n); + } else { + SET_BIT16(mute_sets[dev].mutes[current_mute_set], n); + } + } + } +} + +void MixerPage::switch_mute_set(uint8_t state) { + + MidiDevice *devs[2] = { + midi_active_peering.get_device(UART1_PORT), + midi_active_peering.get_device(UART2_PORT), + }; + + for (uint8_t dev = 0; dev < 2; dev++) { + + bool is_md_device = dev == 0; + uint8_t len = + (is_md_device) ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + + for (uint8_t n = 0; n < len; n++) { + SeqTrack *seq_track = (is_md_device) ? (SeqTrack *)&mcl_seq.md_tracks[n] + : (SeqTrack *)&mcl_seq.ext_tracks[n]; + + uint8_t mute_set = state; + bool mute_state = IS_BIT_CLEAR16(mute_sets[dev].mutes[state], n); + // Flip + if (state == 4 && devs[dev] == midi_device) { + mute_state = !seq_track->mute_state; + } + // Switch + if (mute_state != seq_track->mute_state) { + devs[dev]->muteTrack(n, mute_state); + if (is_md_device) { + mcl_seq.md_tracks[n].toggle_mute(); + } else { + mcl_seq.ext_tracks[n].toggle_mute(); + } + } + } + } + if (state < 4) { + load_perf_locks(state); + } + oled_draw_mutes(); +} + +uint8_t MixerPage::get_mute_set(uint8_t key) { + switch (key) { + case MDX_KEY_LEFT: + return 1; + case MDX_KEY_UP: + return 2; + case MDX_KEY_RIGHT: + return 3; + } + return 0; +} + +void MixerPage::redraw() { + redraw_mask = -1; + seq_step_page.mute_mask++; + oled_display.clearDisplay(); + oled_draw_mutes(); +} + +void MixerPage::toggle_or_solo(bool solo) { + uint8_t is_md_device = (midi_device == &MD); + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + for (int i = 0; i < len; i++) { + bool note_on = note_interface.is_note_on(i); + bool mute_state = false; + + if (solo) { + if (is_md_device) { + if (mcl_seq.md_tracks[i].mute_state == note_on) { + mcl_seq.md_tracks[i].toggle_mute(); + mute_state = mcl_seq.md_tracks[i].mute_state; + } + } else { + if (mcl_seq.ext_tracks[i].mute_state == note_on) { + mcl_seq.ext_tracks[i].toggle_mute(); + mute_state = mcl_seq.ext_tracks[i].mute_state; + } + } + midi_device->muteTrack(i, !note_on); + } else if (note_on) { + // TOGGLE + if (is_md_device) { + mcl_seq.md_tracks[i].toggle_mute(); + mute_state = mcl_seq.md_tracks[i].mute_state; + } else { + mcl_seq.ext_tracks[i].toggle_mute(); + mute_state = mcl_seq.ext_tracks[i].mute_state; + } + midi_device->muteTrack(i, mute_state); + } + } + oled_draw_mutes(); +} + bool MixerPage::handleEvent(gui_event_t *event) { + if (note_interface.is_event(event)) { uint8_t mask = event->mask; uint8_t port = event->port; @@ -225,15 +516,48 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t track = event->source - 128; + uint8_t is_md_device = (midi_device == &MD); + if (track > 16) { return false; } + if (!show_mixer_menu && preview_mute_set == 255) { + trig_interface.send_md_leds(TRIGLED_OVERLAY); + } - trig_interface.send_md_leds(TRIGLED_OVERLAY); - - if (event->mask == EVENT_BUTTON_PRESSED) { + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + if (event->mask == EVENT_BUTTON_PRESSED && track < len) { if (note_interface.is_note(track)) { - if (first_track == 255) { + if (show_mixer_menu || preview_mute_set != 255) { + + SeqTrack *seq_track = is_md_device + ? (SeqTrack *)&mcl_seq.md_tracks[track] + : (SeqTrack *)&mcl_seq.ext_tracks[track]; + + uint8_t mute_set = preview_mute_set; + + // Toggle active mutes + if (mute_set == 255) { + if (is_md_device) { + mcl_seq.md_tracks[track].toggle_mute(); + } else { + mcl_seq.ext_tracks[track].toggle_mute(); + } + midi_device->muteTrack(track, seq_track->mute_state); + return; + } + + // Toggle preview mutes + bool state = + IS_BIT_SET16(mute_sets[!is_md_device].mutes[mute_set], track); + if (state == SEQ_MUTE_ON) { + CLEAR_BIT16(mute_sets[!is_md_device].mutes[mute_set], track); + } else { + SET_BIT16(mute_sets[!is_md_device].mutes[mute_set], track); + } + + // oled_draw_mutes(); + } else if (first_track == 255 && midi_device == &MD) { first_track = track; MD.setStatus(0x22, track); } @@ -245,15 +569,8 @@ bool MixerPage::handleEvent(gui_event_t *event) { SET_BIT16(redraw_mask, track); if (note_interface.notes_count_on() == 0) { first_track = 255; - // encoder_level_handle(mixer_page.encoders[0]); - if (BUTTON_DOWN(Buttons.BUTTON4)) { - route_page.toggle_routes_batch(); - } - if (BUTTON_DOWN(Buttons.BUTTON1)) { - route_page.toggle_routes_batch(true); - } note_interface.init_notes(); - oled_draw_routing(); + oled_draw_mutes(); } return true; } @@ -272,59 +589,187 @@ bool MixerPage::handleEvent(gui_event_t *event) { uint8_t key = event->source - 64; if (event->mask == EVENT_BUTTON_PRESSED) { switch (key) { + case MDX_KEY_KIT: { + record_mutes_set(false); + // trig_interface.ignore_next_event(GLOBAL); + break; + } + case MDX_KEY_PATSONGKIT: { + bool clear = true; + disable_record_mutes(true); + // trig_interface.ignore_next_event(GLOBAL); + break; + } + case MDX_KEY_EXTENDED: { + if (midi_device == &MD) { + for (uint8_t i = 0; i < 16; i++) { + if (note_interface.is_note_on(i)) { + for (uint8_t c = 0; c < 24; c++) { + MD.restore_kit_param(i, c); + } + } + } + } + break; + } case MDX_KEY_NO: { - if (note_interface.notes_count_on() == 0) { - GUI.setPage(&grid_page); - return true; + uint64_t mask = + ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | + ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN); + if (((trig_interface.cmd_key_state & mask) == 0)) { + if (note_interface.notes_count_on() == 0) { + mcl.setPage(fx_page_a.last_page); + return true; + } + toggle_or_solo(true); + } + break; + } + case MDX_KEY_YES: { + if (preview_mute_set == 255 && + trig_interface.is_key_down(MDX_KEY_FUNC) && + note_interface.notes_on == 0) { + switch_mute_set(4); //---> Flip mutes + break; + } + if (trig_interface.is_key_down(MDX_KEY_LEFT)) { + switch_mute_set(1); + break; + } else if (trig_interface.is_key_down(MDX_KEY_UP)) { + switch_mute_set(2); + break; + } else if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { + switch_mute_set(3); + break; + } else if (trig_interface.is_key_down(MDX_KEY_DOWN)) { + switch_mute_set(0); + break; + } else { + if (!note_interface.notes_on) { + seq_step_page.mute_mask = 0; + show_mixer_menu = true; + } else { + toggle_or_solo(); + } } + break; + } - goto reset_params; + case MDX_KEY_LEFT: + case MDX_KEY_UP: + case MDX_KEY_RIGHT: + case MDX_KEY_DOWN: { + uint8_t set = get_mute_set(key); + if (trig_interface.is_key_down(MDX_KEY_YES)) { + switch_mute_set(set); + } else { + preview_mute_set = set; + for (uint8_t n = 0; n < 4; n++) { + if (perf_locks_temp[n] == 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { + perf_locks_temp[n] = encoders[n]->cur; + encoders[n]->old = encoders[n]->cur; + } + } + // force redraw in display() + seq_step_page.mute_mask++; + } + break; + } + case MDX_KEY_SCALE: { + if (midi_device != &MD) { + midi_device = &MD; + } else { + midi_device = midi_active_peering.get_device(UART2_PORT); + } + redraw(); + break; } } } + if (event->mask == EVENT_BUTTON_RELEASED) { + switch (key) { + case MDX_KEY_GLOBAL: + case MDX_KEY_YES: { + goto global_release; + } + case MDX_KEY_LEFT: + case MDX_KEY_UP: + case MDX_KEY_RIGHT: + case MDX_KEY_DOWN: { + uint64_t mask = + ((uint64_t)1 << MDX_KEY_LEFT) | ((uint64_t)1 << MDX_KEY_UP) | + ((uint64_t)1 << MDX_KEY_RIGHT) | ((uint64_t)1 << MDX_KEY_DOWN) | ((uint64_t)1 << MDX_KEY_YES); + if ((trig_interface.cmd_key_state & mask) == 0) { + trig_interface.send_md_leds(TRIGLED_OVERLAY); + preview_mute_set = 255; + redraw(); + for (uint8_t n = 0; n < 4; n++) { + if (perf_locks_temp[n] != 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { + encoders[n]->cur = perf_locks_temp[n]; + encoders[n]->old = encoders[n]->cur; + } + perf_locks_temp[n] = 255; + } + } + break; + } + } + } + } + if (EVENT_PRESSED(event, Buttons.BUTTON3) && !BUTTON_DOWN(Buttons.BUTTON4)) { + // show_mixer_menu = true; + if (note_interface.notes_on) { + setLed2(); + record_mutes_set(true); + } + return true; + } + + if (EVENT_RELEASED(event, Buttons.BUTTON3)) { + + global_release: + preview_mute_set = 255; + show_mixer_menu = false; + disable_record_mutes(); + MD.set_trigleds(0, TRIGLED_OVERLAY); + redraw(); + return true; } + if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - trig_interface.on(); - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } - if (EVENT_PRESSED(event, Buttons.BUTTON3)) { - reset_params: - for (uint8_t i = 0; i < 16; i++) { - if (note_interface.is_note_on(i)) { - for (uint8_t c = 0; c < 24; c++) { - MD.restore_kit_param(i, c); + if (preview_mute_set != 255 && (trig_interface.is_key_down(MDX_KEY_NO))) { + if (event->source >= Buttons.ENCODER1 && + event->source <= Buttons.ENCODER4) { + uint8_t b = event->source - Buttons.ENCODER1; + if ((event)->mask & EVENT_BUTTON_RELEASED) { + perf_locks[preview_mute_set][b] = 255; + } + if ((event)->mask & EVENT_BUTTON_PRESSED) { + if (perf_locks[preview_mute_set][b] == 255) { + GUI.ignoreNextEvent(event->source); + perf_locks[preview_mute_set][b] = encoders[b]->cur; } - mcl_seq.md_tracks[i].update_params(); } + return true; } - return true; } - /* - if (EVENT_PRESSED(event, Buttons.ENCODER1) || - EVENT_PRESSED(event, Buttons.ENCODER2) || - EVENT_PRESSED(event, Buttons.ENCODER3) || - EVENT_PRESSED(event, Buttons.ENCODER4)) { - // if (note_interface.notes_count() == 0) { - // route_page.update_globals(); - // GUI.setPage(&grid_page); - // } - return true; - } - */ return false; } +/* void MixerMidiEvents::setup_callbacks() { if (state) { return; } Midi.addOnNoteOnCallback( this, (midi_callback_ptr_t)&MixerMidiEvents::onNoteOnCallback_Midi); - Midi.addOnNoteOffCallback( - this, (midi_callback_ptr_t)&MixerMidiEvents::onNoteOffCallback_Midi); + //Midi.addOnNoteOffCallback( + // this, (midi_callback_ptr_t)&MixerMidiEvents::onNoteOffCallback_Midi); Midi.addOnControlChangeCallback( this, (midi_callback_ptr_t)&MixerMidiEvents::onControlChangeCallback_Midi); @@ -350,7 +795,7 @@ void MixerMidiEvents::remove_callbacks() { } void MixerMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { - uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); +uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t param = msg[1]; uint8_t value = msg[2]; uint8_t track; @@ -360,23 +805,29 @@ void MixerMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { if (track > 15) { return; } +} +*/ + +void MixerPage::onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, + uint8_t value) { if (track_param == 32) { + redraw_mutes = true; return; } // don't process mute + if (mixer_page.midi_device != &MD) { + return; + } SET_BIT16(mixer_page.redraw_mask, track); for (int i = 0; i < 16; i++) { if (note_interface.is_note_on(i) && (i != track)) { MD.setTrackParam(i, track_param, value, nullptr, true); - if (track_param < 24) { - mcl_seq.md_tracks[i].update_param(track_param, value); - } SET_BIT16(mixer_page.redraw_mask, i); } } mixer_page.set_display_mode(track_param); } -uint8_t MixerMidiEvents::note_to_trig(uint8_t note_num) { +uint8_t MixerPage::note_to_trig(uint8_t note_num) { uint8_t trig_num = 0; for (uint8_t i = 0; i < sizeof(MD.global.drumMapping); i++) { if (note_num == MD.global.drumMapping[i]) { @@ -385,7 +836,8 @@ uint8_t MixerMidiEvents::note_to_trig(uint8_t note_num) { } return trig_num; } -void MixerMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { + +void MixerPage::onNoteOnCallback_Midi(uint8_t *msg) { uint8_t note_num = msg[1]; uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); @@ -394,4 +846,3 @@ void MixerMidiEvents::onNoteOnCallback_Midi(uint8_t *msg) { mixer_page.disp_levels[n] = MD.kit.levels[n]; } } -void MixerMidiEvents::onNoteOffCallback_Midi(uint8_t *msg) {} diff --git a/avr/cores/megacommand/MCL/MixerPage.h b/avr/cores/megacommand/MCL/MixerPage.h index b27a10df3..77c939310 100644 --- a/avr/cores/megacommand/MCL/MixerPage.h +++ b/avr/cores/megacommand/MCL/MixerPage.h @@ -7,13 +7,17 @@ #include "GUI.h" +class MuteSet { + public: + uint16_t mutes[4]; +}; + class MixerMidiEvents : public MidiCallback { public: bool state; void setup_callbacks(); void remove_callbacks(); - uint8_t note_to_trig(uint8_t note_num); void onNoteOnCallback_Midi(uint8_t *msg); void onNoteOffCallback_Midi(uint8_t *msg); void onControlChangeCallback_Midi(uint8_t *msg); @@ -27,24 +31,61 @@ void encoder_lastparam_handle(EncoderParent *enc); class MixerPage : public LightPage { public: - MixerMidiEvents midi_events; uint8_t level_pressmode = 0; int8_t disp_levels[16]; - char info_line2[9]; + int8_t ext_disp_levels[6]; + + MidiDevice* midi_device; + uint8_t display_mode; uint8_t first_track; uint16_t redraw_mask; + bool redraw_mutes; + bool show_mixer_menu; + + bool draw_encoders; + + uint8_t current_mute_set = 255; + uint8_t preview_mute_set = 255; + void send_fx(uint8_t param, Encoder *enc, uint8_t type); + + //Don't change order + MuteSet mute_sets[2]; + uint8_t perf_locks[4][4]; + // + + uint8_t perf_locks_temp[4]; + + uint8_t get_mute_set(uint8_t key); + MixerPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) { + midi_device = &MD; + memset(mute_sets,0xFF,sizeof(mute_sets)); + memset(perf_locks,0xFF,sizeof(perf_locks)); } void adjust_param(EncoderParent *enc, uint8_t param); - void draw_levels(); + void redraw(); void set_level(int curtrack, int value); void set_display_mode(uint8_t param); + void record_mutes_set(bool state); + void disable_record_mutes(bool clear = false); + void oled_draw_mutes(); + void switch_mute_set(uint8_t state); + void populate_mute_set(); + + void load_perf_locks(uint8_t state); + void toggle_or_solo(bool solo = false); + //Handled in MCLSeq + void onNoteOnCallback_Midi(uint8_t *msg); + void onControlChangeCallback_Midi(uint8_t track, uint8_t track_param, uint8_t value); + + uint8_t note_to_trig(uint8_t note_num); + virtual bool handleEvent(gui_event_t *event); virtual void display(); virtual void loop(); diff --git a/avr/cores/megacommand/MCL/NoteInterface.cpp b/avr/cores/megacommand/MCL/NoteInterface.cpp index 1cd01c774..152b75703 100644 --- a/avr/cores/megacommand/MCL/NoteInterface.cpp +++ b/avr/cores/megacommand/MCL/NoteInterface.cpp @@ -15,14 +15,6 @@ bool NoteInterface::is_note(uint8_t note_num) { return IS_BIT_SET32(mask, note_num); } -bool NoteInterface::is_note_on(uint8_t note_num) { - return IS_BIT_SET32(notes_on, note_num); -} - -bool NoteInterface::is_note_off(uint8_t note_num) { - return IS_BIT_SET32(notes_off, note_num); -} - void NoteInterface::clear_note(uint8_t note_num) { if (note_num < NI_MAX_NOTES) { CLEAR_BIT32(notes_on, note_num); @@ -30,14 +22,6 @@ void NoteInterface::clear_note(uint8_t note_num) { } } -bool NoteInterface::is_event(gui_event_t *event) { - DEBUG_PRINTLN(event->source); - if (event->source >= 128) { - return true; - } - return false; -} - void NoteInterface::add_note_event(uint8_t note_num, uint8_t event_mask, uint8_t port) { gui_event_t event; event.source = note_num + 128; @@ -106,25 +90,9 @@ uint8_t NoteInterface::get_first_md_note() { return 255; } -bool NoteInterface::notes_all_off_md() { - - if (((uint16_t) notes_on == 0) && ((uint16_t)notes_off > 0)) { - return true; - } - return false; -} - -bool NoteInterface::notes_all_off() { - if ((notes_on == 0) && (notes_off > 0)) { - return true; - } - return false; -} - uint8_t NoteInterface::notes_count_on() { return popcount32(notes_on); } - uint8_t NoteInterface::notes_count_off() { return popcount32(notes_off); } diff --git a/avr/cores/megacommand/MCL/NoteInterface.h b/avr/cores/megacommand/MCL/NoteInterface.h index c30424310..64ee3597c 100644 --- a/avr/cores/megacommand/MCL/NoteInterface.h +++ b/avr/cores/megacommand/MCL/NoteInterface.h @@ -30,7 +30,6 @@ class NoteInterface { uint32_t notes_on; uint32_t notes_off; uint32_t notes_ignore; - uint8_t last_note; uint16_t note_hold[NUM_DEVS]; bool note_proceed = false; @@ -43,17 +42,17 @@ class NoteInterface { void add_note_event(uint8_t note_num, uint8_t event_mask, uint8_t port); void note_on_event(uint8_t note_num, uint8_t port); void note_off_event(uint8_t note_num, uint8_t port); - bool is_event(gui_event_t *event); - bool notes_all_off(); - bool notes_all_off_md(); + bool is_event(gui_event_t *event) { return event->source >= 128; } + bool notes_all_off() { return ((notes_on == 0) && (notes_off > 0)); } + bool notes_all_off_md() { return (((uint16_t) notes_on == 0) && ((uint16_t)notes_off > 0)); } + uint8_t notes_count_on(); uint8_t notes_count_off(); uint8_t notes_count(); - uint8_t notes_count_on(); uint8_t get_first_md_note(); bool is_note(uint8_t note_num); - bool is_note_on(uint8_t note_num); - bool is_note_off(uint8_t note_num); + bool is_note_on(uint8_t note_num) { return IS_BIT_SET32(notes_on, note_num); } + bool is_note_off(uint8_t note_num) { return IS_BIT_SET32(notes_off, note_num); } void clear_note(uint8_t note_num); void ignoreNextEvent(uint8_t i) { diff --git a/avr/cores/megacommand/MCL/Osc.h b/avr/cores/megacommand/MCL/Osc.h index 0fc0398a2..c6bc922c1 100644 --- a/avr/cores/megacommand/MCL/Osc.h +++ b/avr/cores/megacommand/MCL/Osc.h @@ -3,7 +3,7 @@ #ifndef OSC_H__ #define OSC_H__ -#include "MCL.h" +#include "mcl.h" #include "math.h" #define SIN_OSC 1 diff --git a/avr/cores/megacommand/MCL/OscMixerPage.cpp b/avr/cores/megacommand/MCL/OscMixerPage.cpp index edc8b19b8..1c45a913f 100644 --- a/avr/cores/megacommand/MCL/OscMixerPage.cpp +++ b/avr/cores/megacommand/MCL/OscMixerPage.cpp @@ -7,7 +7,7 @@ void OscMixerPage::setup() {} void OscMixerPage::init() { WavDesignerPage::init(); trig_interface.off(); - wd.last_page = this; + wd.last_page = mcl.currentPage(); wavdesign_menu_page.menu.enable_entry(1, false); wavdesign_menu_page.menu.enable_entry(2, true); } @@ -37,7 +37,7 @@ void OscMixerPage::display() { oled_display.setCursor(0, 0); oled_display.fillRect(0, 0, 64, 32, BLACK); - oled_display.print("OSC MIXER"); + oled_display.print(F("OSC MIXER")); draw_levels(); scanline_width = 4; draw_wav(); @@ -167,7 +167,7 @@ void OscMixerPage::draw_wav() { void OscMixerPage::draw_levels() { uint8_t scaled_level; char str[17] = " "; - for (int i = 0; i < 3; i++) { + for (uint8_t i = 0; i < 3; i++) { scaled_level = (uint8_t)(((float)encoders[i]->cur / (float)127) * 15); oled_display.fillRect(0 + i * 6, 12 + (15 - scaled_level), 4, diff --git a/avr/cores/megacommand/MCL/OscPage.cpp b/avr/cores/megacommand/MCL/OscPage.cpp index 3727baf4a..0a786b17f 100644 --- a/avr/cores/megacommand/MCL/OscPage.cpp +++ b/avr/cores/megacommand/MCL/OscPage.cpp @@ -8,7 +8,7 @@ uint32_t OscPage::exploit_delay_clock = 0; void OscPage::setup() { for (uint8_t i = 0; i < 16; i++) { - usr_values[i] = random(127); + usr_values[i] = get_random(127); } } @@ -21,8 +21,9 @@ float OscPage::get_freq() { return fout; } void OscPage::init() { + if (wd.last_page != 255 && wd.last_page != WD_PAGE_0 + id) { mcl.setPage(wd.last_page); wd.last_page = 255; return; } WavDesignerPage::init(); - wd.last_page = this; + wd.last_page = mcl.currentPage(); wavdesign_menu_page.menu.enable_entry(1, true); wavdesign_menu_page.menu.enable_entry(2, false); oled_display.clearDisplay(); @@ -44,6 +45,17 @@ bool OscPage::handleEvent(gui_event_t *event) { } trig_interface.send_md_leds(TRIGLED_OVERLAY); } + if (EVENT_CMD(event)) { + uint8_t key = event->source - 64; + if (event->mask == EVENT_BUTTON_PRESSED) { + switch (key) { + case MDX_KEY_NO: + // trig_interface.ignoreNextEvent(MDX_KEY_NO); + show_freq = !show_freq; + return true; + } + } + } if (EVENT_PRESSED(event, Buttons.BUTTON1)) { show_freq = !show_freq; } @@ -74,7 +86,7 @@ void OscPage::loop() { int dir = 0; int16_t newval; int8_t diff = enc_->cur - enc_->old; - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (note_interface.is_note_on(i)) { if (osc_waveform == SIN_OSC) { newval = sine_levels[i] + diff; @@ -129,10 +141,10 @@ void OscPage::display() { switch (osc_waveform) { case 0: draw_wav(0); - oled_display.print("--"); + oled_display.print(F("--")); break; case SIN_OSC: - oled_display.print("SIN"); + oled_display.print(F("SIN")); draw_levels(); for (i = 0; i < 16; i++) { if (sine_levels[i] > 0) { @@ -143,34 +155,34 @@ void OscPage::display() { draw_wav(SIN_OSC); break; case TRI_OSC: - oled_display.print("TRI"); + oled_display.print(F("TRI")); sample_number = 0; draw_wav(TRI_OSC); break; case PUL_OSC: - oled_display.print("PUL"); + oled_display.print(F("PUL")); sample_number = 0; draw_wav(PUL_OSC); break; case SAW_OSC: - oled_display.print("SAW"); + oled_display.print(F("SAW")); sample_number = 0; draw_wav(SAW_OSC); break; case USR_OSC: - oled_display.print("USR"); + oled_display.print(F("USR")); draw_wav(USR_OSC); sample_number = 0; draw_usr(); break; } - oled_display.print(" "); + oled_display.print(F(" ")); - char *str = " "; + char str[] = " "; if (show_freq) { float freq = get_freq(); oled_display.print((int)freq); - oled_display.print("Hz"); + oled_display.print(F("Hz")); // GUI.printf_at(6, "%f", freq); } else { uint8_t s = enc1.cur - 8; @@ -178,9 +190,9 @@ void OscPage::display() { oled_display.print(number_to_note.notes_upper[note]); oled_display.print((uint8_t)floor(s / 12)); if (enc3.cur < 0) { - oled_display.print("-"); + oled_display.print(F("-")); } else { - oled_display.print("+"); + oled_display.print(F("+")); } oled_display.print(enc2.cur); } @@ -280,7 +292,6 @@ void OscPage::draw_usr() { void OscPage::draw_levels() { uint8_t scaled_level; - char str[17] = " "; uint8_t x = 64; uint8_t w = 128 - x; UsrOsc usr_osc(w); diff --git a/avr/cores/megacommand/MCL/PageSelectPage.cpp b/avr/cores/megacommand/MCL/PageSelectPage.cpp index 7c9a2d702..cfd40973a 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.cpp +++ b/avr/cores/megacommand/MCL/PageSelectPage.cpp @@ -15,13 +15,13 @@ static uint8_t get_pageidx(uint8_t page_number) { uint8_t i = 0; for (; i < R.page_entries->countof_Entries; ++i) { if (page_number == R.page_entries->Entries[i].PageNumber) { - break; + return i; } } - return i; + return 255; } -static LightPage *get_page(uint8_t pageidx, char *str) { +static PageIndex get_page(uint8_t pageidx, char *str) { if (pageidx < R.page_entries->countof_Entries) { if (str) { strcpy(str, R.page_entries->Entries[pageidx].Name); @@ -29,9 +29,9 @@ static LightPage *get_page(uint8_t pageidx, char *str) { return R.page_entries->Entries[pageidx].Page; } else { if (str) { - strncpy(str, "----", 5); + strcpy(str, "----"); } - return NULL; + return 255; } } @@ -69,7 +69,7 @@ static void get_category_name(uint8_t page_number, char *str) { get_category_name_fail: if (str) { - strncpy(str, "----", 5); + strcpy(str, "----"); } return; } @@ -88,7 +88,7 @@ void PageSelectPage::init() { oled_display.setFont(&TomThumb); oled_display.setTextColor(BLACK); oled_display.setCursor(47, 6); - oled_display.print("PAGE SELECT"); + oled_display.print(F("PAGE SELECT")); oled_display.setTextColor(WHITE); loop_init = true; @@ -126,7 +126,7 @@ void PageSelectPage::cleanup() { uint8_t PageSelectPage::get_nextpage_down() { for (int8_t i = page_select - 1; i >= 0; i--) { - if (get_page(get_pageidx(i), nullptr)) { + if (get_page(get_pageidx(i), nullptr) != 255) { return i; } } @@ -135,7 +135,7 @@ uint8_t PageSelectPage::get_nextpage_down() { uint8_t PageSelectPage::get_nextpage_up() { for (uint8_t i = page_select + 1; i < 16; i++) { - if (get_page(get_pageidx(i), nullptr)) { + if (get_page(get_pageidx(i), nullptr) != 255) { return i; } } @@ -225,7 +225,7 @@ void PageSelectPage::display() { oled_display.setFont(&TomThumb); oled_display.setTextColor(BLACK); oled_display.setCursor(47, 6); - oled_display.print("PAGE SELECT"); + oled_display.print(F("PAGE SELECT")); oled_display.setTextColor(WHITE); uint8_t label_pos[4] = {30, 57, 81, 104}; for (uint8_t i = 0; i < 4; ++i) { @@ -354,14 +354,14 @@ bool PageSelectPage::handleEvent(gui_event_t *event) { } if (EVENT_RELEASED(event, Buttons.BUTTON2)) { release: - LightPage *p; + PageIndex p; p = get_page(get_pageidx(page_select), nullptr); - if (BUTTON_DOWN(Buttons.BUTTON1) || (!p)) { + if (BUTTON_DOWN(Buttons.BUTTON1) || (p == 255)) { GUI.ignoreNextEvent(Buttons.BUTTON1); // md_exploit.off(); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } else { - GUI.setPage(p); + mcl.setPage(p); } return true; } @@ -369,13 +369,13 @@ bool PageSelectPage::handleEvent(gui_event_t *event) { if (EVENT_PRESSED(event, Buttons.BUTTON1)) { load_grid: GUI.ignoreNextEvent(event->source); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { //PAT SONG - GUI.setPage(&grid_page); - GUI.pushPage(&system_page); + mcl.setPage(GRID_PAGE); + mcl.pushPage(SYSTEM_PAGE); return true; } diff --git a/avr/cores/megacommand/MCL/PageSelectPage.h b/avr/cores/megacommand/MCL/PageSelectPage.h index b09ce67ed..a83cc5391 100644 --- a/avr/cores/megacommand/MCL/PageSelectPage.h +++ b/avr/cores/megacommand/MCL/PageSelectPage.h @@ -17,7 +17,7 @@ struct PageCategory { struct PageSelectEntry { char Name[16]; - LightPage *Page; + PageIndex Page; uint8_t PageNumber; // same as trig id uint8_t CategoryId; uint8_t IconWidth; diff --git a/avr/cores/megacommand/MCL/PerfData.h b/avr/cores/megacommand/MCL/PerfData.h new file mode 100644 index 000000000..95a1eda0a --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfData.h @@ -0,0 +1,293 @@ +/* Copyright Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef PERFDATATRACK_H__ +#define PERFDATATRACK_H__ +#include "WProgram.h" +#include "MCLMemory.h" +#include "MD.h" + +#define PERF_SETTINGS NUM_NUM_PERF_PARAMS + +static uint8_t get_param_device(uint8_t dest, uint8_t param) { + if (dest <= NUM_MD_TRACKS) { + return MD.kit.params[dest - 1][param]; + } else { + switch (dest - NUM_MD_TRACKS - 1) { + case MD_FX_ECHO - MD_FX_ECHO: + return MD.kit.delay[param]; + break; + case MD_FX_DYN - MD_FX_ECHO: + return MD.kit.dynamics[param]; + break; + + case MD_FX_REV - MD_FX_ECHO: + return MD.kit.reverb[param]; + break; + case MD_FX_EQ - MD_FX_ECHO: + return MD.kit.eq[param]; + break; + } + } + return 255; +} + + + +class PerfParam { +public: + uint8_t dest; + uint8_t param; + uint8_t val; + +}; + +#define LEARN_MIN 1 + +class PerfScene { +public: + PerfParam params[NUM_PERF_PARAMS]; + uint8_t count; + PerfScene() { } + + bool is_active() { return count > 0; } + + void init() { + count = 0; + for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { + params[a].dest = 0; + params[a].param = 0; + params[a].val = 255; + } + } + + void debug() { + DEBUG_PRINT("count: "); DEBUG_PRINTLN(count); + for (uint8_t n = 0; n < NUM_PERF_PARAMS; n++) { + DEBUG_PRINT("PARAM "); DEBUG_PRINT(n); + DEBUG_PRINT(" DEST:"); DEBUG_PRINT(params[n].dest); + DEBUG_PRINT(" PARAM:"); DEBUG_PRINT(params[n].param); + DEBUG_PRINT(" DEST:"); DEBUG_PRINT(params[n].dest); + DEBUG_PRINTLN(""); + } + } + + uint8_t add_param(uint8_t dest, uint8_t param, uint8_t value) { + + uint8_t match = 255; + uint8_t empty = 255; + + for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { + // Find first empty + if (params[a].dest == 0) { + if (empty == 255) { empty = a; } + } + if (params[a].dest == dest + 1 && params[a].param == param) { + // Update existing, if matches + match = a; + } + } + + uint8_t b = match; + if (b == 255) { + b = empty; + } + if (b == 255) { + return 255; + } + + params[b].dest = dest + 1; + params[b].param = param; + params[b].val = value; + if (match == 255) { + count++; + } + return b; + } + + void clear_param(uint8_t dest, uint8_t param) { + if (count == 0) { return; } + for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { + // Find match + if (params[a].dest == dest + 1 && params[a].param == param) { + params[a].val = 255; + params[a].dest = 0; + params[a].param = 0; + count--; + } + } + } + + uint8_t find_empty() { + for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { + // Find first empty + if (params[a].dest == 0) { + return a; + } + // Update existing, if matches + } + return 255; + } + + uint8_t find_match(uint8_t dest_, uint8_t param_) { + + for (uint8_t a = 0; a < NUM_PERF_PARAMS; a++) { + if (params[a].dest == dest_ + 1 && params[a].param == param_ && params[a].val != 255) { + return a; + } + } + return 255; + } + + +}; + +class PerfData { +public: + static PerfScene scenes[NUM_SCENES]; + + uint8_t src; + uint8_t param; + uint8_t min; + + + PerfData() { } + + void init() { + src = param = min = 0; + init_params(); + } + + void *data() const { return (void *)&scenes; } + + void update_src(uint8_t src_, uint8_t param_, uint8_t min_) { + src = src_; + param = param_; + min = min_; + } + + uint16_t get_active_scene_mask() { + uint16_t mask = 0; + for (uint8_t n = 0; n < NUM_SCENES; n++) { + if (scenes[n].is_active()) { + mask |= (1 << n); + } + } + return mask; + } + + uint8_t find_match(uint8_t dest_, uint8_t param_, uint8_t scene) { + PerfScene *s = &scenes[scene]; + return s->find_match(dest_, param_); + } + + void clear_param_scene(uint8_t dest_, uint8_t param_, uint8_t scene) { + + PerfScene *s = &scenes[scene]; + s->clear_param(dest_, param_); + + } + + uint8_t add_param(uint8_t dest_, uint8_t param_, uint8_t scene, uint8_t value) { + + PerfScene *s = &scenes[scene]; + return s->add_param(dest_,param_,value); + } + + void clear_scene(uint8_t scene) { + PerfScene *s = &scenes[scene]; + s->init(); + } + + void init_params() { + for (uint8_t n = 0; n < NUM_SCENES; n++) { + clear_scene(n); + } + } + + +}; + +class PerfFade { +public: + PerfFade() { + dest = 0; + param = 0; + min = 255; + max = 255; + } + uint8_t dest; + uint8_t param; + uint8_t min; + uint8_t max; +}; + + +class PerfMorph { +public: + PerfFade fades[NUM_PERF_PARAMS * 2]; + uint8_t count; + PerfMorph() { + } + + uint8_t find_existing(uint8_t dest, uint8_t param) { + for (uint8_t n = 0; n < count; n++) { + PerfFade *f = &fades[n]; + if (f->dest == 0) { return 255; } + if (f->dest == dest && f->param == param) { return n; } + } + return 255; + } + + void populate(PerfScene *s1, PerfScene *s2) { + count = 0; + if (s1 == nullptr && s2 == nullptr) { return; } + if (s1 == nullptr) { + s1 = s2; + s2 = nullptr; + } + for (uint8_t n = 0; n < NUM_PERF_PARAMS; n++) { + PerfFade *f = &fades[count]; + PerfParam *p = &s1->params[n]; + if (p->dest != 0) { + f->dest = p->dest; + f->param = p->param; + uint8_t v = get_param_device(p->dest, p->param); + f->min = p->val == 255 ? v : p->val; + f->max = v; + DEBUG_PRINT("ADDING "); + DEBUG_PRINT(f->min); + DEBUG_PRINT(" "); + DEBUG_PRINT(f->max); + count++; + } + } + if (s2 == nullptr) { return; } + for (uint8_t n = 0; n < NUM_PERF_PARAMS; n++) { + PerfFade *f = &fades[count]; + PerfParam *p = &s2->params[n]; + if (p->dest != 0) { + uint8_t m = find_existing(p->dest, p->param); + uint8_t v = get_param_device(p->dest, p->param); + if (m != 255) { + f = &fades[m]; + DEBUG_PRINTLN("exists"); + } + else { + f->dest = p->dest; + f->param = p->param; + f->min = v; + count++; + DEBUG_PRINTLN("does not exist"); + } + f->max = p->val == 255 ? v : p->val; + DEBUG_PRINT("HERE "); + DEBUG_PRINT(f->min); + DEBUG_PRINT(" "); + DEBUG_PRINT(f->max); + } + } + } +}; + + +#endif /* PERFDATATRACK_H__ */ diff --git a/avr/cores/megacommand/MCL/PerfEncoder.cpp b/avr/cores/megacommand/MCL/PerfEncoder.cpp new file mode 100644 index 000000000..cea092d71 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfEncoder.cpp @@ -0,0 +1,63 @@ +#include "PerfEncoder.h" +#include "MCLMemory.h" +#include "MD.h" +#include "PerfData.h" + +#define DIV_1_127 (1.00f / 127.0f) + +PerfScene PerfData::scenes[NUM_SCENES]; + +void PerfEncoder::send_param(uint8_t dest, uint8_t param, uint8_t val) { + if (dest >= NUM_MD_TRACKS + 4) { + uint8_t channel = dest - NUM_MD_TRACKS - 4; + DEBUG_PRINTLN("send cc"); + DEBUG_PRINT(channel); DEBUG_PRINT(" "); DEBUG_PRINT(param); DEBUG_PRINT(" "); DEBUG_PRINTLN(val); + MidiUart2.sendCC(channel, param, val); + } else if (dest >= NUM_MD_TRACKS) { + MD.sendFXParam(param, val, MD_FX_ECHO + dest - NUM_MD_TRACKS); + } else { + MD.setTrackParam(dest, param, val); + } +} + +void PerfEncoder::send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2) { + PerfMorph morph; + + morph.populate(s1, s2); + + for (uint8_t n = 0; n < morph.count; n++) { + + PerfFade *f = &morph.fades[n]; + DEBUG_PRINTLN("send para"); + DEBUG_PRINTLN(f->max); + DEBUG_PRINTLN(f->min); + + uint8_t val = 0; + if (f->max == 255 || f->min == 255) { + continue; + } + int8_t range = f->max - f->min; + int16_t q = cur_ * range; + DEBUG_PRINTLN("range"); + DEBUG_PRINTLN(range); + DEBUG_PRINTLN(cur); + val = ((int16_t)q / (int16_t)127) + f->min; + if (val > 127) { + continue; + } + DEBUG_PRINTLN(val); + send_param(f->dest - 1, f->param, val); + } +} +void PerfEncoder::send() { + PerfScene *s1 = active_scene_a == 255 ? nullptr : &perf_data.scenes[active_scene_a]; + PerfScene *s2 = active_scene_b == 255 ? nullptr : &perf_data.scenes[active_scene_b]; + send_params(cur, s1, s2); +} + +int PerfEncoder::update(encoder_t *enc) { + MCLEncoder::update(enc); + // Update all params + return cur; +} + diff --git a/avr/cores/megacommand/MCL/PerfEncoder.h b/avr/cores/megacommand/MCL/PerfEncoder.h new file mode 100644 index 000000000..8e7051fb0 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfEncoder.h @@ -0,0 +1,41 @@ +/* Copyright 2018, Justin Mammarella jmamma@gmail.com */ + +#ifndef PERFENCODER_H__ +#define PERFENCODER_H__ + +#include "MCLEncoder.h" +#include "PerfData.h" + +#define PERF_NAME_LENGTH 9 + +class PerfEncoder : public MCLEncoder { + /** + \addtogroup gui_rangeencoder_class + @{ + **/ + + public: + char name[PERF_NAME_LENGTH] = "CONTROL"; + + PerfData perf_data; + + uint8_t active_scene_a = 0; + uint8_t active_scene_b = 1; + + void init() { perf_data.init(); } + void send(); + void send_param(uint8_t dest, uint8_t param, uint8_t val); + void send_params(uint8_t cur_, PerfScene *s1, PerfScene *s2); + /** + Create a new range-limited encoder with max and min value, short + name, initial value, and handling function. The initRangeEncoder + will be called with the constructor arguments. + **/ + PerfEncoder(int _max = 127, int _min = 0, int res = 1) : MCLEncoder(_max , _min, res) { + } + + virtual int update(encoder_t *enc); + +}; + +#endif /* PerfENCODER_H__ */ diff --git a/avr/cores/megacommand/MCL/PerfPage.cpp b/avr/cores/megacommand/MCL/PerfPage.cpp new file mode 100644 index 000000000..94dfec52a --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfPage.cpp @@ -0,0 +1,627 @@ +#include "MCL_impl.h" +#include "MCLMemory.h" + +#define LEARN_MIN 1 +#define LEARN_MAX 2 +#define LEARN_OFF 0 + +void PerfPage::setup() { + DEBUG_PRINT_FN(); + page_mode = PERF_DESTINATION; + perf_param1.init(); + perf_param2.init(); + perf_param3.init(); + perf_param4.init(); + + perf_encoders[0] = &perf_param1; + perf_encoders[1] = &perf_param2; + perf_encoders[2] = &perf_param3; + perf_encoders[3] = &perf_param4; + + perf_param2.active_scene_a = 2; + perf_param2.active_scene_b = 3; + perf_param3.active_scene_a = 4; + perf_param3.active_scene_b = 5; + perf_param4.active_scene_a = 6; + perf_param4.active_scene_b = 7; + + isSetup = true; +} + +void PerfPage::init() { + DEBUG_PRINT_FN(); + PerfPageParent::init(); + trig_interface.on(); + last_mask = last_blink_mask = 0; + show_menu = false; + last_page_mode = 255; + MD.set_rec_mode(3); + config_encoders(); +} + +void PerfPage::set_led_mask() { + uint16_t mask = 0; + + PerfEncoder *e = perf_encoders[perf_id]; + + if (show_menu) { + SET_BIT16(mask, perf_id); + } else { + if (e->active_scene_a < NUM_SCENES) { + SET_BIT16(mask, e->active_scene_a); + } + if (e->active_scene_b < NUM_SCENES) { + SET_BIT16(mask, e->active_scene_b); + } + } + if (last_mask != mask) { + MD.set_trigleds(mask, TRIGLED_EXCLUSIVENDYNAMIC); + } + if (show_menu) { + last_mask = mask; + return; + } + bool blink = true; + + uint16_t blink_mask = 0; + + blink_mask |= e->perf_data.get_active_scene_mask(); + blink_mask &= ~mask; + + if (last_blink_mask != blink_mask) { + MD.set_trigleds(blink_mask, TRIGLED_EXCLUSIVENDYNAMIC, blink); + } + + last_blink_mask = blink_mask; + last_mask = mask; +} + +void PerfPage::cleanup() { + PerfPageParent::cleanup(); + trig_interface.off(); + MD.set_rec_mode(0); +} +void PerfPage::func_enc_check() { + if (trig_interface.is_key_down(MDX_KEY_FUNC)) { + for (uint8_t n = 0; n < 4; n++) { + PerfEncoder *e = perf_encoders[n]; + if (e->hasChanged()) { + int dir = e->cur - e->old; + if (dir < 0) { + e->cur = 0; + } + if (dir > 0) { + e->cur = 127; + } + e->old = e->cur; + e->send(); + } + } + } +} +void PerfPage::config_encoder_range(uint8_t i) { + ((PerfEncoder *)encoders[i])->max = NUM_MD_TRACKS + 4 + 16; + ((PerfEncoder *)encoders[i + 1])->min = 0; + + uint8_t dest = encoders[i]->cur - 1; + if (dest >= NUM_MD_TRACKS + 4) { + ((MCLEncoder *)encoders[i + 1])->max = 127; + } else if (dest >= NUM_MD_TRACKS) { + ((MCLEncoder *)encoders[i + 1])->max = 7; + } else { + ((MCLEncoder *)encoders[i + 1])->max = 23; + } +} + +void PerfPage::config_encoders(uint8_t show_val) { + + encoders[0] = perf_encoders[perf_id]; + encoders[1] = &fx_param2; + encoders[2] = &fx_param3; + encoders[3] = &fx_param4; + + if (page_mode > PERF_DESTINATION) { + if (learn) { + uint8_t scene = learn - 1; + + last_page_mode = page_mode; + + uint8_t c = page_mode - 1; + + PerfEncoder *e = perf_encoders[perf_id]; + PerfParam *p = &e->perf_data.scenes[scene].params[c]; + + encoders[1]->cur = p->dest; + encoders[2]->cur = p->param; + + uint8_t v = p->val; + + if (v == 255) { + v = 0; + } else { + v++; + } + + encoders[3]->cur = v; + ((PerfEncoder *)encoders[3])->max = 128; + + config_encoder_range(1); + } + } + + if (page_mode == PERF_DESTINATION) { + + PerfData *d = &perf_encoders[perf_id]->perf_data; + encoders[1]->cur = d->src; + encoders[2]->cur = d->param; + config_encoder_range(1); + encoders[3]->cur = d->min; + ((PerfEncoder *)encoders[3])->max = 127; + } + + if (!show_val) { + init_encoders_used_clock(); + } +} +void PerfPage::update_params() { + if (show_menu) { + return; + } + uint8_t c = page_mode - 1; + if (page_mode > PERF_DESTINATION) { + config_encoder_range(1); + + if (encoders[1]->hasChanged() && encoders[1]->cur == 0) { + encoders[2]->cur = 0; + } + + if (learn) { + uint8_t scene = learn - 1; + + PerfEncoder *e = perf_encoders[perf_id]; + PerfParam *p = &perf_encoders[perf_id]->perf_data.scenes[scene].params[c]; + p->dest = encoders[1]->cur; + p->param = encoders[2]->cur; + if (encoders[3]->hasChanged() && BUTTON_DOWN(Buttons.ENCODER4)) { GUI.ignoreNextEvent(Buttons.ENCODER4); } + if (encoders[3]->cur > 0) { + if (p->val == 255) { perf_encoders[perf_id]->perf_data.scenes[scene].count++; } + p->val = encoders[3]->cur - 1; + } + } + } else { + config_encoder_range(1); + + if (encoders[1]->hasChanged() && encoders[1]->cur == 0) { + encoders[2]->cur = 0; + } + if (encoders[1]->hasChanged() || encoders[2]->hasChanged() || encoders[3]->hasChanged()) { + PerfData *d = &perf_encoders[perf_id]->perf_data; + d->update_src(encoders[1]->cur, encoders[2]->cur, encoders[3]->cur); + } + } +} + +void PerfPage::loop() { + set_led_mask(); + if (show_menu) { + perf_menu_page.loop(); + return; + } + func_enc_check(); + encoder_send(); + update_params(); +} + +void PerfPage::display() { + if (show_menu) { + constexpr uint8_t width = 52; + oled_display.fillRect(128 - width - 2, 0, width + 2, 32, BLACK); + perf_menu_page.draw_menu(128 - width, 8, width); + return; + } + + oled_display.clearDisplay(); + + auto oldfont = oled_display.getFont(); + + uint8_t x = mcl_gui.knob_x0 + 5; + uint8_t y = 8; + uint8_t lfo_height = 7; + uint8_t width = 13; + + // mcl_gui.draw_vertical_dashline(x, 0, knob_y); + mcl_gui.draw_knob_frame(); + + const char *info1 = ""; + const char *info2 = "PARAMETER"; + + uint8_t scene = learn - 1; + + PerfEncoder *e = perf_encoders[perf_id]; + + char str1[] = " A"; + str1[1] = 'A' + perf_id; + mcl_gui.draw_knob(0, encoders[0], str1); + + if (learn) { + draw_dest(1, encoders[1]->cur); + draw_param(2, encoders[1]->cur, encoders[2]->cur); + + info1 = "LCK> "; + mcl_gui.put_value_at(page_mode, info1 + 4); + + const char *str1 = "LCK"; + uint8_t v = encoders[3]->cur; + bool is_lock = encoders[3]->cur != 0; + if (!is_lock) { + str1 = "OFF"; + // Show the "non-lock" value + uint8_t c = page_mode - 1; + v = 0; //perf_encoders[perf_id]->perf_data.scenes[scene].params[c].val; + } else { + v -= 1; + } + + bool show_value = mcl_gui.show_encoder_value(encoders[3]); + mcl_gui.draw_light_encoder(MCLGUI::knob_x0 + 3 * MCLGUI::knob_w + 7, 6, v, + str1, is_lock, show_value); + + } else { + draw_dest(1, encoders[1]->cur, false); + draw_param(2, encoders[1]->cur, encoders[2]->cur); + mcl_gui.draw_knob(3, encoders[3], "THR"); + strcpy(info2, e->name); + } + + // oled_display.fillCircle(6, 6, 6, WHITE); + oled_display.fillRect(0, 0, 10, 12, WHITE); + oled_display.setFont(&Elektrothic); + oled_display.setCursor(2, 10); + // oled_display.setCursor(4, 10); + oled_display.setTextColor(BLACK, WHITE); + oled_display.print((char)(0x3C + perf_id)); + + if (learn) { + mcl_gui.draw_panel_number(scene + 1); + } + oled_display.setTextColor(WHITE, BLACK); + oled_display.setFont(oldfont); + mcl_gui.draw_panel_labels(info1, info2); + + if (trig_interface.is_key_down(MDX_KEY_LEFT) || + trig_interface.is_key_down(MDX_KEY_RIGHT)) { + oled_display.setCursor(54, MCLGUI::pane_info2_y + 4); + oled_display.print(F("SELECT")); + } + + oled_display.setCursor(80, MCLGUI::pane_info2_y + 4); + char str3[] = "SCENE: A B"; + str3[7] = e->active_scene_a == 255 ? '-' : '1' + e->active_scene_a; + str3[12] = e->active_scene_b == 255 ? '-' : '1' + e->active_scene_b; + oled_display.print(str3); + oled_display.writeFastHLine(109, MCLGUI::pane_info2_y + 1, 5, WHITE); + oled_display.writeFastVLine(109 + ((e->cur * 5) / 128), MCLGUI::pane_info2_y, + 3, WHITE); + oled_display.display(); +} + + +void PerfPage::encoder_check() { + if (GUI.currentPage() == this || mcl.currentPage() == MIXER_PAGE) return; + encoder_send(); +} + +void PerfPage::encoder_send() { + for (uint8_t i = 0; i < 4; i++) { + if (perf_encoders[i]->hasChanged()) { perf_encoders[i]->send(); } + } +} + +void PerfPage::learn_param(uint8_t dest, uint8_t param, uint8_t value) { + // Intercept controller param. + + for (uint8_t i = 0; i < 4; i++) { + PerfData *d = &perf_encoders[i]->perf_data; + if (dest + 1 == d->src && param == d->param) { + // Controller param, start value; + uint8_t min = d->min; + uint8_t max = 127; + if (value >= min) { + int16_t cur = value - min; + int16_t range = max - min; + uint8_t val = (cur * (int16_t)127) / range; + perf_encoders[i]->cur = val; + //perf_encoders[i]->send(); + if (mcl.currentPage() == PERF_PAGE_0) { + update_params(); + } + } + } + } + + if (mcl.currentPage() == PERF_PAGE_0) { + //if (dest >= NUM_MD_TRACKS + 4 && MidiClock.state == 2) { + // return; + //} + if (learn) { + PerfData *d = &perf_encoders[perf_id]->perf_data; + uint8_t scene = learn - 1; + uint8_t n = d->add_param(dest, param, scene, value); + if (n < 255) { + if (dest + 1 <= NUM_MD_TRACKS) { + trig_interface.ignoreNextEvent(param - MD.currentSynthPage * 8 + 16); + } + page_mode = n + 1; + undo = 255; + config_encoders(true); + } + } + + // MIDI LEARN current mode; + uint8_t a = 1; + + if (encoders[a]->cur == 0 && encoders[a + 1]->cur > 0) { + encoders[a]->cur = dest + 1; + encoders[a + 1]->cur = param; + encoders[a + 2]->cur = 0; + update_params(); + config_encoders(); + } + } +} + +void rename_perf() { + const char *my_title = "PerfCtrl Name:"; + + mcl_gui.wait_for_input(perf_page.perf_encoders[perf_page.perf_id]->name, + my_title, 8); +} + +void PerfPage::send_locks(uint8_t scene) { + MDSeqTrack &active_track = mcl_seq.md_tracks[last_md_track]; + uint8_t params[24]; + memset(params, 255, sizeof(params)); + + for (uint8_t n = 0; n < NUM_PERF_PARAMS; n++) { + PerfParam *p = &perf_encoders[perf_id]->perf_data.scenes[scene].params[n]; + uint8_t dest = p->dest; + uint8_t param = p->param; + + if (param >= 24) { + continue; + } + + if (dest == last_md_track + 1) { + params[param] = p->val; + } + } + seq_step_page.disable_paramupdate_events(); + MD.activate_encoder_interface(params); +} + +bool PerfPage::handleEvent(gui_event_t *event) { + + if (PerfPageParent::handleEvent(event)) { + return true; + } + + if (note_interface.is_event(event)) { + uint8_t mask = event->mask; + uint8_t port = event->port; + auto device = midi_active_peering.get_device(port); + + uint8_t track = event->source - 128; + + if (event->mask == EVENT_BUTTON_PRESSED) { + if (track >= NUM_SCENES) { + return true; + } + + if (show_menu) { + if (track < 4) { + perf_id = track; + } + return true; + } + + PerfEncoder *e = perf_encoders[perf_id]; + + if (trig_interface.is_key_down(MDX_KEY_LEFT)) { + e->active_scene_a = e->active_scene_a == track ? 255 : track; + return true; + } + if (trig_interface.is_key_down(MDX_KEY_RIGHT)) { + e->active_scene_b = e->active_scene_b == track ? 255 : track; + return true; + } + + learn = track + 1; + uint8_t scene = track; + send_locks(scene); + config_encoders(); + if (page_mode == PERF_DESTINATION) { + page_mode = last_page_mode == 255 ? 1 : last_page_mode; + config_encoders(); + } + } + if (event->mask == EVENT_BUTTON_RELEASED) { + if (show_menu) { + return true; + } + if (note_interface.notes_all_off()) { + learn = LEARN_OFF; + seq_step_page.enable_paramupdate_events(); + MD.deactivate_encoder_interface(); + page_mode = PERF_DESTINATION; + config_encoders(); + } + } + } + + if (EVENT_CMD(event)) { + uint8_t key = event->source - 64; + if (trig_interface.is_key_down(MDX_KEY_PATSONG)) { + return perf_menu_page.handleEvent(event); + } + switch (key) { + // ENCODER BUTTONS + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: { + if (learn == 0) { + return true; + } + uint8_t scene = learn - 1; + + uint8_t param = MD.currentSynthPage * 8 + key - 0x10; + + PerfData *d = &perf_encoders[perf_id]->perf_data; + if (event->mask == EVENT_BUTTON_RELEASED) { + d->clear_param_scene(last_md_track, param, scene); + } + if (event->mask == EVENT_BUTTON_PRESSED) { + if (d->find_match(last_md_track, param, scene) == 255) { + trig_interface.ignoreNextEvent(key); + d->add_param(last_md_track, param, scene, + MD.kit.params[last_md_track][param]); + } + } + send_locks(scene); + config_encoders(); + return true; + } + } + if (event->mask == EVENT_BUTTON_PRESSED) { + + uint8_t t = note_interface.get_first_md_note(); + if (t < NUM_SCENES) { + switch (key) { + case MDX_KEY_COPY: { + char str[] = "COPY SCENE"; + oled_display.textbox(str, ""); + MD.popup_text(str); + mcl_clipboard.copy_scene( + &perf_encoders[perf_id]->perf_data.scenes[t]); + undo = 255; + return true; + } + case MDX_KEY_PASTE: { + if (undo < NUM_SCENES) { + return; + } + if (mcl_clipboard.paste_scene( + &perf_encoders[perf_id]->perf_data.scenes[t])) { + char str[] = "PASTE SCENE"; + oled_display.textbox(str, ""); + MD.popup_text(str); + config_encoders(); + send_locks(t); + } + return true; + } + case MDX_KEY_CLEAR: { + if (t == undo) { + if (mcl_clipboard.paste_scene( + &perf_encoders[perf_id]->perf_data.scenes[undo])) { + char str[] = "UNDO CLEAR"; + oled_display.textbox(str, ""); + MD.popup_text(str); + undo = 255; + goto end_clear; + } + undo = 255; + return true; + } else { + undo = t; + mcl_clipboard.copy_scene( + &perf_encoders[perf_id]->perf_data.scenes[t]); + } + char str[] = "CLEAR SCENE"; + oled_display.textbox(str, ""); + MD.popup_text(str); + perf_encoders[perf_id]->perf_data.clear_scene(t); + end_clear: + config_encoders(); + send_locks(t); + return true; + } + case MDX_KEY_YES: { + PerfEncoder *e = perf_encoders[perf_id]; + if (t >= NUM_SCENES) { + return true; + } + PerfScene *s1 = &e->perf_data.scenes[t], *s2 = nullptr; + e->send_params(0, s1, s2); + return true; + } + } + } + switch (key) { + case MDX_KEY_UP: { + if (learn && page_mode < NUM_PERF_PARAMS) { + page_mode++; + config_encoders(); + } + return true; + } + case MDX_KEY_DOWN: { + if (learn && page_mode > 1) { + page_mode--; + config_encoders(); + } + return true; + } + } + } + return true; + } + + if (EVENT_RELEASED(event, Buttons.ENCODER4)) { + //if (EVENT_PRESSED(event, Buttons.ENCODER4)) { + if (learn) { + PerfData *d = &perf_encoders[perf_id]->perf_data; + uint8_t scene = learn - 1; + if (encoders[1]->cur != 0 && encoders[2]->cur != 255) { + d->clear_param_scene(encoders[1]->cur - 1 , encoders[2]->cur, scene); + config_encoders(); + } + } + } + + if (EVENT_PRESSED(event, Buttons.BUTTON4)) { + page_mode_up: + page_mode++; + if (page_mode > NUM_PERF_PARAMS) { + page_mode = 0; + } + config_encoders(); + return true; + } + + if (EVENT_PRESSED(event, Buttons.BUTTON3)) { + show_menu = true; + encoders[0] = &seq_menu_value_encoder; + encoders[1] = &seq_menu_entry_encoder; + perf_menu_page.init(); + return true; + } + if (EVENT_RELEASED(event, Buttons.BUTTON3)) { + if (show_menu) { + void (*row_func)() = + perf_menu_page.menu.get_row_function(perf_menu_page.encoders[1]->cur); + if (row_func != NULL) { + DEBUG_PRINTLN("calling menu func"); + (*row_func)(); + } + init(); + } + return true; + } + + return false; +} diff --git a/avr/cores/megacommand/MCL/PerfPage.h b/avr/cores/megacommand/MCL/PerfPage.h new file mode 100644 index 000000000..cb1c6a3cf --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfPage.h @@ -0,0 +1,71 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef PERFPAGE_H__ +#define PERFPAGE_H__ + +#include "GUI.h" +#include "MCLEncoder.h" + +#include "PerfPageParent.h" +#include "PerfEncoder.h" + +#define NUM_PERF_CONTROLS 4 +#define PERF_DESTINATION 0 + +class PerfPage : public LightPage, PerfPageParent { +public: + PerfPage(Encoder *e1 = NULL, Encoder *e2 = NULL, + Encoder *e3 = NULL, Encoder *e4 = NULL) + : LightPage(e1, e2, e3, e4) { + } + + uint8_t undo = 255; + + uint8_t learn = 0; + uint8_t old_mode = 0; + uint8_t last_page_mode; + + bool midi_state = false; + uint8_t page_mode = 0; + uint8_t perf_id = 0; + + uint16_t last_mask = 0; + uint16_t last_blink_mask = 0; + + bool show_menu = false; + + PerfEncoder *perf_encoders[4]; + + bool handleEvent(gui_event_t *event); + void update_params(); + void learn_param(uint8_t dest, uint8_t param, uint8_t value); + + void display(); + void setup(); + + void init(); + void loop(); + void cleanup(); + + void func_enc_check(); + void set_led_mask(); + void config_encoders(uint8_t show_val = false); + + void send_locks(uint8_t mode); + + void config_encoder_range(uint8_t i); + + void encoder_check(); + void encoder_send(); + + void onControlChangeCallback_Midi(uint8_t *msg); + void onControlChangeCallback_Midi2(uint8_t *msg); +}; +extern void rename_perf(); + +extern MCLEncoder perf_page_param1; +extern MCLEncoder perf_page_param2; +extern MCLEncoder perf_page_param3; +extern MCLEncoder perf_page_param4; + +#endif /* PERFPAGE_H__ */ diff --git a/avr/cores/megacommand/MCL/PerfPageParent.cpp b/avr/cores/megacommand/MCL/PerfPageParent.cpp new file mode 100644 index 000000000..0d291bbfd --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfPageParent.cpp @@ -0,0 +1,103 @@ +#include "MCLEncoder.h" +#include "MCL_impl.h" +#include "PerfPageParent.h" +#include "ResourceManager.h" + +void PerfPageParent::setup() { DEBUG_PRINT_FN(); } + +void PerfPageParent::init() { + DEBUG_PRINT_FN(); + MD.set_key_repeat(0); + oled_display.clearDisplay(); + oled_display.setFont(); + config_encoders(); + R.Clear(); + R.use_machine_param_names(); + R.use_icons_knob(); + setup_callbacks(); +} + +void PerfPageParent::cleanup() { MD.set_key_repeat(1); remove_callbacks(); } + +void PerfPageParent::loop() {} + +void PerfPageParent::draw_param(uint8_t knob, uint8_t dest, uint8_t param) { + + char myName[4] = "-- "; + + const char *modelname = NULL; + if (dest == 0) { + if (param > 1) { + strcpy(myName, "LER"); + } + } else { + dest = dest - 1; + if (dest >= NUM_MD_TRACKS + 4) { + mcl_gui.put_value_at(param, myName); + } else if (dest >= NUM_MD_TRACKS) { + modelname = fx_param_name(MD_FX_ECHO + dest - 16, param); + } else { + modelname = model_param_name(MD.kit.get_model(dest), param); + } + + if (modelname != NULL) { + strncpy(myName, modelname, 4); + } + } + mcl_gui.draw_knob(knob, "PAR", myName); +} + +void PerfPageParent::draw_dest(uint8_t knob, uint8_t value, bool dest) { + char K[4]; + K[0] = value > 20 ? 'M' : 'T'; + switch (value) { + case 0: + strcpy(K, "--"); + break; + case 17: + strcpy(K, "ECH"); + break; + case 18: + strcpy(K, "REV"); + break; + case 19: + strcpy(K, "EQ"); + break; + case 20: + strcpy(K, "DYN"); + break; + default: + if (value > 20) { + value -= 20; + } + mcl_gui.put_value_at(value, K + 1); + break; + } + const char *str1 = "DEST"; + if (!dest) { str1 = "SRC"; } + mcl_gui.draw_knob(knob, str1, K); +} + +void PerfPageParent::display() {} + +bool PerfPageParent::handleEvent(gui_event_t *event) { + /* + if (note_interface.is_event(event)) { + uint8_t mask = event->mask; + uint8_t port = event->port; + auto device = midi_active_peering.get_device(port); + + uint8_t track = event->source - 128; + uint8_t page_select = 0; + uint8_t step = track + (page_select * 16); + if (event->mask == EVENT_BUTTON_PRESSED) { + } + } + */ + if (EVENT_PRESSED(event, Buttons.BUTTON2)) { + mcl.setPage(PAGE_SELECT_PAGE); + return true; + } + + return false; +} diff --git a/avr/cores/megacommand/MCL/PerfPageParent.h b/avr/cores/megacommand/MCL/PerfPageParent.h new file mode 100644 index 000000000..ac66187a0 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfPageParent.h @@ -0,0 +1,34 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef PERFPAGEPARENT_H__ +#define PERFPAGEPARENT_H__ + +#include "GUI.h" +#include "MCLEncoder.h" + +class PerfPageParent : public MidiCallback { +public: + + PerfPageParent() { }; + + bool learn = false; + bool midi_state = false; + + + void draw_dest(uint8_t knob, uint8_t value, bool dest = true); + void draw_param(uint8_t knob, uint8_t dest, uint8_t param); + + virtual void display(); + virtual void setup(); + + virtual void init(); + virtual void loop(); + virtual void cleanup(); + virtual void config_encoders() {}; + virtual void setup_callbacks() {}; + virtual void remove_callbacks() {}; + + virtual bool handleEvent(gui_event_t *event); +}; + +#endif /* PERFPAGEPARENT_H__ */ diff --git a/avr/cores/megacommand/MCL/PerfTrack.cpp b/avr/cores/megacommand/MCL/PerfTrack.cpp new file mode 100644 index 000000000..29cb24622 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfTrack.cpp @@ -0,0 +1,90 @@ +#include "MCL_impl.h" + +void PerfTrack::transition_send(uint8_t tracknumber, uint8_t slotnumber) { + DEBUG_PRINTLN("transition send"); +} + +void PerfTrack::transition_load(uint8_t tracknumber, SeqTrack *seq_track, + uint8_t slotnumber) { + DEBUG_PRINTLN("transition send"); + GridTrack::transition_load(tracknumber, seq_track, slotnumber); + load_perf(); +} + +uint16_t PerfTrack::calc_latency(uint8_t tracknumber) { + return 0; +} + +void PerfTrack::get_perf() { + + for (uint8_t n = 0; n < 4; n++) { + PerfEncoder *e = perf_page.perf_encoders[n]; + PerfData *d = &e->perf_data; + encs[n].src = d->src; + encs[n].param = d->param; + encs[n].min = d->min; + encs[n].active_scene_a = e->active_scene_a; + encs[n].active_scene_b = e->active_scene_b; + encs[n].cur = e->cur; + memcpy(encs[n].name,e->name, PERF_NAME_LENGTH); + } + DEBUG_PRINTLN("get perf"); + DEBUG_PRINTLN(sizeof(scenes)); + memcpy(scenes, PerfData::scenes, sizeof(PerfScene) * NUM_SCENES); + memcpy(mute_sets,mixer_page.mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); +} + + +void PerfTrack::load_perf() { + DEBUG_PRINTLN("load perf"); + DEBUG_PRINTLN( sizeof(scenes)); + for (uint8_t n = 0; n < 4; n++) { + PerfEncoder *e = perf_page.perf_encoders[n]; + PerfData *d = &e->perf_data; + d->src = encs[n].src; + d->param = encs[n].param; + d->min = encs[n].min; + e->active_scene_a = encs[n].active_scene_a; + e->active_scene_b = encs[n].active_scene_b; + e->cur = encs[n].cur; + e->old = encs[n].cur; + memcpy(e->name,encs[n].name, PERF_NAME_LENGTH); + } + memcpy(PerfData::scenes, scenes, sizeof(PerfScene) * NUM_SCENES); + memcpy(mixer_page.mute_sets, mute_sets, sizeof(mute_sets) + sizeof(perf_locks)); +} + +void PerfTrack::load_immediate(uint8_t tracknumber, SeqTrack *seq_track) { + DEBUG_PRINTLN("load immediate"); + load_link_data(seq_track); + load_perf(); +} + +bool PerfTrack::store_in_grid(uint8_t column, uint16_t row, + SeqTrack *seq_track, uint8_t merge, + bool online, Grid *grid) { + active = PERF_TRACK_TYPE; + bool ret; + int b = 0; + DEBUG_PRINT_FN(); + uint32_t len; + + if (column != 255 && online == true) { + get_perf(); + if (merge == SAVE_MD) { + link.length = MD.pattern.patternLength; + link.speed = SEQ_SPEED_1X + MD.pattern.doubleTempo; + } + } + + len = sizeof(PerfTrack); + DEBUG_PRINTLN(len); + + ret = write_grid((uint8_t *)(this), len, column, row, grid); + + if (!ret) { + DEBUG_PRINTLN(F("write failed")); + return false; + } + return true; +} diff --git a/avr/cores/megacommand/MCL/PerfTrack.h b/avr/cores/megacommand/MCL/PerfTrack.h new file mode 100644 index 000000000..cc37412b0 --- /dev/null +++ b/avr/cores/megacommand/MCL/PerfTrack.h @@ -0,0 +1,82 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#pragma once + +#include "AUXTrack.h" + +class PerfTrackEncoderData { +public: + char name[PERF_NAME_LENGTH]; + uint8_t src; + uint8_t param; + uint8_t min; + + uint8_t active_scene_a; + uint8_t active_scene_b; + + uint8_t cur; + void init() { + src = param = min = 0; + active_scene_a = 0; + active_scene_b = 1; + const char *str = "CONTROL"; + strcpy(name, str); + } + +}; + +class PerfTrackData { +public: + PerfTrackEncoderData encs[4]; + PerfScene scenes[NUM_SCENES]; + //Don't change order + MuteSet mute_sets[2]; + uint8_t perf_locks[4][4]; + // +}; + +class PerfTrack : public AUXTrack, public PerfTrackData { +public: + + PerfTrack() { + active = PERF_TRACK_TYPE; + static_assert(sizeof(PerfTrack) <= PERF_TRACK_LEN); + } + + virtual void init(uint8_t tracknumber, SeqTrack *seq_track) { + init(); + } + + void init() { + for (uint8_t n = 0; n < NUM_SCENES; n++) { + if (n < 4) { + encs[n].init(); + } + scenes[n].init(); + } + memset(mute_sets, 0xFF, sizeof(mute_sets)); + memset(perf_locks, 255, sizeof(perf_locks)); + } + + void load_perf(); + void get_perf(); + + uint16_t calc_latency(uint8_t tracknumber); + + void transition_send(uint8_t tracknumber, uint8_t slotnumber); + void transition_load(uint8_t tracknumber, SeqTrack *seq_track, uint8_t slotnumber); + bool store_in_grid(uint8_t column, uint16_t row, + SeqTrack *seq_track = nullptr, uint8_t merge = 0, + bool online = false, Grid *grid = nullptr); + + void load_immediate(uint8_t tracknumber, SeqTrack *seq_track); + + virtual uint16_t get_track_size() { return sizeof(PerfTrack); } + virtual uint16_t get_region() { return BANK1_PERF_TRACK_START; } + + virtual uint8_t get_model() { return PERF_TRACK_TYPE; } + virtual uint8_t get_device_type() { return PERF_TRACK_TYPE; } + + virtual void *get_sound_data_ptr() { return &encs; } + virtual size_t get_sound_data_size() { return sizeof(PerfTrackData); } +}; diff --git a/avr/cores/megacommand/MCL/PolyPage.cpp b/avr/cores/megacommand/MCL/PolyPage.cpp index a40fca55b..b3edfab33 100644 --- a/avr/cores/megacommand/MCL/PolyPage.cpp +++ b/avr/cores/megacommand/MCL/PolyPage.cpp @@ -20,24 +20,25 @@ void PolyPage::cleanup() { } void PolyPage::draw_mask() { - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { + uint8_t x = i * 8; if (note_interface.is_note(i)) { - oled_display.fillRect(0 + i * 8, 2, 6, 6, WHITE); + oled_display.fillRect(x, 2, 6, 6, WHITE); } else if (IS_BIT_SET16(*poly_mask, i)) { - oled_display.fillRect(0 + i * 8, 2, 6, 6, BLACK); - oled_display.drawRect(0 + i * 8, 2, 6, 6, WHITE); + oled_display.fillRect(x, 2, 6, 6, BLACK); + oled_display.drawRect(x, 2, 6, 6, WHITE); } else { - oled_display.fillRect(0 + i * 8, 2, 6, 6, BLACK); - oled_display.drawLine(+i * 8, 5, 5 + (i * 8), 5, WHITE); + oled_display.fillRect(x, 2, 6, 6, BLACK); + oled_display.drawLine(x, 5, 5 + x, 5, WHITE); } } } @@ -109,7 +110,7 @@ bool PolyPage::handleEvent(gui_event_t *event) { GUI.ignoreNextEvent(event->source); exit: mcl_cfg.write_cfg(); - GUI.popPage(); + mcl.popPage(); GUI.currentPage()->init(); return true; } diff --git a/avr/cores/megacommand/MCL/Project.cpp b/avr/cores/megacommand/MCL/Project.cpp index 866ddb9a6..a30470de7 100644 --- a/avr/cores/megacommand/MCL/Project.cpp +++ b/avr/cores/megacommand/MCL/Project.cpp @@ -75,7 +75,7 @@ bool Project::new_project_prompt() { if (proj.load_project(newprj)) { grid_page.reload_slot_models = false; DEBUG_PRINTLN("project loaded, setting page to grid"); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } else { gfx.alert("ERROR", "SD ERROR"); @@ -83,7 +83,7 @@ bool Project::new_project_prompt() { } } if (proj.project_loaded) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } return false; diff --git a/avr/cores/megacommand/MCL/Project.h b/avr/cores/megacommand/MCL/Project.h index 5ec9fb96d..efe1a2833 100644 --- a/avr/cores/megacommand/MCL/Project.h +++ b/avr/cores/megacommand/MCL/Project.h @@ -4,12 +4,12 @@ #define PROJECT_H__ #include "Grid.h" +#include "MidiDeviceGrid.h" #include "MCLMemory.h" #include "MCLSysConfig.h" #include "ProjectPages.h" #define PROJ_VERSION 3000 -#define PRJ_NAME_LEN 14 #define PRJ_DIR "/Projects" class ProjectHeader { @@ -25,7 +25,7 @@ class Project : public ProjectHeader { File file; uint8_t grid_select; - Grid grids[NUM_GRIDS]; + MidiDeviceGrid grids[NUM_GRIDS]; void chdir_projects(); bool project_loaded = false; diff --git a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp index d9a3bce8e..6b488a804 100644 --- a/avr/cores/megacommand/MCL/QuestionDialogPage.cpp +++ b/avr/cores/megacommand/MCL/QuestionDialogPage.cpp @@ -10,10 +10,10 @@ void QuestionDialogPage::init(const char* title_, const char* text_) { oled_display.setTextColor(WHITE); oled_display.setCursor(MCLGUI::dlg_info_x2 - 86, MCLGUI::dlg_info_y1 + 23); - oled_display.print(" NO"); + oled_display.print(F(" NO")); oled_display.setCursor(MCLGUI::dlg_info_x2 - 55, MCLGUI::dlg_info_y1 + 23); - oled_display.print(" YES"); + oled_display.print(F(" YES")); oled_display.drawRect(MCLGUI::dlg_info_x2 - 88, MCLGUI::dlg_info_y1 + 16, 18, 9, WHITE); oled_display.drawRect(MCLGUI::dlg_info_x2 - 57, MCLGUI::dlg_info_y1 + 16, 18, 9, WHITE); @@ -71,18 +71,18 @@ bool QuestionDialogPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON4)) { YES_released: return_state = true; - GUI.popPage(); + mcl.popPage(); return true; } if (EVENT_RELEASED(event, Buttons.BUTTON1)) { NO_released: return_state = false; - GUI.popPage(); + mcl.popPage(); return true; } - //GUI.popPage(); + //mcl.popPage(); return false; } diff --git a/avr/cores/megacommand/MCL/RAMPage.cpp b/avr/cores/megacommand/MCL/RAMPage.cpp index 309c7a7bf..556eb0254 100644 --- a/avr/cores/megacommand/MCL/RAMPage.cpp +++ b/avr/cores/megacommand/MCL/RAMPage.cpp @@ -46,6 +46,8 @@ void RAMPage::init() { } } } + R.Clear(); + R.use_icons_knob(); } void RAMPage::cleanup() { oled_display.clearDisplay(); } @@ -83,9 +85,8 @@ void RAMPage::setup_ram_rec(uint8_t track, uint8_t model, uint8_t lev, MDTrack md_track; MDSeqTrack md_seq_track; bool clear_locks = true; - bool send_params = false; - md_seq_track.clear_track(clear_locks, send_params); + md_seq_track.clear_track(clear_locks); md_track.machine.init(); @@ -194,11 +195,10 @@ bool RAMPage::slice(uint8_t track, uint8_t linked_track) { uint8_t track_length = encoders[3]->cur * 4; uint8_t step_inc = track_length / slices; bool clear_locks = true; - bool send_params = false; auto &trk = mcl_seq.md_tracks[track]; auto &ln_trk = mcl_seq.md_tracks[linked_track]; - trk.clear_track(clear_locks, send_params); + trk.clear_track(clear_locks); trk.locks_params[0] = ROM_STRT + 1; trk.locks_params[1] = ROM_END + 1; @@ -235,7 +235,7 @@ bool RAMPage::slice(uint8_t track, uint8_t linked_track) { } case 6: { uint8_t t; - t = random(0, slices); + t = get_random(slices); trk.set_track_locks_i(n, 0, sample_inc * (t) + 0); uint8_t val = (sample_inc) * (t + 1) + 0; trk.set_track_locks_i(n, 1, val); @@ -284,12 +284,10 @@ void RAMPage::setup_ram_play(uint8_t track, uint8_t model, uint8_t pan, MDSeqTrack md_seq_track; bool clear_locks = true; - bool send_params = false; - md_seq_track.clear_track(clear_locks, send_params); + md_seq_track.clear_track(clear_locks); - mcl_seq.md_tracks[track].clear_track( - clear_locks, send_params); // make sure current track does not retrigger + mcl_seq.md_tracks[track].clear_track(clear_locks); // make sure current track does not retrigger md_track.machine.init(); @@ -455,26 +453,26 @@ void RAMPage::display() { oled_display.setCursor(28, 24); switch (RAMPage::rec_states[page_id]) { case STATE_QUEUE: - oled_display.print(" [Queue]"); + oled_display.print(F(" [Queue]")); break; case STATE_RECORD: - oled_display.print(" [Record]"); + oled_display.print(F(" [Record]")); break; case STATE_PLAY: - oled_display.print(" [Play]"); + oled_display.print(F(" [Play]")); break; } oled_display.setFont(&TomThumb); oled_display.setCursor(0, 32); - oled_display.print("RAM "); + oled_display.print(F("RAM ")); oled_display.print(page_id + 1); oled_display.setCursor(105, 32); if (mcl_cfg.ram_page_mode == 0) { - oled_display.print("MONO"); + oled_display.print(F("MONO")); } else { - oled_display.print("LINK"); + oled_display.print(F("LINK")); } oled_display.setFont(); oled_display.setCursor(0, 24); @@ -520,9 +518,9 @@ void RAMPage::display() { } /* oled_display.print(encoders[1]->cur); - oled_display.print(" S:"); + oled_display.print(F(" S:")); oled_display.print(1 << encoders[2]->cur); - oled_display.print(" L:"); + oled_display.print(F(" L:")); oled_display.print(encoders[3]->cur * 4); */ mcl_gui.draw_knob_frame(); @@ -567,32 +565,35 @@ void RAMPage::display() { oled_display.fillRect(progress_x + 1, progress_y, width, 4, WHITE); } + bool flip_hor = false, flip_vert = false; + uint8_t *icon = R.icons_knob->wheel_top; switch (wheel_spin) { case 0: - oled_display.drawBitmap(w_x, w_y, wheel_top, 19, 19, WHITE); break; case 1: - oled_display.drawBitmap(w_x, w_y, wheel_angle, 19, 19, WHITE); + icon = R.icons_knob->wheel_angle; break; case 2: - oled_display.drawBitmap(w_x, w_y, wheel_side, 19, 19, WHITE); + icon = R.icons_knob->wheel_side; break; case 3: - oled_display.drawBitmap(w_x, w_y, wheel_angle, 19, 19, WHITE, false, true); + icon = R.icons_knob->wheel_angle; flip_hor = false; flip_vert = true; break; case 4: - oled_display.drawBitmap(w_x, w_y, wheel_top, 19, 19, WHITE, false, true); + icon = R.icons_knob->wheel_top; flip_hor = false; flip_vert = true; break; case 5: - oled_display.drawBitmap(w_x, w_y, wheel_angle, 19, 19, WHITE, true, true); + icon = R.icons_knob->wheel_angle; flip_hor = true; flip_vert = true; break; case 6: - oled_display.drawBitmap(w_x, w_y, wheel_side, 19, 19, WHITE, true, false); + icon = R.icons_knob->wheel_side; flip_hor = true; flip_vert = false; break; case 7: - oled_display.drawBitmap(w_x, w_y, wheel_angle, 19, 19, WHITE, true, false); + icon = R.icons_knob->wheel_angle; flip_hor = true; flip_vert = false; break; } + oled_display.drawBitmap(w_x, w_y, icon, 19, 19, WHITE, flip_hor, flip_vert); + if ((wheel_spin_last_clock != MidiClock.div16th_counter) && ((RAMPage::rec_states[page_id] == STATE_RECORD) || (RAMPage::rec_states[page_id] == STATE_PLAY))) { @@ -659,9 +660,6 @@ void RAMPage::onControlChangeCallback_Midi(uint8_t *msg) { } */ } else { - if (track_param < 24) { - mcl_seq.md_tracks[n].update_param(track_param, value); - } MD.setTrackParam(n, track_param, value, nullptr, true); } } @@ -714,7 +712,7 @@ bool RAMPage::handleEvent(gui_event_t *event) { EVENT_PRESSED(event, Buttons.ENCODER2) || EVENT_PRESSED(event, Buttons.ENCODER3) || EVENT_PRESSED(event, Buttons.ENCODER4)) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); } if (EVENT_PRESSED(event, Buttons.BUTTON1)) { yes: @@ -770,7 +768,7 @@ bool RAMPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } diff --git a/avr/cores/megacommand/MCL/RoutePage.cpp b/avr/cores/megacommand/MCL/RoutePage.cpp index 42c0630dc..adc59edb5 100644 --- a/avr/cores/megacommand/MCL/RoutePage.cpp +++ b/avr/cores/megacommand/MCL/RoutePage.cpp @@ -27,7 +27,7 @@ void RoutePage::draw_routes() { /*Display 16 track routes on screen, For 16 tracks check to see if there is a route*/ - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if (mcl_cfg.routing[i] != 6) { cur = (char)'A' + mcl_cfg.routing[i]; @@ -99,7 +99,7 @@ void RoutePage::display() { auto *oldfont = oled_display.getFont(); oled_display.clearDisplay(); - oled_display.drawBitmap(0, 0, R.icons_page->icon_route, 24, 16, WHITE); + oled_display.drawBitmap(0, 0, R.icons_page->icon_route, 24, 14, WHITE); mcl_gui.draw_knob_frame(); @@ -160,11 +160,11 @@ bool RoutePage::handleEvent(gui_event_t *event) { // update_globals(); // md_exploit.off(); // md_exploit.on(); - // GUI.setPage(&mixer_page); + // mcl.setPage(MIXER_PAGE); // return true; //} if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } /* @@ -173,7 +173,7 @@ bool RoutePage::handleEvent(gui_event_t *event) { EVENT_PRESSED(event, Buttons.ENCODER3) || EVENT_PRESSED(event, Buttons.ENCODER1)) { update_globals(); - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.cpp b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp new file mode 100644 index 000000000..946ee47d2 --- /dev/null +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.cpp @@ -0,0 +1,423 @@ +#include "MCL_impl.h" + +const char *c_wav_root = "/Samples/WAV"; +const char *c_syx_root = "/Samples/SYX"; +const char *c_wav_suffix = ".wav"; +const char *c_syx_suffix = ".syx"; + +const char *c_wav_name = "WAV"; +const char *c_syx_name = "SYSEX"; + +static bool s_query_returned = false; + +void SampleBrowserPage::setup() { + SD.mkdir(c_wav_root, true); + SD.mkdir(c_syx_root, true); + sysex = &(Midi.midiSysex); + FileBrowserPage::setup(); + _cd(c_wav_root); + position.reset(); +} + +void SampleBrowserPage::display() { + if (filemenu_active) { + draw_menu(); + return; + } + if (FileBrowserPage::selection_change) { + draw_sidebar(); + if (clock_diff(FileBrowserPage::selection_change_clock, slowclock) < 200) { + goto end; + } + FileBrowserPage::selection_change = false; + char temp_entry[FILE_ENTRY_SIZE]; + + get_entry(encoders[1]->getValue(), temp_entry); + uint8_t len = strlen(temp_entry); + + if (len > 4) { + bool is_wav = strcmp(c_wav_suffix, (&temp_entry[len - 4])) == 0; + bool is_syx = strcmp(c_syx_suffix, (&temp_entry[len - 4])) == 0; + Wav wav_file; + + uint32_t size = 0; + + if (is_wav) { + if (!wav_file.open(temp_entry, false)) { goto end; } + oled_display.setCursor(0, 23); + + float sample_rate_f = (wav_file.header.fmt.sampleRate * 0.001f); + uint16_t sample_rate = (uint16_t)sample_rate_f; + oled_display.print(sample_rate); + oled_display.print('.'); + + uint8_t decimal = + ((sample_rate_f - (float)sample_rate) * (float)10.0f) + 0.5f; + oled_display.print(decimal); + oled_display.print(F("k ")); + + oled_display.print(wav_file.header.fmt.bitRate); + oled_display.print('/'); + oled_display.print(wav_file.header.fmt.numChannels); + /* + float seconds = wav_file.header.get_length() / (float)wav_file.header.fmt.sampleRate; + int16_t minutes = seconds * 0.01666666667f; + int16_t ms = ((float)seconds - int(seconds)) * 1000; + */ + /* + oled_display.print(minutes); + oled_display.print(F(":")); + oled_display.print(int(seconds)); + oled_display.print(F(":")); + oled_display.print(ms); + */ + uint32_t size = wav_file.file.size(); + wav_file.close(); + } + else if (is_syx) { + File tmp_file; + if (!tmp_file.open(temp_entry)) { goto end; } + size = tmp_file.size(); + tmp_file.close(); + } + else { goto end; } + oled_display.setCursor(0, 30); + if (size < 1024) { + oled_display.print(size); + oled_display.print('B'); + } + else { + oled_display.print(size / 1024); + oled_display.print(F("kB")); + } + } + } + FileBrowserPage::selection_change = false; +end: + draw_filebrowser(); + oled_display.display(); +} + +void SampleBrowserPage::init(uint8_t show_samplemgr_) { + FileBrowserPage::selection_change = true; + file_types.reset(); + file_types.add(c_wav_suffix); + file_types.add(c_syx_suffix); + strcpy(str_save, "[ RECV ]"); + + trig_interface.off(); + filemenu_active = false; + select_dirs = false; + show_overwrite = false; + show_samplemgr = show_samplemgr_; + + if (show_samplemgr) { + strcpy(title, "MD-ROM"); + encoders[1] = &samplebrowser_param3; + draw_dirs = false; + show_dirs = false; + show_save = false; + show_filemenu = false; + show_new_folder = false; + show_parent = false; + query_sample_slots(); + } else { + strcpy(title, "SAMPLE"); + encoders[1] = &samplebrowser_param2; + if (old_cur_row != 255) { cur_row = old_cur_row; old_cur_row = 255;} + draw_dirs = true; + show_dirs = true; + show_save = true; + show_filemenu = true; + show_new_folder = true; + show_parent = true; + //if (query) { + SD.chdir(lwd); + query_filesystem(); + // } + } + +} + +// send current selected sample file to slot +void SampleBrowserPage::send_sample(int slot, char *newname, bool silent) { + bool success; + if (file.isOpen()) { + char temp_entry[FILE_ENTRY_SIZE]; + file.getName(temp_entry, FILE_ENTRY_SIZE); + file.close(); + bool is_syx = + strcmp(c_syx_suffix, &temp_entry[strlen(temp_entry) - 4]) == 0; + if (!silent) { + if (!mcl_gui.wait_for_confirm("Sample Slot", "Overwrite?")) { + return; + } + } + if (is_syx) { + success = midi_sds.sendSyx(temp_entry, slot); + } else { + char *ptr = newname; + if (newname == nullptr) { + if (isdigit(temp_entry[0]) && isdigit(temp_entry[1]) && + (temp_entry[2] != '.') && (temp_entry[2] != '\0')) { + ptr = temp_entry + 2; + } + } + success = + midi_sds.sendWav(temp_entry, ptr, slot, /* show progress */ true); + } + if (!silent) { + if (success) { + gfx.alert("Sample sent", temp_entry); + } else { + gfx.alert("Send failed", temp_entry); + } + } + } +} + +void SampleBrowserPage::recv_wav(int slot, bool silent) { + char wav_name[FILE_ENTRY_SIZE] = ""; + // should be of form "ID - NAME..." + // ^--~~~~~~~ + // memmove + get_entry(slot, wav_name); + memmove(wav_name + 2, wav_name + 5, FILE_ENTRY_SIZE - 5); + wav_name[FILE_ENTRY_SIZE - 3] = '\0'; + wav_name[FILE_ENTRY_SIZE - 2] = '\0'; + wav_name[FILE_ENTRY_SIZE - 1] = '\0'; + + if (!silent) { + if (!mcl_gui.wait_for_input(wav_name, "Sample Name", + sizeof(wav_name) - 1)) { + return; + } + } + char temp_entry[FILE_ENTRY_SIZE]; + strncpy(temp_entry, wav_name, sizeof(wav_name) - 1); + strcat(temp_entry, ".wav"); + if (SD.exists(temp_entry)) { gfx.alert("File exists!", temp_entry); return; } + DEBUG_PRINTLN("bulk recv"); + DEBUG_PRINTLN(temp_entry); + bool ret = midi_sds.recvWav(temp_entry, slot); + if (!silent) { + if (ret) { + gfx.alert("Sample received", temp_entry); + } else { + gfx.alert("Receive failed", temp_entry); + } + } +} + +void SampleBrowserPage::on_new() { + if (!show_samplemgr) { + pending_action = PA_NEW; + show_ram_slots = true; + init(true); + } else { + // shouldn't happen. + // show_save = false for samplemgr. + init(false); + } +} + +void SampleBrowserPage::on_cancel() { + pending_action = 0; + if (show_samplemgr) { + show_samplemgr = false; + //init(false); + } else { + // TODO cd .. ? + _cd_up(); + } +} + +void SampleBrowserPage::on_select(const char *__) { + if (!show_samplemgr) { + pending_action = PA_SELECT; + show_ram_slots = false; + DEBUG_PRINTLN("on select"); + init(true); + } else { + auto slot = encoders[1]->cur; + switch (pending_action) { + case PA_NEW: + recv_wav(slot); + break; + case PA_SELECT: + send_sample(slot); + break; + } + pending_action = 0; + init(false); + } +} + +bool SampleBrowserPage::handleEvent(gui_event_t *event) { + if (EVENT_PRESSED(event, Buttons.BUTTON3) && show_filemenu) { + FileBrowserPage::handleEvent(event); + bool state = (param2->cur == 0); + file_menu_page.menu.enable_entry(FM_NEW_FOLDER, !state); + file_menu_page.menu.enable_entry(FM_DELETE, !state); // delete + file_menu_page.menu.enable_entry(FM_RENAME, !state); // rename + file_menu_page.menu.enable_entry(FM_OVERWRITE, !state); + file_menu_page.menu.enable_entry(FM_RECVALL, state); + file_menu_page.menu.enable_entry(FM_SENDALL, state); + return true; + } + + if (EVENT_PRESSED(event, Buttons.BUTTON2)) { + mcl.setPage(PAGE_SELECT_PAGE); + return true; + } + + return FileBrowserPage::handleEvent(event); +} + +void SampleBrowserPage::query_sample_slots() { + encoders[1]->cur = 0; + encoders[1]->old = 0; + old_cur_row = cur_row; + numEntries = 0; + cur_file = 255; // XXX why 255? + cur_row = 0; + uint8_t data[2] = {0x70, 0x34}; + call_handle_filemenu = false; + s_query_returned = false; + + sysex->addSysexListener(this); + MD.sendRequest(data, 2); + auto time_start = read_slowclock(); + auto time_now = time_start; + do { + handleIncomingMidi(); + time_now = read_slowclock(); + } while (!s_query_returned && clock_diff(time_start, time_now) < 1000); + + if (!s_query_returned) { + add_entry("ERROR"); + } else if (numEntries == 0) { + add_entry("NON-UW MODEL"); + } else if (show_ram_slots) { + bool mk1 = numEntries < 48; + char ram[] = "R1"; + add_entry(ram); + ram[1]++; + add_entry(ram); + if (!mk1) { + ram[1]++; + add_entry(ram); + ram[1]++; + add_entry(ram); + } + } + ((MCLEncoder *)encoders[1])->max = numEntries - 1; + sysex->removeSysexListener(this); +} + +// MidiSysexListenerClass implementation + +bool SampleBrowserPage::_handle_filemenu() { + if (FileBrowserPage::_handle_filemenu()) { + return true; + } + switch (file_menu_page.menu.get_item_index(file_menu_encoder.cur)) { + case FM_RECVALL: + show_ram_slots = true; + init(true); + if (numEntries == 0) { + gfx.alert("NON", "UW"); + goto end; + } + if (!mcl_gui.wait_for_confirm("Receive all", "Overwrite?")) { + goto end; + } + DEBUG_PRINTLN("Recv samples"); + DEBUG_PRINTLN(numEntries); + for (uint8_t n = 0; n < numEntries; n++) { + DEBUG_PRINTLN("Recv wav"); + char wav_name[FILE_ENTRY_SIZE] = ""; + get_entry(n, wav_name); + DEBUG_PRINTLN(wav_name); + if (wav_name[5] != '[') { + recv_wav(n, true); + } + } + end: + show_ram_slots = false; + init(false); + return true; + case FM_SENDALL: + if (!mcl_gui.wait_for_confirm("Send all", "Overwrite?")) { + return; + } + char wav_name[FILE_ENTRY_SIZE] = ""; + for (uint8_t n = 0; n < numEntries; n++) { + get_entry(n, wav_name); + DEBUG_PRINTLN(wav_name); + if (!isdigit(wav_name[0]) || !isdigit(wav_name[1])) + continue; + uint8_t slot = (wav_name[0] - '0') * 10 + wav_name[1] - '0' - 1; + DEBUG_PRINTLN("slot pos:"); + DEBUG_PRINTLN(slot); + DEBUG_PRINTLN((uint8_t)wav_name[0]); + DEBUG_PRINTLN((uint8_t)wav_name[1]); + if (slot > 48) { + continue; + } + + file.open(wav_name); + mcl_gui.draw_progress("Send Samples", n, numEntries); + send_sample(slot, wav_name + 2, true); + } + break; + } +} +void SampleBrowserPage::start() {} + +void SampleBrowserPage::end() { + if (sysex->getByte(3) != 0x02) + return; + if (sysex->getByte(4) != 0x00) + return; + if (sysex->getByte(5) != 0x72) + return; + if (sysex->getByte(6) != 0x34) + return; + int nr_samplecount = sysex->getByte(7); + if (nr_samplecount > 48) + return; + + char s_tmpbuf[5]; + char temp_entry[FILE_ENTRY_SIZE]; + + for (uint8_t i = 0, j = 7; i < nr_samplecount; ++i) { + for (uint8_t k = 0; k < 5; ++k) { + s_tmpbuf[k] = sysex->getByte(++j); + } + bool slot_occupied = s_tmpbuf[4]; + s_tmpbuf[4] = 0; + strcpy(temp_entry, "00 - "); + if (i < 9) { + mcl_gui.put_value_at(i + 1, temp_entry + 1); + } else { + mcl_gui.put_value_at(i + 1, temp_entry); + } + // put_value_at null-terminates the string. undo that. + temp_entry[2] = ' '; + if (slot_occupied) { + strcat(temp_entry, s_tmpbuf); + } else { + strcat(temp_entry, "[EMPTY]"); + } + add_entry(temp_entry); + } + + s_query_returned = true; +} + +MCLEncoder samplebrowser_param1(0, 1, ENCODER_RES_SYS); +MCLEncoder samplebrowser_param2(0, 36, ENCODER_RES_SYS); +MCLEncoder samplebrowser_param3(0, 36, ENCODER_RES_SYS); + +SampleBrowserPage sample_browser(&samplebrowser_param1, &samplebrowser_param2); diff --git a/avr/cores/megacommand/MCL/SampleBrowserPage.h b/avr/cores/megacommand/MCL/SampleBrowserPage.h new file mode 100644 index 000000000..93fd6a1c4 --- /dev/null +++ b/avr/cores/megacommand/MCL/SampleBrowserPage.h @@ -0,0 +1,55 @@ +/* Justin Mammarella jmamma@gmail.com 2018 */ + +#ifndef SAMPLEBROWSERPAGE_H__ +#define SAMPLEBROWSERPAGE_H__ + +#include "FileBrowserPage.h" +#include "MidiSysex.h" + +#define FT_SND 0 +#define FT_WAV 1 +#define FT_SYX 2 + +#define PA_NEW 0 +#define PA_SELECT 1 + +class SampleBrowserPage : public FileBrowserPage, public MidiSysexListenerClass { + public: + + SampleBrowserPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, + Encoder *e4 = NULL) : FileBrowserPage(e1, e2, e3, e4), MidiSysexListenerClass(){ + ids[0] = 0; + ids[1] = 0x20; + ids[2] = 0x3c; + } + + uint8_t pending_action = 0; + bool show_ram_slots = false; + + uint8_t old_cur_row = 255; + + virtual void on_new(); + virtual void on_select(const char*); + virtual void on_cancel(); + virtual bool handleEvent(gui_event_t *event); + virtual void display(); + + void init(uint8_t show_samplemgr_); + virtual void init() { init(false); } + void setup(); + void send_sample(int slot, char *newname = nullptr, bool silent = false); + void recv_wav(int slot, bool silent = false); + + virtual void start(); + virtual void end(); + virtual bool _handle_filemenu(); + protected: + void query_sample_slots(); +}; + +extern MCLEncoder samplebrowser_param1; +extern MCLEncoder samplebrowser_param2; +extern MCLEncoder samplebrowser_param3; +extern SampleBrowserPage sample_browser; + +#endif /* SAMPLEBROWSERPAGE_H__ */ diff --git a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp index a7f3ba047..45ae2e8a7 100644 --- a/avr/cores/megacommand/MCL/SeqExtStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqExtStepPage.cpp @@ -29,7 +29,7 @@ void SeqExtStepPage::config() { display_page_index = false; } void SeqExtStepPage::config_encoders() { -#ifdef EXT_TRACKS + if (show_seq_menu) { return; } seq_extparam1.max = 127; seq_extparam2.max = 127; @@ -38,23 +38,26 @@ void SeqExtStepPage::config_encoders() { seq_extparam4.min = 4; seq_extparam4.max = 128; + auto &active_track = mcl_seq.ext_tracks[last_ext_track]; + if (encoder_init) { encoder_init = false; - uint8_t timing_mid = mcl_seq.ext_tracks[last_ext_track].get_timing_mid(); + uint8_t timing_mid = active_track.get_timing_mid(); seq_extparam1.cur = 64; seq_extparam2.cur = 64; + seq_extparam4.cur = 16; seq_extparam3.handler = NULL; seq_extparam3.cur = 64; fov_offset = 0; cur_x = 0; - fov_y = 64; + fov_y = MIDI_NOTE_C3 - 1; cur_y = fov_y + 1; cur_w = timing_mid; - seq_extparam4.cur = 16; } + seq_extparam1.old = seq_extparam1.cur; seq_extparam2.old = seq_extparam2.cur; seq_extparam3.old = seq_extparam3.cur; @@ -62,7 +65,6 @@ void SeqExtStepPage::config_encoders() { config(); SeqPage::midi_device = midi_active_peering.get_device(UART2_PORT); -#endif } void SeqExtStepPage::init() { @@ -70,7 +72,6 @@ void SeqExtStepPage::init() { DEBUG_PRINTLN(F("seq extstep init")); midi_device = midi_active_peering.get_device(UART2_PORT); - opt_midi_device_capture = midi_device; SeqPage::init(); param_select = PARAM_OFF; @@ -78,28 +79,23 @@ void SeqExtStepPage::init() { trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); last_cur_x = -1; + config_menu_entries(); config_encoders(); - midi_events.setup_callbacks(); +// midi_events.setup_callbacks(); - // Common menu entries - seq_menu_page.menu.enable_entry(SEQ_MENU_TRACK, true); - seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH, true); - seq_menu_page.menu.enable_entry(SEQ_MENU_CHANNEL, true); - seq_menu_page.menu.enable_entry(SEQ_MENU_PIANOROLL, true); - seq_menu_page.menu.enable_entry(SEQ_MENU_SLIDE, true); } void SeqExtStepPage::cleanup() { SeqPage::cleanup(); - midi_events.remove_callbacks(); +// midi_events.remove_callbacks(); } #define MAX_FOV_W 96 void SeqExtStepPage::draw_seq_pos() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; - uint16_t cur_tick_x = active_track.step_count * active_track.get_timing_mid(); - +active_track.mod12_counter; + uint16_t cur_tick_x = active_track.step_count * active_track.get_timing_mid();// + active_track.mod12_counter; + // Draw sequencer position.. if (is_within_fov(cur_tick_x)) { @@ -113,6 +109,35 @@ void SeqExtStepPage::draw_seq_pos() { void SeqExtStepPage::draw_grid() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; uint8_t h = fov_h / fov_notes; + + uint8_t m = 4, n = 16; + + switch (active_track.speed) { + default: + break; + //case SEQ_SPEED_2X: + //m = 2; n = 8; + //break; + case SEQ_SPEED_3_2X: + case SEQ_SPEED_3_4X: + m = 3; n = 12; + break; + /* + case SEQ_SPEED_3_2X: + m = 3; n = 6; + break; + case SEQ_SPEED_1_2X: + m = 8; n = 32; + break; + case SEQ_SPEED_1_4X: + m = 16; n = 64; + break; + case SEQ_SPEED_1_8X: + m = 32; n = 128; + break; + */ + } + for (uint8_t i = 0; i < active_track.length; i++) { uint16_t grid_tick_x = i * active_track.get_timing_mid(); if (is_within_fov(grid_tick_x)) { @@ -124,17 +149,26 @@ void SeqExtStepPage::draw_grid() { // if ((fov_y + k + i) % 2 == 0) { oled_display.drawPixel( // grid_fov_x, (k * (fov_h / fov_notes)), WHITE); } bool draw = false; + uint8_t v = draw_y + (k * h); if ((pianoroll_mode > 0 && k == 3) || i % 16 == 0) { draw = true; } if (pianoroll_mode == 0) { draw = true; } + if (i % n == 0) { + //if ((fov_y + k + i) % 2 == 0) { + if (k % 2 == 0) { + oled_display.drawLine(grid_fov_x, v, grid_fov_x, v + 4, WHITE); + } + continue; + } if (draw) { - oled_display.drawPixel(grid_fov_x, draw_y + (k * (h)), WHITE); + oled_display.drawPixel(grid_fov_x, v, WHITE); } - if (i % 16 == 0) { - oled_display.drawPixel(grid_fov_x, draw_y + (k * h) + (h / 2), WHITE); + + if (i % m == 0) { + oled_display.drawPixel(grid_fov_x, v + (h / 2), WHITE); } } } @@ -180,20 +214,17 @@ void SeqExtStepPage::draw_lockeditor() { uint16_t next_lock_ev = ev_idx; ev_j_end = ev_end; - if (ev.event_on) { j = active_track.search_lock_idx(pianoroll_mode - 1, i, next_lock_ev, ev_j_end); if (next_lock_ev == 0xFFFF) { next_lock_ev = ev_idx; } - } else { - j = i; - } auto &ev_j = active_track.events[next_lock_ev]; - uint16_t start_x = i * timing_mid + ev.micro_timing - timing_mid; - uint16_t end_x = j * timing_mid + ev_j.micro_timing - timing_mid; + int16_t start_x = i * timing_mid + ev.micro_timing - timing_mid; + int16_t end_x = j * timing_mid + ev_j.micro_timing - timing_mid; + if (start_x == end_x) { end_x = start_x - 1; } if (is_within_fov(start_x, end_x)) { uint8_t start_fov_x, end_fov_x; @@ -201,8 +232,8 @@ void SeqExtStepPage::draw_lockeditor() { uint8_t start_y = ev.event_value; uint8_t end_y = ev_j.event_value; - uint16_t start_x_tmp = start_x; - uint16_t end_x_tmp = end_x; + int16_t start_x_tmp = start_x; + int16_t end_x_tmp = end_x; uint8_t start_y_tmp = start_y; uint8_t end_y_tmp = end_y; @@ -210,7 +241,7 @@ void SeqExtStepPage::draw_lockeditor() { end_x_tmp += roll_length; } float gradient; - if (start_x == end_x) { + if (start_x == end_x || !ev.event_on) { gradient = 0; } else { gradient = @@ -244,10 +275,10 @@ void SeqExtStepPage::draw_lockeditor() { fov_h - (((float)start_y_tmp / 128.0) * (float)fov_h); uint8_t end_fov_y = fov_h - (((float)end_y_tmp / 128.0) * (float)fov_h); - if (!ev.event_on) { + // if (!ev.event_on) { // Draw single lock. - oled_display.fillRect(start_fov_x + draw_x, start_fov_y, 2, 2, WHITE); - } else { + // oled_display.fillRect(start_fov_x + draw_x, start_fov_y, 2, 2, WHITE); + // } else { // Draw Slide if (end_x < start_x) { // Wrap around note @@ -260,8 +291,7 @@ void SeqExtStepPage::draw_lockeditor() { start_y; uint8_t tmp_end_fov_y = fov_h - (((float)end_y_tmp / 128.0) * (float)fov_h); - draw_thick_line(start_fov_x + draw_x, start_fov_y, fov_w + draw_x, - tmp_end_fov_y); + draw_thick_line(start_fov_x + draw_x, start_fov_y, fov_w + draw_x, tmp_end_fov_y); } if (end_x > fov_offset) { @@ -272,25 +302,24 @@ void SeqExtStepPage::draw_lockeditor() { uint8_t tmp_end_fov_y = fov_h - (((float)end_y_tmp / 128.0) * (float)fov_h); - draw_thick_line(draw_x, tmp_end_fov_y, end_fov_x + draw_x, - end_fov_y); + draw_thick_line(draw_x, !ev.event_on ? start_fov_y : tmp_end_fov_y, end_fov_x + draw_x, + !ev.event_on ? start_fov_y : end_fov_y); } } else { // Standard note. draw_thick_line(start_fov_x + draw_x, start_fov_y, - draw_x + end_fov_x, end_fov_y); + draw_x + end_fov_x, !ev.event_on ? start_fov_y : end_fov_y); } } } - } + // } /*if (j < i) { break; }*/ } // Draw interactive cursor int16_t fov_cur_x = (float)(cur_x - fov_offset) * fov_pixels_per_tick; - uint8_t fov_cur_w = (float)(cur_w)*fov_pixels_per_tick; uint8_t fov_cur_y = fov_h - ((float)lock_cur_y / 128.0 * (float)fov_h); oled_display.drawPixel(draw_x + fov_cur_x - 1, draw_y + fov_cur_y - 2, WHITE); @@ -299,6 +328,11 @@ void SeqExtStepPage::draw_lockeditor() { oled_display.drawPixel(draw_x + fov_cur_x, draw_y + fov_cur_y + 1 - 2, WHITE); } +void SeqExtStepPage::draw_note(uint8_t x, uint8_t y, uint8_t w) { + oled_display.drawRect(x, y, w, fov_h / fov_notes, WHITE); + oled_display.fillRect(x + 1, y + 1, w - 2, fov_h / fov_notes - 2, BLACK); +} + void SeqExtStepPage::draw_pianoroll() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; uint8_t timing_mid = active_track.get_timing_mid(); @@ -315,7 +349,7 @@ void SeqExtStepPage::draw_pianoroll() { uint16_t ev_idx = 0, ev_end = 0; uint8_t h = fov_h / fov_notes; - for (int i = 0; i < active_track.length; i++) { + for (uint8_t i = 0; i < active_track.length; i++) { // Update bucket index range ev_end += active_track.timing_buckets.get(i); @@ -336,8 +370,10 @@ void SeqExtStepPage::draw_pianoroll() { } auto &ev_j = active_track.events[note_off_idx]; - uint16_t note_start = i * timing_mid + ev.micro_timing - timing_mid; - uint16_t note_end = j * timing_mid + ev_j.micro_timing - timing_mid; + int16_t note_start = i * timing_mid + ev.micro_timing - timing_mid; + int16_t note_end = j * timing_mid + ev_j.micro_timing - timing_mid; + + if (i > j && j == 0) { note_end += timing_mid * active_track.length; } if (is_within_fov(note_start, note_end)) { uint8_t note_fov_start, note_fov_end; @@ -355,7 +391,9 @@ void SeqExtStepPage::draw_pianoroll() { } else { note_fov_end = (float)(note_end - fov_offset) * fov_pixels_per_tick; } - + //On screen notes to be no less than 2 pixels, regardless of zoom + if (i < j && note_fov_end - note_fov_start < 2) { note_fov_end = note_fov_start + 2; } + //if (note_fov_end <= note_fov_start) { note_fov_end = note_fov_start + 1; } uint8_t note_fov_y = fov_h - ((note_val - fov_y) * (fov_h / fov_notes)); // Draw vertical projection uint8_t proj_y = 255; @@ -373,12 +411,12 @@ void SeqExtStepPage::draw_pianoroll() { if (note_start < fov_offset + fov_length) { oled_display.drawRect(note_fov_start + draw_x, proj_y, - pattern_end_fov_x - note_fov_start, 1, + pattern_end_fov_x - note_fov_start, 1, WHITE); } if (note_end > fov_offset) { - oled_display.drawRect(draw_x, proj_y, note_fov_end, 1, WHITE); + oled_display.drawRect(draw_x, proj_y, note_fov_end, 1, WHITE); } } else { @@ -392,22 +430,19 @@ void SeqExtStepPage::draw_pianoroll() { if (note_end < note_start) { // Wrap around note if (note_start < fov_offset + fov_length) { - oled_display.drawRect(note_fov_start + draw_x, + draw_note(note_fov_start + draw_x, draw_y + note_fov_y, - pattern_end_fov_x - note_fov_start, - (fov_h / fov_notes), WHITE); + pattern_end_fov_x - note_fov_start); } if (note_end > fov_offset) { - oled_display.drawRect(draw_x, draw_y + note_fov_y, note_fov_end, - (fov_h / fov_notes), WHITE); + draw_note(draw_x, draw_y + note_fov_y, note_fov_end); } } else { // Standard note. - oled_display.drawRect(note_fov_start + draw_x, draw_y + note_fov_y, - note_fov_end - note_fov_start, - (fov_h / fov_notes), WHITE); + draw_note(note_fov_start + draw_x, draw_y + note_fov_y, + note_fov_end - note_fov_start); } } } @@ -416,7 +451,7 @@ void SeqExtStepPage::draw_pianoroll() { // Draw interactive cursor uint8_t fov_cur_y = fov_h - ((cur_y - fov_y) * ((fov_h) / fov_notes)); int16_t fov_cur_x = (float)(cur_x - fov_offset) * fov_pixels_per_tick; - uint8_t fov_cur_w = (float)(cur_w)*fov_pixels_per_tick; + uint8_t fov_cur_w = ceil((float)(cur_w)*fov_pixels_per_tick); if (fov_cur_x < 0) { fov_cur_x = 0; } @@ -432,8 +467,11 @@ void SeqExtStepPage::draw_pianoroll() { void SeqExtStepPage::draw_viewport_minimap() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; uint8_t timing_mid = active_track.get_timing_mid(); + constexpr uint16_t width = pidx_w * 4 + 3; - uint16_t pattern_end = active_track.length * timing_mid; + + uint16_t pattern_end = max(16,active_track.length) * timing_mid; + uint16_t cur_tick_x = active_track.step_count * timing_mid + active_track.mod12_counter; @@ -445,15 +483,14 @@ void SeqExtStepPage::draw_viewport_minimap() { uint16_t s = fov_offset * (width - 1) / pattern_end; uint16_t w = fov_length * (width - 2) / pattern_end; uint16_t p = min(width, cur_tick_x * (width - 1) / pattern_end); + oled_display.drawFastHLine(pidx_x0 + 1 + s, pidx_y + 1, w, WHITE); + oled_display.drawPixel(pidx_x0 + 1 + p, pidx_y + 1, INVERT); } -void SeqExtStepPage::draw_note(uint8_t note_val, uint16_t note_start, - uint16_t note_end) {} - void SeqExtStepPage::pos_cur_x(int16_t diff) { - uint8_t w = cur_w; + uint16_t w = cur_w; if (pianoroll_mode >= 1) { w = 3; } @@ -473,12 +510,18 @@ void SeqExtStepPage::pos_cur_x(int16_t diff) { } } else { - if (cur_x >= fov_offset + fov_length - w) { - if (fov_offset + fov_length + diff < roll_length) { + if (cur_x + w >= fov_offset + fov_length) { + if (fov_offset + fov_length < roll_length) { fov_offset += diff; cur_x = fov_offset + fov_length - w; } - } else { + else { + if (cur_x + diff < roll_length) { + cur_x += diff; + // cur_w = roll_length - cur_x; + } + } + } else { cur_x += diff; if (cur_x > fov_offset + fov_length - w) { cur_x = fov_offset + fov_length - w; @@ -488,7 +531,7 @@ void SeqExtStepPage::pos_cur_x(int16_t diff) { } void SeqExtStepPage::set_cur_y(uint8_t cur_y_) { - if (GUI.currentPage() != this || show_seq_menu) { return; } + if (mcl.currentPage() != SEQ_EXTSTEP_PAGE || show_seq_menu) { return; } uint8_t fov_y_ = fov_y; if (fov_y >= cur_y_ && cur_y_ != 0) { fov_y_ = cur_y_ - 1; @@ -498,15 +541,17 @@ void SeqExtStepPage::set_cur_y(uint8_t cur_y_) { // if (MidiClock.state != 2) { fov_y = fov_y_; cur_y = cur_y_; - for (uint8_t n = 0; n < 16; n++) { if (note_interface.is_note_on(n)) { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; uint8_t timing_mid = active_track.get_timing_mid(); - active_track.del_note(fov_offset + timing_mid * n, cur_w - 1, cur_y); - active_track.add_note(fov_offset + timing_mid * n, cur_w, cur_y, velocity, - cond); + uint16_t pos = fov_offset + timing_mid * n; + uint16_t w = cur_w; + if (pos + w >= roll_length) { w = roll_length - pos - 1; } + + active_track.del_note(pos, w - 1, cur_y); + active_track.add_note(pos, w, cur_y, velocity, cond); } } @@ -556,7 +601,7 @@ void SeqExtStepPage::pos_cur_w(int16_t diff) { cur_w += diff; cur_w = max(cur_w, cur_w_min); } else { - if (cur_x >= fov_offset + fov_length - cur_w - diff) { + if (cur_x + cur_w >= fov_offset + fov_length) { if (fov_offset + fov_length + diff < roll_length) { cur_w += diff; fov_offset += diff; @@ -566,8 +611,12 @@ void SeqExtStepPage::pos_cur_w(int16_t diff) { } } } - -void SeqExtStepPage::loop() { +void SeqExtStepPage::config_menu_entries() { + seq_menu_page.menu.enable_entry(SEQ_MENU_PIANOROLL, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_TRACK, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_CHANNEL, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_EXT, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_AUTOMATION, true); if (pianoroll_mode == 0) { seq_menu_page.menu.enable_entry(SEQ_MENU_ARP, true); @@ -587,13 +636,18 @@ void SeqExtStepPage::loop() { seq_menu_page.menu.enable_entry(SEQ_MENU_CLEAR_LOCKS, true); seq_menu_page.menu.enable_entry(SEQ_MENU_SLIDE, true); } + +} + +void SeqExtStepPage::loop() { + config_menu_entries(); auto &active_track = mcl_seq.ext_tracks[last_ext_track]; uint8_t timing_mid = active_track.get_timing_mid(); SeqPage::loop(); // If pianoroll_edit mode changed. if (show_seq_menu) { - display_ext_mute_mask(); + display_mute_mask(midi_device, 8); if (last_pianoroll_mode != pianoroll_mode) { if (pianoroll_mode > 0) { @@ -644,40 +698,66 @@ void SeqExtStepPage::loop() { } seq_extparam3.cur = 64; seq_extparam3.old = 64; -} - -void SeqExtStepPage::display() { -#ifdef EXT_TRACKS - oled_display.clearDisplay(); - - auto &active_track = mcl_seq.ext_tracks[last_ext_track]; - uint8_t timing_mid = active_track.get_timing_mid(); roll_length = active_track.length * timing_mid; // in ticks - // FOV offsets - if (seq_extparam4.cur > zoom_max) { - seq_extparam4.cur = zoom_max; + seq_extparam4.cur = zoom_max; } - if (seq_extparam4.cur > active_track.length) { - seq_extparam4.cur = active_track.length; + + if (cur_w > roll_length) { cur_w = roll_length / 2; } + + int fov_length_new = active_track.length * timing_mid * fov_pixels_per_tick; + if (fov_length_new < fov_w) { + seq_extparam4.cur = active_track.length * active_track.get_speed_multiplier(); + if (seq_extparam4.cur > zoom_max) { + seq_extparam4.cur = zoom_max; + } + fov_length = fov_w; + + goto change; +// fov_offset = 0; +// cur_x = 0; } + if (seq_extparam4.hasChanged()) { + change: + uint8_t fov_zoom = seq_extparam4.cur; - uint8_t fov_zoom = seq_extparam4.cur; + fov_length = fov_zoom * timing_mid; // how many ticks to display on screen. + if (fov_length > roll_length) { fov_length = roll_length; } + + int x = cur_x - fov_offset; + + int fov_old_x = x * fov_pixels_per_tick; + + fov_pixels_per_tick = (float)fov_w / (float)fov_length; + + int fov_cur_x = x * fov_pixels_per_tick; + + int offset = (fov_cur_x - fov_old_x) / fov_pixels_per_tick; + + fov_offset += offset; + + if (fov_length + fov_offset > roll_length) { + fov_offset = roll_length - fov_length; + } + fov_offset = max(0,fov_offset); - fov_length = fov_zoom * timing_mid; // how many ticks to display on screen. - if (fov_length + fov_offset > roll_length) { - fov_offset = roll_length - fov_length; } - fov_pixels_per_tick = (float)fov_w / (float)fov_length; +} +void SeqExtStepPage::display() { +#ifdef EXT_TRACKS + auto &active_track = mcl_seq.ext_tracks[last_ext_track]; + uint8_t timing_mid = active_track.get_timing_mid(); + uint8_t epoch = 0; + do { + oled_display.clearDisplay(); draw_viewport_minimap(); draw_grid(); - draw_seq_pos(); - mcl_gui.put_value_at(cur_x/timing_mid + 1,info1); + epoch = active_track.epoch; if (pianoroll_mode == 0) { MusicalNotes number_to_note; uint8_t oct = cur_y / 12; @@ -695,6 +775,8 @@ void SeqExtStepPage::display() { mcl_gui.put_value_at(lock_cur_y, info1); draw_lockeditor(); } + } while (epoch != ExtSeqTrack::epoch); + draw_seq_pos(); SeqPage::display(); // Draw vertical keyboard @@ -727,11 +809,14 @@ void SeqExtStepPage::display() { void SeqExtStepPage::enter_notes() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; + uint16_t w = cur_w; + if (cur_x + w >= roll_length) { w = roll_length - cur_x - 1; } + for (uint8_t n = 0; n < NUM_NOTES_ON; n++) { if (active_track.notes_on[n].value == 255) continue; - active_track.del_note(cur_x, cur_w - 1, active_track.notes_on[n].value); - active_track.add_note(cur_x, cur_w, active_track.notes_on[n].value, + active_track.del_note(cur_x, w - 1, active_track.notes_on[n].value); + active_track.add_note(cur_x, w, active_track.notes_on[n].value, velocity, cond); } } @@ -777,6 +862,7 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { // cur_x = fov_offset + (float)(fov_length / 16) * (float)track; int a = 16 * timing_mid; pos_cur_x(((cur_x / a) * a + timing_mid * track) - cur_x); + pos_cur_x(((cur_x / a) * a + timing_mid * track) - cur_x); note_interface.last_note = track; } if (mask == EVENT_BUTTON_RELEASED) { @@ -801,7 +887,34 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { } if (pianoroll_mode > 0) { - w = inc; + inc = 1; + w = seq_extparam4.cur / 2; + if (trig_interface.is_key_down(MDX_KEY_FUNC)) { + w *= 2; + inc = 12; + } + } + if (event->mask == EVENT_BUTTON_RELEASED) { + switch (key) { + case MDX_KEY_SCALE: { + // seq_extparam4.cur = 16; + // + //int a = fov_length + int a = timing_mid * 16;// / active_track.get_speed_multiplier(); + cur_x += a; + if (cur_x > fov_offset + fov_length) { fov_offset += a; } + if (cur_x >= roll_length) { + cur_x = cur_x - (cur_x / a ) * a; + fov_offset = 0; + } + pos_cur_x(0); + /* if (fov_offset + fov_length > roll_length) { + cur_x = cur_x - fov_offset; + fov_offset = 0; + } */ + return true; + } + } } if (event->mask == EVENT_BUTTON_PRESSED) { if (trig_interface.is_key_down(MDX_KEY_YES)) { @@ -811,11 +924,11 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { if (trig_interface.is_key_down(MDX_KEY_NO) || note_interface.notes_count_on()) { switch (key) { case MDX_KEY_UP: { - seq_extparam4.cur -= inc; + seq_extparam4.cur -= 2; return true; } case MDX_KEY_DOWN: { - seq_extparam4.cur += inc; + seq_extparam4.cur += 2; return true; } case MDX_KEY_LEFT: { @@ -868,24 +981,7 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { pos_cur_y(-1 * inc); return true; } - case MDX_KEY_SCALE: { - // seq_extparam4.cur = 16; - int diff = cur_x - fov_offset; - int a = timing_mid * 16; - fov_offset += a; - cur_x += a; - if (cur_x + cur_w > roll_length) { - cur_x = cur_x - (cur_x / a ) * a; - fov_offset = 0; - } - pos_cur_x(0); - /* if (fov_offset + fov_length > roll_length) { - cur_x = cur_x - fov_offset; - fov_offset = 0; - } */ - return true; - } - // case MDX_KEY_YES: { + // case MDX_KEY_YES: { // ignore_clear = true; // goto YES; // } @@ -918,7 +1014,7 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { bool clear = false; clear = active_track.del_track_locks(cur_x, lock_idx, lock_cur_y); - if (!clear) { + if (!clear && active_track.locks_params[lock_idx] - 1 > 0) { active_track.set_track_locks(step, utiming, active_track.locks_params[lock_idx] - 1, lock_cur_y, slide, lock_idx); @@ -931,9 +1027,11 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { if (active_track.notes_on_count > 0) { enter_notes(); } else { + uint16_t w = cur_w; + if (cur_x + w >= roll_length) { w = roll_length - cur_x - 1; } - if (!active_track.del_note(cur_x, cur_w - 1, cur_y)) { - active_track.add_note(cur_x, cur_w, cur_y, velocity, cond); + if (!active_track.del_note(cur_x, w - 1, cur_y)) { + active_track.add_note(cur_x, w, cur_y, velocity, cond); } } return true; @@ -946,7 +1044,7 @@ bool SeqExtStepPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { - ext_mute_mask = 128; + mute_mask = 128; param_select_update(); } if (SeqPage::handleEvent(event)) { diff --git a/avr/cores/megacommand/MCL/SeqExtStepPage.h b/avr/cores/megacommand/MCL/SeqExtStepPage.h index e09ae33b6..72bed3785 100644 --- a/avr/cores/megacommand/MCL/SeqExtStepPage.h +++ b/avr/cores/megacommand/MCL/SeqExtStepPage.h @@ -58,11 +58,11 @@ class SeqExtStepPage : public SeqPage { SeqExtStepPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) : SeqPage(e1, e2, e3, e4) {} - void config_encoders(); + virtual void config_encoders(); void draw_thick_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color = WHITE); - void draw_note(uint8_t note_val, uint16_t note_start, uint16_t note_end); + void draw_note(uint8_t x, uint8_t y, uint8_t w); void draw_pianoroll(); void draw_lockeditor(); void draw_viewport_minimap(); @@ -73,15 +73,13 @@ class SeqExtStepPage : public SeqPage { void pos_cur_y(int16_t diff); void pos_cur_w(int16_t diff); - void display_mute_mask(); - - bool is_within_fov(uint16_t x) { + bool is_within_fov(int16_t x) { if ((x >= fov_offset) && (x < fov_offset + fov_length)) { return true; } return false; } - bool is_within_fov(uint16_t start_x, uint16_t end_x) { + bool is_within_fov(int16_t start_x, int16_t end_x) { if (is_within_fov(start_x) || is_within_fov(end_x) || ((start_x < fov_offset) && (end_x >= fov_offset + fov_length)) || (end_x < start_x && @@ -92,6 +90,7 @@ class SeqExtStepPage : public SeqPage { } void param_select_update(); void enter_notes(); + void config_menu_entries(); virtual bool handleEvent(gui_event_t *event); virtual void display(); virtual void loop(); diff --git a/avr/cores/megacommand/MCL/SeqPage.cpp b/avr/cores/megacommand/MCL/SeqPage.cpp index 0877781f8..19eb9021a 100644 --- a/avr/cores/megacommand/MCL/SeqPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPage.cpp @@ -23,10 +23,9 @@ uint8_t SeqPage::slide = true; uint8_t SeqPage::md_micro = false; bool SeqPage::show_seq_menu = false; -bool SeqPage::show_step_menu = false; bool SeqPage::toggle_device = true; -uint16_t SeqPage::ext_mute_mask = 0; +uint16_t SeqPage::mute_mask = 0; uint8_t SeqPage::step_select = 255; @@ -53,8 +52,6 @@ bool SeqPage::recording = false; uint8_t SeqPage::last_midi_state = 0; uint8_t SeqPage::last_step = 255; -static MidiDevice *opt_midi_device_capture = &MD; -static SeqPage *opt_seqpage_capture = nullptr; static MCLEncoder *opt_param1_capture = nullptr; static MCLEncoder *opt_param2_capture = nullptr; @@ -92,7 +89,7 @@ void SeqPage::enable_record() { } void SeqPage::disable_record() { - MD.set_rec_mode((GUI.currentPage() == &seq_step_page)); + MD.set_rec_mode((mcl.currentPage() == SEQ_STEP_PAGE)); recording = false; clearLed2(); } @@ -103,10 +100,15 @@ void SeqPage::init() { disable_record(); page_count = 4; ((MCLEncoder *)encoders[2])->handler = pattern_len_handler; + config_encoders(); seqpage_midi_events.setup_callbacks(); + oled_display.clearDisplay(); + toggle_device = true; - seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH, false); + DEBUG_PRINTLN("seq page init"); + + seq_menu_page.menu.enable_entry(SEQ_MENU_DEVICE, false); seq_menu_page.menu.enable_entry(SEQ_MENU_CHANNEL, false); seq_menu_page.menu.enable_entry(SEQ_MENU_MASK, false); seq_menu_page.menu.enable_entry(SEQ_MENU_ARP, false); @@ -117,7 +119,11 @@ void SeqPage::init() { seq_menu_page.menu.enable_entry(SEQ_MENU_PARAMSELECT, false); seq_menu_page.menu.enable_entry(SEQ_MENU_SLIDE, false); seq_menu_page.menu.enable_entry(SEQ_MENU_POLY, false); + seq_menu_page.menu.enable_entry(SEQ_MENU_SOUND, false); + seq_menu_page.menu.enable_entry(SEQ_MENU_AUTOMATION, false); + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_MD, false); + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_EXT, false); /* if (mcl_cfg.track_select == 1) { seq_menu_page.menu.enable_entry(SEQ_MENU_TRACK, false); @@ -129,15 +135,17 @@ void SeqPage::init() { last_md_model = MD.kit.models[MD.currentTrack]; R.Clear(); + R.use_icons_knob(); R.use_machine_names_short(); R.use_machine_param_names(); MidiUartParent::handle_midi_lock = _midi_lock_tmp; + } void SeqPage::cleanup() { seqpage_midi_events.remove_callbacks(); note_interface.init_notes(); - opt_midi_device_capture = &MD; + midi_device = &MD; disable_record(); if (show_seq_menu) { encoders[0] = opt_param1_capture; @@ -156,10 +164,10 @@ void SeqPage::params_reset() { } void SeqPage::bootstrap_record() { - if (GUI.currentPage() != &seq_step_page && - GUI.currentPage() != &seq_extstep_page && - GUI.currentPage() != &seq_ptc_page) { - GUI.setPage(&seq_step_page); + if (mcl.currentPage() != SEQ_STEP_PAGE && + mcl.currentPage() != SEQ_EXTSTEP_PAGE && + mcl.currentPage() != SEQ_PTC_PAGE) { + mcl.setPage(SEQ_STEP_PAGE); } trig_interface.send_md_leds(TRIGLED_OVERLAY); enable_record(); @@ -197,20 +205,12 @@ void SeqPage::toggle_ext_mask(uint8_t track) { if (track >= mcl_seq.num_ext_tracks) { return true; } - if (mcl_seq.ext_tracks[track].mute_state == SEQ_MUTE_ON) { - mcl_seq.ext_tracks[track].mute_state = SEQ_MUTE_OFF; - } else { - mcl_seq.ext_tracks[track].mute_state = SEQ_MUTE_ON; - uint8_t mod12_counter = MidiClock.mod12_counter; - while (MidiClock.state == 2 && mod12_counter == MidiClock.mod12_counter) {}; - mcl_seq.ext_tracks[track].buffer_notesoff(); - } + mcl_seq.ext_tracks[track].toggle_mute(); } else { if (track >= mcl_seq.num_ext_tracks) { return true; } MidiDevice *dev = midi_active_peering.get_device(UART2_PORT); - opt_midi_device_capture = dev; midi_device = dev; select_track(dev, track); opt_trackid = last_ext_track + 1; @@ -241,87 +241,59 @@ void SeqPage::select_track(MidiDevice *device, uint8_t track, bool send) { else { DEBUG_PRINTLN("setting ext track"); last_ext_track = min(track, NUM_EXT_TRACKS - 1); + auto &active_track = mcl_seq.ext_tracks[last_ext_track]; + MD.sync_seqtrack(min(active_track.length,64), active_track.speed, + active_track.step_count); } #endif - if (GUI.currentPage()) { - GUI.currentPage()->config(); - } + GUI.currentPage()->config(); + //config_encoders(); } -void SeqPage::display_ext_mute_mask() { - uint16_t last_mute_mask = ext_mute_mask; - ext_mute_mask = 0; - for (uint8_t n = 0; n < mcl_seq.num_ext_tracks; n++) { - if (mcl_seq.ext_tracks[n].mute_state == SEQ_MUTE_OFF) { - SET_BIT16(ext_mute_mask, 8 + n); +bool SeqPage::display_mute_mask(MidiDevice* device, uint8_t offset) { + uint16_t last_mute_mask = mute_mask; + + bool is_md_device = (device == &MD); + mute_mask = 0; + + uint8_t len = is_md_device ? mcl_seq.num_md_tracks : mcl_seq.num_ext_tracks; + + //Hack to display last_ext_track + if (offset > 0 && !is_md_device) { + SET_BIT16(mute_mask, last_ext_track); + } + + for (uint8_t n = 0; n < len; n++) { + + SeqTrack *seq_track = is_md_device ? (SeqTrack*) &mcl_seq.md_tracks[n] : (SeqTrack*) &mcl_seq.ext_tracks[n]; + + if (seq_track->mute_state == SEQ_MUTE_OFF) { + uint8_t d = offset + n; + if (d < 16) { + SET_BIT16(mute_mask, d); + } } } - SET_BIT16(ext_mute_mask, last_ext_track); - if (last_mute_mask != ext_mute_mask) { - MD.set_trigleds(ext_mute_mask, TRIGLED_EXCLUSIVE); + if (last_mute_mask != mute_mask) { + MD.set_trigleds(mute_mask, TRIGLED_EXCLUSIVE); + return true; } + return false; } + bool SeqPage::handleEvent(gui_event_t *event) { if (note_interface.is_event(event)) { uint8_t port = event->port; MidiDevice *device = midi_active_peering.get_device(port); uint8_t track = event->source - 128; - // =================== seq menu mode TI events ================ - - if (show_seq_menu) { - // TI + SHIFT2 = select track. - if (BUTTON_DOWN(Buttons.BUTTON3) && (mcl_cfg.track_select == 0)) { - opt_trackid = track + 1; - note_interface.ignoreNextEvent(track); - select_track(device, track); - seq_menu_page.select_item(0); - } - - return true; - } - // =================== normal mode TI events ================ - - // TI + WRITE (BUTTON4): adjust track seq length. - // Ignore WRITE release event so it won't trigger - // a page select action. + //Removing this block causes progmem to balloon by 1K ?? if (BUTTON_DOWN(Buttons.BUTTON4)) { // calculate the intended seq length. uint8_t step = track; step += 1 + page_select * 16; - // Further, if SHIFT2 is pressed, set all tracks. - /* not required. pattern_len_handler will detect change when - * encoder is updated below */ - /* - if (SeqPage::midi_device == DEVICE_MD) { - char str[4]; - itoa(step, str, 10); - - if (BUTTON_DOWN(Buttons.BUTTON3)) { - oled_display.textbox("MD TRACKS LEN:", str); - GUI.ignoreNextEvent(Buttons.BUTTON3); - for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { - mcl_seq.md_tracks[n].length = step; - } - } - else { - oled_display.textbox("MD TRACK LEN:", str); - mcl_seq.md_tracks[last_md_track].length = step; - } - } -#ifdef EXT_TRACKS - else { - if (BUTTON_DOWN(Buttons.BUTTON3)) { - for (uint8_t n = 0; n < NUM_EXT_TRACKS; n++) { - mcl_seq.ext_tracks[n].length = step; - } - } - mcl_seq.ext_tracks[last_ext_track].length = step; - } -#endif -*/ encoders[2]->cur = step; note_interface.ignoreNextEvent(track); if (event->mask == EVENT_BUTTON_RELEASED) { @@ -331,9 +303,9 @@ bool SeqPage::handleEvent(gui_event_t *event) { if (BUTTON_DOWN(Buttons.BUTTON3)) { GUI.ignoreNextEvent(Buttons.BUTTON3); } + return true; } - // notify derived class about unhandled TI event return false; } // end TI events @@ -387,33 +359,15 @@ bool SeqPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); } - // activate show_seq_menu only if S2 press is not a key combination - if (EVENT_PRESSED(event, Buttons.BUTTON3) && !BUTTON_DOWN(Buttons.BUTTON4)) { - // If MD trig is held and BUTTON3 is pressed, launch note menu - if ((note_interface.notes_count_on() != 0) && (!show_step_menu) && - (GUI.currentPage() != &seq_ptc_page)) { - uint8_t note = 255; - note = note_interface.get_first_md_note(); - if (note == 255) { - return false; - } - step_select = note; - opt_param1_capture = (MCLEncoder *)encoders[0]; - opt_param2_capture = (MCLEncoder *)encoders[1]; - encoders[0] = &step_menu_value_encoder; - encoders[1] = &step_menu_entry_encoder; - step_menu_page.init(); - show_step_menu = true; - return true; - } else if (!show_seq_menu) { + if (EVENT_PRESSED(event, Buttons.BUTTON3)) { + // If MD trig is held and BUTTON3 is pressed, launch note menu + if (!show_seq_menu) { show_seq_menu = true; - // capture current page. - opt_seqpage_capture = this; - if (opt_midi_device_capture == &MD) { + if (midi_device == &MD) { auto &active_track = mcl_seq.md_tracks[last_md_track]; opt_trackid = last_md_track + 1; opt_speed = active_track.speed; @@ -430,6 +384,8 @@ bool SeqPage::handleEvent(gui_event_t *event) { encoders[0] = &seq_menu_value_encoder; encoders[1] = &seq_menu_entry_encoder; seq_menu_page.init(); + seq_menu_page.gen_menu_device_names(); + mcl_cfg.seq_dev = midi_device == &MD ? UART1_PORT : UART2_PORT; return true; } } @@ -437,19 +393,22 @@ bool SeqPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON3)) { encoders[0] = opt_param1_capture; encoders[1] = opt_param2_capture; - oled_display.clearDisplay(); + //oled_display.clearDisplay(); void (*row_func)(); if (show_seq_menu) { row_func = seq_menu_page.menu.get_row_function(seq_menu_page.encoders[1]->cur); - } else if (show_step_menu) { - row_func = - step_menu_page.menu.get_row_function(step_menu_page.encoders[1]->cur); + MidiDevice* old_dev = midi_device; + midi_device = midi_active_peering.get_device(mcl_cfg.seq_dev); + if (old_dev == midi_device) { + opt_speed_handler(); + opt_length_handler(); + opt_channel_handler(); + } } if (row_func != NULL) { row_func(); show_seq_menu = false; - show_step_menu = false; init(); return true; } @@ -457,14 +416,9 @@ bool SeqPage::handleEvent(gui_event_t *event) { show_seq_menu = false; return true; } - if (show_step_menu && step_menu_page.enter()) { - show_step_menu = false; - return true; - } show_seq_menu = false; - show_step_menu = false; - mcl_gui.init_encoders_used_clock(); + init_encoders_used_clock(); init(); return true; } @@ -507,13 +461,14 @@ void SeqPage::draw_mask(uint8_t offset, uint8_t device, if (device == DEVICE_MD) { auto &active_track = mcl_seq.md_tracks[last_md_track]; - uint64_t mask, lock_mask, oneshot_mask = 0, slide_mask = 0; + uint64_t mask, lock_mask, mute_mask = 0, slide_mask = 0; active_track.get_mask(&mask, MASK_PATTERN); uint64_t led_mask = 0; switch (mask_type) { case MASK_PATTERN: led_mask = mask; + mute_mask = active_track.mute_mask; break; case MASK_LOCK: active_track.get_mask(&lock_mask, MASK_LOCK); @@ -521,8 +476,8 @@ void SeqPage::draw_mask(uint8_t offset, uint8_t device, mask = lock_mask; break; case MASK_MUTE: - oneshot_mask = active_track.oneshot_mask; - led_mask = oneshot_mask; + mute_mask = active_track.mute_mask; + led_mask = mute_mask; break; case MASK_SLIDE: active_track.get_mask(&slide_mask, MASK_SLIDE); @@ -531,7 +486,7 @@ void SeqPage::draw_mask(uint8_t offset, uint8_t device, } shed_mask(led_mask, active_track.length, offset); draw_mask(offset, mask, active_track.step_count, active_track.length, - oneshot_mask, slide_mask, show_current_step); + mute_mask, slide_mask, show_current_step); if (recording) return; @@ -625,72 +580,75 @@ void SeqPage::draw_knob_timing(uint8_t timing, uint8_t timing_mid) { draw_knob(1, "UTIM", K); } -void pattern_len_handler(EncoderParent *enc) { - MCLEncoder *enc_ = (MCLEncoder *)enc; - if (!enc_->hasChanged()) { - return; - } +void SeqPage::length_handler(uint8_t length, bool multi) { bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); if (SeqPage::midi_device == &MD) { - if (BUTTON_DOWN(Buttons.BUTTON4)) { + if (multi) { for (uint8_t c = 0; c < 16; c++) { - mcl_seq.md_tracks[c].set_length(enc_->cur); + mcl_seq.md_tracks[c].set_length(length); } - GUI.ignoreNextEvent(Buttons.BUTTON4); } else { if ((mcl_cfg.poly_mask) && (is_poly)) { for (uint8_t c = 0; c < 16; c++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, c)) { - mcl_seq.md_tracks[c].set_length(enc_->cur); + mcl_seq.md_tracks[c].set_length(length); } } } else { - mcl_seq.md_tracks[last_md_track].set_length(enc_->cur); + mcl_seq.md_tracks[last_md_track].set_length(length); } } + auto &active_track = mcl_seq.md_tracks[last_md_track]; + MD.sync_seqtrack(active_track.length, active_track.speed, + active_track.step_count); } else { - if (BUTTON_DOWN(Buttons.BUTTON4)) { + if (multi) { for (uint8_t c = 0; c < NUM_EXT_TRACKS; c++) { - mcl_seq.ext_tracks[c].set_length(enc_->cur); + mcl_seq.ext_tracks[c].set_length(length); + if (last_ext_track == c) { seq_extparam4.cur = length; } } - GUI.ignoreNextEvent(Buttons.BUTTON4); } else { - mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); - mcl_seq.ext_tracks[last_ext_track].set_length(enc_->cur); + mcl_seq.ext_tracks[last_ext_track].set_length(length); + seq_extparam4.cur = length; } } } -void opt_length_handler() { - if (opt_midi_device_capture == &MD) { - auto &active_track = mcl_seq.md_tracks[last_md_track]; - active_track.set_length(opt_length); - MD.sync_seqtrack(active_track.length, active_track.speed, - active_track.step_count); - } else { - mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); - mcl_seq.ext_tracks[last_ext_track].set_length(opt_length); + +void pattern_len_handler(EncoderParent *enc) { + MCLEncoder *enc_ = (MCLEncoder *)enc; + if (!enc_->hasChanged()) { + return; } + seq_step_page.length_handler(enc_->cur, BUTTON_DOWN(Buttons.BUTTON4)); + GUI.ignoreNextEvent(Buttons.BUTTON4); +} + +void opt_length_handler() { + seq_step_page.length_handler(opt_length); } void opt_channel_handler() { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { } else { - mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); - mcl_seq.ext_tracks[last_ext_track].channel = opt_channel - 1; + uint8_t chan = opt_channel - 1; + if (mcl_seq.ext_tracks[last_ext_track].channel != chan) { + mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); + mcl_seq.ext_tracks[last_ext_track].channel = chan; + } } } void opt_mask_handler() { seq_step_page.config_mask_info(false); } void opt_trackid_handler() { - opt_seqpage_capture->select_track(opt_midi_device_capture, opt_trackid - 1); + seq_step_page.select_track(SeqPage::midi_device, opt_trackid - 1); } void opt_speed_handler() { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { DEBUG_PRINTLN(F("okay using MD for length update")); if (BUTTON_DOWN(Buttons.BUTTON4)) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { @@ -699,9 +657,12 @@ void opt_speed_handler() { GUI.ignoreNextEvent(Buttons.BUTTON4); } else { auto &active_track = mcl_seq.md_tracks[last_md_track]; - active_track.set_speed(opt_speed); - MD.sync_seqtrack(active_track.length, active_track.speed, - active_track.step_count); + uint8_t last_speed = active_track.speed; + if (opt_speed != last_speed) { + active_track.set_speed(opt_speed); + MD.sync_seqtrack(active_track.length, active_track.speed, + active_track.step_count); + } } seq_step_page.config_encoders(); } @@ -713,12 +674,15 @@ void opt_speed_handler() { } GUI.ignoreNextEvent(Buttons.BUTTON4); } else { - mcl_seq.ext_tracks[last_ext_track].set_speed(opt_speed); - seq_extstep_page.config_encoders(); + uint8_t last_speed = mcl_seq.ext_tracks[last_ext_track].speed; + if (opt_speed != last_speed) { + mcl_seq.ext_tracks[last_ext_track].set_speed(opt_speed); + seq_extstep_page.config_encoders(); + } } } #endif - opt_seqpage_capture->init(); +// opt_seqpage_capture->init(); } void opt_clear_track_handler() { @@ -735,7 +699,7 @@ void opt_clear_track_handler() { COPY: copy = true; } - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD || !(mcl.currentPage() == SEQ_PTC_PAGE || mcl.currentPage() == SEQ_EXTSTEP_PAGE)) { if (opt_clear == 2) { MD.popup_text(2); @@ -754,18 +718,19 @@ void opt_clear_track_handler() { } } else if (opt_clear == 1) { bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); - char *str = "CLEAR TRACK"; + const char *str = "CLEAR TRACK"; if (is_poly) { str = "CLEAR POLY TRACKS"; } oled_display.textbox(str, ""); - MD.popup_text(str); + MD.popup_text((char*) str); if (copy) { opt_copy_track_handler(opt_clear); } if (is_poly) { for (uint8_t c = 0; c < 16; c++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, c)) { + mcl_clipboard.copy_sequencer_track(c); mcl_seq.md_tracks[c].clear_track(); } } @@ -777,7 +742,7 @@ void opt_clear_track_handler() { if (copy) { opt_copy_track_handler(opt_clear); } - char *str = "CLEAR EXT TRACK"; + const char *str = "CLEAR EXT TRACK"; if (opt_clear == 2) { for (uint8_t n = 0; n < mcl_seq.num_ext_tracks; n++) { str = "CLEAR EXT TRACKS"; @@ -787,8 +752,8 @@ void opt_clear_track_handler() { mcl_seq.ext_tracks[last_ext_track].clear_track(); } if (opt_clear) { - oled_display.textbox(str, ""); - MD.popup_text(str); + oled_display.textbox((char*) str, ""); + MD.popup_text((char*) str); } } opt_clear = 0; @@ -796,7 +761,7 @@ void opt_clear_track_handler() { void opt_clear_locks_handler() { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { if (opt_clear == 2) { for (uint8_t n = 0; n < 16; ++n) { oled_display.textbox("CLEAR MD ", "LOCKS"); @@ -811,9 +776,7 @@ void opt_clear_locks_handler() { auto &active_track = mcl_seq.ext_tracks[last_ext_track]; if (opt_clear == 2) { oled_display.textbox("CLEAR ", "LOCKS"); - for (uint8_t n = 0; n < NUM_LOCKS; n++) { - active_track.clear_track_locks(n); - } + active_track.clear_track_locks(); } if (opt_clear == 1) { oled_display.textbox("CLEAR ", "LOCK"); @@ -827,7 +790,7 @@ void opt_clear_locks_handler() { } void opt_clear_all_tracks_handler() { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { } #ifdef EXT_TRACKS else { @@ -837,7 +800,7 @@ void opt_clear_all_tracks_handler() { } void opt_clear_all_locks_handler() { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { } #ifdef EXT_TRACKS else { @@ -862,7 +825,7 @@ void opt_copy_track_handler(uint8_t op) { DEBUG_PRINTLN("/end"); if (opt_copy == 2) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { if (!silent) { oled_display.textbox("COPY MD ", "TRACKS"); MD.popup_text(1); @@ -879,7 +842,7 @@ void opt_copy_track_handler(uint8_t op) { #endif } if (opt_copy == 1) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { if (!silent) { oled_display.textbox("COPY TRACK", ""); MD.popup_text(4); @@ -907,7 +870,7 @@ void opt_paste_track_handler() { } if (opt_paste == 2) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { if (!undo) { oled_display.textbox("PASTE MD ", "TRACKS"); MD.popup_text(3); @@ -917,33 +880,44 @@ void opt_paste_track_handler() { } mcl_clipboard.paste_sequencer(); } else { - char *str = "UNDO EXT TRACKS"; + const char *str = "UNDO EXT TRACKS"; if (!undo) { str = "PASTE EXT TRACKS"; } oled_display.textbox(str, ""); - MD.popup_text(str); + MD.popup_text((char*)str); mcl_clipboard.paste_sequencer(NUM_MD_TRACKS); } } if (opt_paste == 1) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { + bool is_poly = false; if (!undo) { oled_display.textbox("PASTE TRACK", ""); MD.popup_text(6); } else { oled_display.textbox("UNDO TRACK", ""); + is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); MD.popup_text(23); } + if (is_poly) { + for (uint8_t c = 0; c < 16; c++) { + if (IS_BIT_SET16(mcl_cfg.poly_mask, c)) { + mcl_clipboard.paste_sequencer_track(mcl_clipboard.copy_track, c); + } + } + } + else { mcl_clipboard.paste_sequencer_track(mcl_clipboard.copy_track, last_md_track); + } } else { - char *str = "UNDO EXT TRACK"; + const char *str = "UNDO EXT TRACK"; if (!undo) { str = "PASTE EXT TRACK"; } oled_display.textbox(str, ""); - MD.popup_text(str); + MD.popup_text((char*)str); mcl_clipboard.paste_sequencer_track(mcl_clipboard.copy_track, last_ext_track + NUM_MD_TRACKS); @@ -1084,7 +1058,7 @@ void opt_paste_step_handler() { void opt_mute_step_handler() { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { if (note_interface.is_note_on(n)) { - TOGGLE_BIT64(mcl_seq.md_tracks[last_md_track].oneshot_mask, + TOGGLE_BIT64(mcl_seq.md_tracks[last_md_track].mute_mask, n + SeqPage::page_select * 16); } } @@ -1098,7 +1072,7 @@ void opt_clear_step_locks_handler() { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { if (note_interface.is_note_on(n)) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { mcl_seq.md_tracks[last_md_track].clear_step_locks( n + SeqPage::page_select * 16); } else { @@ -1113,7 +1087,7 @@ void opt_clear_step_locks_handler() { void opt_shift_track_handler() { switch (opt_shift) { case 1: - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { mcl_seq.md_tracks[last_md_track].rotate_left(); } #ifdef EXT_TRACKS @@ -1123,7 +1097,7 @@ void opt_shift_track_handler() { #endif break; case 2: - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { mcl_seq.md_tracks[last_md_track].rotate_right(); } #ifdef EXT_TRACKS @@ -1133,7 +1107,7 @@ void opt_shift_track_handler() { #endif break; case 3: - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].rotate_left(); } @@ -1147,7 +1121,7 @@ void opt_shift_track_handler() { #endif break; case 4: - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].rotate_right(); } @@ -1166,7 +1140,7 @@ void opt_shift_track_handler() { void opt_reverse_track_handler() { if (opt_reverse == 2) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { // oled_display.textbox("REVERSE ", "MD TRACKS"); for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { mcl_seq.md_tracks[n].reverse(); @@ -1183,7 +1157,7 @@ void opt_reverse_track_handler() { } if (opt_reverse == 1) { - if (opt_midi_device_capture == &MD) { + if (SeqPage::midi_device == &MD) { // oled_display.textbox("REVERSE ", "TRACK"); mcl_seq.md_tracks[last_md_track].reverse(); } @@ -1198,8 +1172,6 @@ void opt_reverse_track_handler() { void seq_menu_handler() { } -void step_menu_handler() { -} void SeqPage::config_as_trackedit() { @@ -1234,14 +1206,12 @@ void SeqPage::loop() { if (show_seq_menu) { seq_menu_page.loop(); - if (opt_midi_device_capture != &MD && opt_trackid > NUM_EXT_TRACKS) { + if (midi_device != &MD && opt_trackid > NUM_EXT_TRACKS) { // lock trackid to [1..4] opt_trackid = min(opt_trackid, NUM_EXT_TRACKS); seq_menu_value_encoder.cur = opt_trackid; } return; - } else if (show_step_menu) { - step_menu_page.loop(); } } @@ -1295,7 +1265,7 @@ void SeqPage::draw_page_index(bool show_page_index, uint8_t _playing_idx) { // ref: design/Sequencer.png void SeqPage::display() { - bool is_md = (opt_midi_device_capture == &MD); + bool is_md = (midi_device == &MD); const char *int_name = midi_active_peering.get_device(UART1_PORT)->name; const char *ext_name = midi_active_peering.get_device(UART2_PORT)->name; @@ -1308,8 +1278,12 @@ void SeqPage::display() { // draw current active track mcl_gui.draw_panel_number(track_id); - mcl_gui.draw_panel_toggle(int_name, ext_name, is_md); - + if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { + mcl_gui.draw_panel_toggle(ext_name, int_name, true); + } + else { + mcl_gui.draw_panel_toggle(int_name, ext_name, is_md); + } // draw stop/play/rec state mcl_gui.draw_panel_status(recording, MidiClock.state == 2); @@ -1319,13 +1293,10 @@ void SeqPage::display() { // draw info lines mcl_gui.draw_panel_labels(info1, info2); - if (show_seq_menu || show_step_menu) { + if (show_seq_menu) { constexpr uint8_t width = 52; oled_display.setFont(&TomThumb); oled_display.fillRect(128 - width - 2, 0, width + 2, 32, BLACK); - if (show_step_menu) { - step_menu_page.draw_menu(128 - width, 8, width); - } if (show_seq_menu) { seq_menu_page.draw_menu(128 - width, 8, width); } diff --git a/avr/cores/megacommand/MCL/SeqPage.h b/avr/cores/megacommand/MCL/SeqPage.h index 978c5a748..8be0863ff 100644 --- a/avr/cores/megacommand/MCL/SeqPage.h +++ b/avr/cores/megacommand/MCL/SeqPage.h @@ -36,7 +36,6 @@ extern uint8_t opt_channel; extern uint8_t opt_undo; extern uint8_t opt_undo_track; -extern MidiDevice *opt_midi_device_capture; extern uint16_t trigled_mask; extern uint16_t locks_on_step_mask; @@ -64,7 +63,6 @@ extern void opt_paste_page_handler(); extern void opt_clear_step_handler(); extern void seq_menu_handler(); -extern void step_menu_handler(); class MidiDevice; @@ -92,7 +90,6 @@ class SeqPage : public LightPage { static MidiDevice* midi_device; static bool show_seq_menu; - static bool show_step_menu; static bool toggle_device; static uint8_t last_midi_state; @@ -102,7 +99,8 @@ class SeqPage : public LightPage { static uint32_t last_md_model; static bool recording; - static uint16_t ext_mute_mask; + + static uint16_t mute_mask; bool display_page_index = true; char info1[8] = { '\0' }; @@ -148,8 +146,9 @@ class SeqPage : public LightPage { void toggle_ext_mask(uint8_t track); void params_reset(); + void length_handler(uint8_t length, bool multi = false); - void display_ext_mute_mask(); + bool display_mute_mask(MidiDevice *device, uint8_t offset = 0); virtual bool handleEvent(gui_event_t *event); virtual void loop(); @@ -157,7 +156,7 @@ class SeqPage : public LightPage { virtual void setup(); virtual void init(); virtual void cleanup(); - + virtual void config_encoders() = 0; static constexpr uint8_t pidx_x0 = 0; static constexpr uint8_t pidx_y = 15; static constexpr uint8_t pidx_w = 6; diff --git a/avr/cores/megacommand/MCL/SeqPages.h b/avr/cores/megacommand/MCL/SeqPages.h index c7809cfa7..35f5e5e1d 100644 --- a/avr/cores/megacommand/MCL/SeqPages.h +++ b/avr/cores/megacommand/MCL/SeqPages.h @@ -14,24 +14,29 @@ #define NUM_PARAM_PAGES 4 #define SEQ_MENU_TRACK 0 -#define SEQ_MENU_MASK 1 -#define SEQ_MENU_PIANOROLL 2 -#define SEQ_MENU_PARAMSELECT 3 -#define SEQ_MENU_SLIDE 4 -#define SEQ_MENU_ARP 5 -#define SEQ_MENU_TRANSPOSE 6 -#define SEQ_MENU_VEL 7 -#define SEQ_MENU_PROB 8 -#define SEQ_MENU_SPEED 9 -#define SEQ_MENU_LENGTH 10 -#define SEQ_MENU_CHANNEL 11 -#define SEQ_MENU_COPY 12 -#define SEQ_MENU_CLEAR_TRACK 13 -#define SEQ_MENU_CLEAR_LOCKS 14 -#define SEQ_MENU_PASTE 15 -#define SEQ_MENU_SHIFT 16 -#define SEQ_MENU_REVERSE 17 -#define SEQ_MENU_POLY 18 +#define SEQ_MENU_DEVICE 1 +#define SEQ_MENU_MASK 2 +#define SEQ_MENU_PIANOROLL 3 +#define SEQ_MENU_PARAMSELECT 4 +#define SEQ_MENU_SLIDE 5 +#define SEQ_MENU_ARP 6 +#define SEQ_MENU_TRANSPOSE 7 +#define SEQ_MENU_VEL 8 +#define SEQ_MENU_PROB 9 +#define SEQ_MENU_SPEED 10 +#define SEQ_MENU_LENGTH_MD 11 +#define SEQ_MENU_LENGTH_EXT 12 +#define SEQ_MENU_CHANNEL 13 +#define SEQ_MENU_COPY 14 +#define SEQ_MENU_CLEAR_TRACK 15 +#define SEQ_MENU_CLEAR_LOCKS 16 +#define SEQ_MENU_PASTE 17 +#define SEQ_MENU_SHIFT 18 +#define SEQ_MENU_REVERSE 19 +#define SEQ_MENU_POLY 20 +#define SEQ_MENU_QUANT 21 +#define SEQ_MENU_AUTOMATION 22 +#define SEQ_MENU_SOUND 23 extern MCLEncoder seq_param1; extern MCLEncoder seq_param2; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.cpp b/avr/cores/megacommand/MCL/SeqPtcPage.cpp index f3b2994af..876e8ef9a 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.cpp +++ b/avr/cores/megacommand/MCL/SeqPtcPage.cpp @@ -38,8 +38,10 @@ void SeqPtcPage::setup() { SeqPage::setup(); init_poly(); midi_events.setup_callbacks(); - ptc_param_oct.cur = 1; - ptc_param_fine_tune.cur = 32; + octs[0] = 1; + octs[1] = 1; + fine_tunes[0] = 32; + fine_tunes[1] = 32; memset(dev_note_masks, 0, sizeof(dev_note_masks)); memset(dev_note_channels, 17, sizeof(dev_note_channels)); memset(note_mask, 0, sizeof(note_mask)); @@ -50,9 +52,16 @@ void SeqPtcPage::cleanup() { params_reset(); } void SeqPtcPage::config_encoders() { + if (show_seq_menu) { return; } ptc_param_len.min = 1; bool show_chan = true; - if (midi_device == &MD) { + + uint8_t dev = midi_device == &MD ? 0 : 1; + + encoders[0]->cur = octs[dev]; + encoders[1]->cur = fine_tunes[dev]; + + if (dev == 0) { ptc_param_len.max = 64; ptc_param_len.cur = mcl_seq.md_tracks[last_md_track].length; show_chan = false; @@ -77,10 +86,18 @@ void SeqPtcPage::init_poly() { void SeqPtcPage::init() { DEBUG_PRINT_FN(); SeqPage::init(); + seq_menu_page.menu.enable_entry(SEQ_MENU_DEVICE, true); seq_menu_page.menu.enable_entry(SEQ_MENU_TRACK, true); seq_menu_page.menu.enable_entry(SEQ_MENU_ARP, true); seq_menu_page.menu.enable_entry(SEQ_MENU_TRANSPOSE, true); seq_menu_page.menu.enable_entry(SEQ_MENU_POLY, true); + if (midi_device == &MD) { + seq_menu_page.menu.enable_entry(SEQ_MENU_SOUND, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_MD, true); + } + else { + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_EXT, true); + } cc_link_enable = true; scale_padding = false; ptc_param_len.handler = pattern_len_handler; @@ -88,11 +105,6 @@ void SeqPtcPage::init() { DEBUG_PRINTLN(mcl_cfg.uart2_ctrl_chan); trig_interface.on(); trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); - if (mcl_cfg.uart2_ctrl_chan == MIDI_LOCAL_MODE) { - trig_interface.on(); - } else { - trig_interface.off(); - } config(); re_init = false; } @@ -130,14 +142,17 @@ void SeqPtcPage::config() { config_as_trackedit(); } void SeqPtcPage::loop() { - opt_midi_device_capture = midi_device; if (re_init) { init(); } if (ptc_param_oct.hasChanged() || ptc_param_scale.hasChanged() || ptc_param_fine_tune.hasChanged()) { + uint8_t dev = midi_device == &MD ? 0 : 1; + octs[dev] = encoders[0]->cur; + fine_tunes[dev] = encoders[1]->cur; + uint8_t track = last_md_track; - if (midi_device != &MD) { + if (dev) { track = last_ext_track; mcl_seq.ext_tracks[last_ext_track].buffer_notesoff(); } @@ -147,19 +162,22 @@ void SeqPtcPage::loop() { } uint8_t SeqPtcPage::find_arp_track(uint8_t channel_event) { uint8_t track = last_md_track; - if (channel_event == POLY_EVENT) { - uint16_t mask = mcl_cfg.poly_mask; - uint8_t n = 0; - while (mask) { - if (mask & 1) { return n; } - n++; - mask = mask >> 1; + if (channel_event == POLY_EVENT) { + uint16_t mask = mcl_cfg.poly_mask; + uint8_t n = 0; + while (mask) { + if (mask & 1) { + return n; } + n++; + mask = mask >> 1; } + } return track; } -void SeqPtcPage::render_arp(bool recalc_notemask_, MidiDevice *midi_dev, uint8_t track) { +void SeqPtcPage::render_arp(bool recalc_notemask_, MidiDevice *midi_dev, + uint8_t track) { if (recalc_notemask_) { recalc_notemask(); } @@ -169,8 +187,7 @@ void SeqPtcPage::render_arp(bool recalc_notemask_, MidiDevice *midi_dev, uint8_t if (midi_dev == &MD) { seq_track = &mcl_seq.md_tracks[track]; arp_track = &mcl_seq.md_arp_tracks[track]; - } - else { + } else { seq_track = &mcl_seq.ext_tracks[track]; arp_track = &mcl_seq.ext_arp_tracks[track]; } @@ -239,19 +256,19 @@ void SeqPtcPage::display() { arp_track = &mcl_seq.md_arp_tracks[last_md_track]; } if ((mcl_cfg.poly_mask > 0) && (is_poly)) { - oled_display.print("PLY"); + oled_display.print(F("PLY")); } uint64_t *mask = note_mask; if (arp_track->enabled) { - oled_display.print("ARP"); + oled_display.print(F("ARP")); mask = arp_track->note_mask; } mcl_gui.draw_keyboard(32, 23, 6, 9, NUM_KEYS, mask); SeqPage::display(); if (show_seq_menu) { - display_ext_mute_mask(); + display_mute_mask(midi_active_peering.get_device(UART2_PORT), 8); } oled_display.display(); oled_display.setFont(oldfont); @@ -285,24 +302,24 @@ uint8_t SeqPtcPage::calc_scale_note(uint8_t note_num, bool padded) { return scales[ptc_param_scale.cur]->pitches[pos] + oct * 12 + transpose; } -uint8_t SeqPtcPage::get_next_voice(uint8_t pitch, uint8_t track_number, uint8_t channel_event) { +uint8_t SeqPtcPage::get_next_voice(uint8_t pitch, uint8_t track_number, + uint8_t channel_event) { uint8_t voice = 255; if (channel_event == POLY_EVENT) { goto poly; - } - else if (channel_event == CTRL_EVENT) { + } else if (channel_event == CTRL_EVENT) { - // mono - if (!mcl_cfg.poly_mask || (!IS_BIT_SET16(mcl_cfg.poly_mask, track_number))) { + // mono + if (!mcl_cfg.poly_mask || + (!IS_BIT_SET16(mcl_cfg.poly_mask, track_number))) { return track_number; } - } - else { + } else { return 255; } - poly: +poly: // If track previously played pitch, re-use this track for (uint8_t x = 0; x < 16; x++) { if (MD.isMelodicTrack(x) && IS_BIT_SET16(mcl_cfg.poly_mask, x)) { @@ -312,11 +329,11 @@ uint8_t SeqPtcPage::get_next_voice(uint8_t pitch, uint8_t track_number, uint8_t } } + int oldest_val = -1; if (voice != 255) { goto end; } // Reuse oldest note - int oldest_val = -1; for (uint8_t x = 0; x < 16; x++) { if (MD.isMelodicTrack(x) && IS_BIT_SET16(mcl_cfg.poly_mask, x)) { @@ -414,7 +431,7 @@ void SeqPtcPage::trig_md_fromext(uint8_t note_num, uint8_t channel_event) { if (machine_pitch == 255) { return; } - if (GUI.currentPage() == &seq_step_page && channel_event == CTRL_EVENT) { + if (mcl.currentPage() == SEQ_STEP_PAGE && channel_event == CTRL_EVENT) { seq_step_page.pitch_param = note_num; // get_note_from_machine_pitch(machine_pitch); } @@ -438,6 +455,7 @@ void SeqPtcPage::note_on_ext(uint8_t note_num, uint8_t velocity, mcl_seq.ext_tracks[track_number].record_track_noteon(note_num, velocity); //} } + void SeqPtcPage::note_off_ext(uint8_t note_num, uint8_t velocity, uint8_t track_number, MidiUartParent *uart_) { if (track_number == 255) { @@ -450,6 +468,10 @@ void SeqPtcPage::note_off_ext(uint8_t note_num, uint8_t velocity, //} } +void SeqPtcPage::buffer_notesoff_ext(uint8_t track_number) { + mcl_seq.ext_tracks[track_number].buffer_notesoff(); +} + void SeqPtcPage::recalc_notemask() { memset(note_mask, 0, sizeof(note_mask)); @@ -466,13 +488,13 @@ void SeqPtcPage::recalc_notemask() { } void SeqPtcPage::draw_popup_transpose() { - char *str = "KEY: "; + char str[] = "KEY: "; mcl_gui.put_value_at(transpose, str + 5); MD.popup_text(str); } void SeqPtcPage::draw_popup_octave() { - char *str = "OCT: "; + char str[] = "OCT: "; mcl_gui.put_value_at(ptc_param_oct.cur, str + 5); MD.popup_text(str); } @@ -496,41 +518,34 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } return true; } - + /* if (mask == EVENT_BUTTON_PRESSED) { SET_BIT128_P(dev_note_masks[0], note); } else { CLEAR_BIT128_P(dev_note_masks[0], note); } + */ - uint8_t pitch = calc_scale_note(note); - if (pitch > 127) - return false; - DEBUG_PRINTLN(F("yep")); // note interface presses are treated as musical notes here - if (mask == EVENT_BUTTON_PRESSED) { - - if (midi_device != &MD) { - midi_device = &MD; - config(); - } else { - config_encoders(); - } - scale_padding = false; + scale_padding = false; + bool is_md = midi_device == &MD; + uint8_t channel_event = NO_EVENT; + + if (is_md) { + note += MIDI_NOTE_C4; + bool is_poly = IS_BIT_SET16(mcl_cfg.poly_mask, last_md_track); + channel_event = is_poly ? POLY_EVENT : CTRL_EVENT; + } else { + note += MIDI_NOTE_C1; + } + uint8_t msg[] = {MIDI_NOTE_ON | (is_md ? last_md_track : last_ext_track), + note, 127}; - SET_BIT128_P(note_mask, pitch); + if (mask == EVENT_BUTTON_PRESSED) { + midi_events.note_on(msg, channel_event); - arp_page.track_update(); - ArpSeqTrack *arp_track = &mcl_seq.md_arp_tracks[last_md_track]; - if ((!arp_track->enabled) || (MidiClock.state != 2)) { - trig_md(pitch + ptc_param_oct.cur * 12); - } - render_arp(false, device, last_md_track); } else if (mask == EVENT_BUTTON_RELEASED) { - if (arp_enabled.cur != ARP_LATCH) { - CLEAR_BIT128_P(note_mask, pitch); - render_arp(false, device, last_md_track); - } + midi_events.note_off(msg, channel_event); } trig_interface.send_md_leds(TRIGLED_EXCLUSIVE); @@ -575,6 +590,13 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { draw_popup_octave(); return true; } + case MDX_KEY_SCALE: { + midi_device = midi_device == &MD + ? midi_active_peering.get_device(UART2_PORT) + : midi_active_peering.get_device(UART1_PORT); + config(); + return true; + } } } } @@ -582,7 +604,7 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { if (EVENT_RELEASED(event, Buttons.BUTTON1)) { if (BUTTON_DOWN(Buttons.BUTTON4)) { re_init = true; - GUI.pushPage(&poly_page); + mcl.pushPage(POLY_PAGE); return true; } mcl_seq.ext_tracks[last_ext_track].init_notes_on(); @@ -591,19 +613,19 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } /* if (EVENT_PRESSED(event, Buttons.ENCODER4)) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return true; } */ if (EVENT_RELEASED(event, Buttons.BUTTON4)) { if (BUTTON_DOWN(Buttons.BUTTON1)) { re_init = true; - GUI.pushPage(&poly_page); + mcl.pushPage(POLY_PAGE); return true; } } if (EVENT_PRESSED(event, Buttons.BUTTON3)) { - ext_mute_mask = 128; + mute_mask = 128; } if (SeqPage::handleEvent(event)) { return true; @@ -613,18 +635,33 @@ bool SeqPtcPage::handleEvent(gui_event_t *event) { } uint8_t SeqPtcPage::seq_ext_pitch(uint8_t note_num) { - scale_padding = true; uint8_t pitch = calc_scale_note(note_num, scale_padding); return (pitch < 128) ? pitch : 255; } -uint8_t SeqPtcPage::process_ext_event(uint8_t note_num, bool note_type, uint8_t channel) { +uint8_t SeqPtcPage::process_ext_event(uint8_t note_num, bool note_type, + uint8_t channel) { uint8_t pitch = seq_ptc_page.seq_ext_pitch(note_num); uint8_t dev = (midi_device == &MD) ? 0 : 1; + SeqTrackBase *arp_track = dev ? (SeqTrackBase*) &mcl_seq.ext_arp_tracks[last_ext_track] : (SeqTrackBase*) &mcl_seq.md_arp_tracks[last_md_track]; dev_note_channels[dev] = channel; if (note_type) { + bool notes_all_off = seq_ptc_page.dev_note_masks[dev][0] == 0 && seq_ptc_page.dev_note_masks[dev][1] == 0; + + if (notes_all_off) { + if (dev) { mcl_seq.ext_arp_tracks[last_ext_track].idx = 0; } + else { mcl_seq.md_arp_tracks[last_md_track].idx = 0; } + + if (mcl_cfg.rec_quant == 0) { + arp_track->mod12_counter = arp_track->get_timing_mid() - 2; + arp_track->step_count = arp_track->length - 1; + } + if (arp_enabled.cur == ARP_LATCH) { + memset(seq_ptc_page.note_mask, 0, sizeof(seq_ptc_page.note_mask)); + } + } SET_BIT128_P(seq_ptc_page.dev_note_masks[dev], note_num); if (pitch != 255) { SET_BIT128_P(seq_ptc_page.note_mask, pitch); @@ -635,17 +672,18 @@ uint8_t SeqPtcPage::process_ext_event(uint8_t note_num, bool note_type, uint8_t CLEAR_BIT128_P(seq_ptc_page.note_mask, pitch); } } - + if (pitch == 255) { + return 255; + } pitch += ptc_param_oct.cur * 12; - return pitch; + return (pitch < 128) ? pitch : 255; } uint8_t SeqPtcPage::is_md_midi(uint8_t channel) { - if ((mcl_cfg.uart2_poly_chan - 1 == channel) || (mcl_cfg.uart2_poly_chan == MIDI_OMNI_MODE)) { + if (mcl_cfg.uart2_poly_chan - 1 == channel) { return POLY_EVENT; } - - if (((mcl_cfg.uart2_ctrl_chan - 1 == channel) || (mcl_cfg.uart2_ctrl_chan == MIDI_OMNI_MODE)) && (GUI.currentPage() != &seq_extstep_page)) { + if (mcl_cfg.uart2_ctrl_chan - 1 == channel) { return CTRL_EVENT; } if (mcl_cfg.md_trig_channel - 1 == channel) { @@ -653,40 +691,79 @@ uint8_t SeqPtcPage::is_md_midi(uint8_t channel) { } return NO_EVENT; -/* - return (mcl_cfg.uart2_ctrl_chan != MIDI_LOCAL_MODE) && - (GUI.currentPage() != &seq_extstep_page); -*/ + /* + return (mcl_cfg.uart2_ctrl_chan != MIDI_LOCAL_MODE) && + (mcl.currentPage() != SEQ_EXTSTEP_PAGE); + */ } +void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { + uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); + uint8_t channel_event = seq_ptc_page.is_md_midi(channel); + if (channel_event) { + if (mcl.currentPage() != SEQ_EXTSTEP_PAGE) { + SeqPage::midi_device = midi_active_peering.get_device(UART1_PORT); + } + } else { + auto active_device = midi_active_peering.get_device(UART2_PORT); + uint8_t n = mcl_seq.find_ext_track(channel); + if (n == 255) { + return; + } + if (SeqPage::midi_device != active_device || (last_ext_track != n)) { + SeqPage::midi_device = active_device; + last_ext_track = min(n, NUM_EXT_TRACKS - 1); + seq_ptc_page.config(); + } else { + SeqPage::midi_device = active_device; + } + } + uint8_t scale_padding_old = seq_ptc_page.scale_padding; + seq_ptc_page.scale_padding = true; + note_on(msg, channel_event); + seq_ptc_page.scale_padding = scale_padding_old; +} -void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { +void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { + uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); + uint8_t channel_event = seq_ptc_page.is_md_midi(channel); + if (channel_event) { + + } else { + uint8_t n = mcl_seq.find_ext_track(channel); + if (n == 255) { + return; + } + } + uint8_t scale_padding_old = seq_ptc_page.scale_padding; + seq_ptc_page.scale_padding = true; + note_off(msg, channel_event); + seq_ptc_page.scale_padding = scale_padding_old; +} + +void SeqPtcMidiEvents::note_on(uint8_t *msg, uint8_t channel_event) { uint8_t note_num = msg[1]; uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); DEBUG_PRINTLN("note on"); DEBUG_DUMP(channel); - // matches control channel, or MIDI2 is OMNI? - // then route midi message to MD - // - // pitch - MIDI_NOTE_C4 // uint8_t pitch; bool note_on = true; - uint8_t channel_event = seq_ptc_page.is_md_midi(channel); - if (channel_event) { - SeqPage::midi_device = midi_active_peering.get_device(UART1_PORT); - if (note_num < MIDI_NOTE_C4) { - if (mcl_cfg.md_trig_channel - 1 == channel) { - uint8_t pos = note_num - MIDI_NOTE_C2; - if (pos > 15) { return; } - MD.triggerTrack(pos, msg[2]); - if ((seq_ptc_page.recording) && (MidiClock.state == 2)) { - reset_undo(); - mcl_seq.md_tracks[pos].record_track(msg[2]); - } + if (channel_event) { + if (channel_event == TRIG_EVENT) { + if (note_num < MIDI_NOTE_C4) { + uint8_t pos = note_num - MIDI_NOTE_C2; + if (pos > 15) { + return; + } + MD.triggerTrack(pos, msg[2]); + if ((seq_ptc_page.recording) && (MidiClock.state == 2)) { + reset_undo(); + mcl_seq.md_tracks[pos].record_track(msg[2]); + } } } uint8_t note = note_num - (note_num / 12) * 12; @@ -696,7 +773,7 @@ void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { uint8_t n = seq_ptc_page.find_arp_track(channel_event); if (channel_event == CTRL_EVENT) { - arp_page.track_update(n); + arp_page.track_update(n); } seq_ptc_page.render_arp(false, SeqPage::midi_device, n); @@ -713,27 +790,15 @@ void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { } #ifdef EXT_TRACKS // otherwise, translate the message and send it back to MIDI2. - auto active_device = midi_active_peering.get_device(UART2_PORT); - uint8_t n = mcl_seq.find_ext_track(channel); - if (n == 255) { - return; - } - - if (SeqPage::midi_device != active_device || (last_ext_track != n)) { - SeqPage::midi_device = active_device; - last_ext_track = min(n, NUM_EXT_TRACKS - 1); - seq_ptc_page.config(); - } else { - SeqPage::midi_device = active_device; - } - pitch = seq_ptc_page.process_ext_event(note_num, note_on, channel); seq_ptc_page.config_encoders(); ArpSeqTrack *arp_track = &mcl_seq.ext_arp_tracks[last_ext_track]; arp_page.track_update(); - seq_ptc_page.render_arp(false, SeqPage::midi_device, n); + seq_ptc_page.render_arp(false, SeqPage::midi_device, last_ext_track); + if (pitch == 255) + return; seq_extstep_page.set_cur_y(pitch); @@ -744,13 +809,12 @@ void SeqPtcMidiEvents::onNoteOnCallback_Midi2(uint8_t *msg) { return; } -void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { +void SeqPtcMidiEvents::note_off(uint8_t *msg, uint8_t channel_event) { DEBUG_PRINTLN(F("note off midi2")); uint8_t note_num = msg[1]; uint8_t channel = MIDI_VOICE_CHANNEL(msg[0]); uint8_t pitch; - uint8_t channel_event = seq_ptc_page.is_md_midi(channel); if (channel_event) { if (note_num < MIDI_NOTE_C4) { return; @@ -766,19 +830,15 @@ void SeqPtcMidiEvents::onNoteOffCallback_Midi2(uint8_t *msg) { } #ifdef EXT_TRACKS - SeqPage::midi_device = midi_active_peering.get_device(UART2_PORT); pitch = seq_ptc_page.process_ext_event(note_num, false, channel); - uint8_t n = mcl_seq.find_ext_track(channel); - if (n == 255) { - return; - } - last_ext_track = min(n, NUM_EXT_TRACKS - 1);; seq_ptc_page.config_encoders(); - - seq_ptc_page.render_arp(false, SeqPage::midi_device, n); + seq_ptc_page.render_arp(false, SeqPage::midi_device, last_ext_track); arp_page.track_update(); + if (pitch == 255) + return; + ArpSeqTrack *arp_track = &mcl_seq.ext_arp_tracks[last_ext_track]; if (!arp_track->enabled) { seq_ptc_page.note_off_ext(pitch, msg[2]); @@ -796,7 +856,7 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { bool send_uart2 = true; - //CC_FWD + // CC_FWD // if (mcl_cfg.uart_cc_loopback) { MidiUart2.sendCC(channel, param, value); @@ -819,9 +879,6 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { if (channel_event == POLY_EVENT) { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, n)) { - if (track_param < 24) { - mcl_seq.md_tracks[n].update_param(param - 16, value); - } MD.setTrackParam(n, param - 16, value, nullptr, true); } } @@ -829,30 +886,61 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi2(uint8_t *msg) { return; } - uint8_t n = mcl_seq.find_ext_track(channel); + uint8_t n = mcl_seq.find_ext_track(channel); if (n == 255) { return; } - //Send mod wheel CC#1 or bank select CC#0 + // Send mod wheel CC#1 or bank select CC#0 if (send_uart2 && param < 2) { mcl_seq.ext_tracks[n].send_cc(param, value); } - if (GUI.currentPage() == &seq_extstep_page && SeqPage::pianoroll_mode > 0) { - if (mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] - 1 == - PARAM_LEARN) { - mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] = - param + 1; - SeqPage::param_select = param; + if (mcl.currentPage() == SEQ_EXTSTEP_PAGE) { + if (SeqPage::pianoroll_mode > 0) { + if (mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] - 1 == + PARAM_LEARN) { + mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] = + param + 1; + SeqPage::param_select = param; + } + if (mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] - 1 == + param) { + seq_extstep_page.lock_cur_y = value; + } } - if (mcl_seq.ext_tracks[n].locks_params[SeqPage::pianoroll_mode - 1] - 1 == - param) { - seq_extstep_page.lock_cur_y = value; + if (last_ext_track == n) { + auto &active_track = mcl_seq.ext_tracks[n]; + uint8_t timing_mid = active_track.get_timing_mid(); + int a = 16 * timing_mid; + for (uint8_t i = 0; i < 16; i++) { + + if (note_interface.is_note_on(i)) { + auto &active_track = mcl_seq.ext_tracks[n]; + + uint8_t step = ((seq_extstep_page.cur_x / a) * 16) + i; + + active_track.clear_track_locks(step, param, 255); + active_track.set_track_locks(step, timing_mid, param, value, + SeqPage::slide); + if (SeqPage::pianoroll_mode == 0) { + char str[] = "CC:"; + char str2[] = "-- "; + mcl_gui.put_value_at(value, str2); + oled_display.textbox(str, str2); + } else { + uint8_t lock_idx = active_track.find_lock_idx(param); + if (lock_idx != 255) { + SeqPage::pianoroll_mode = lock_idx + 1; + } + } + } + } } } - if (SeqPage::recording && (MidiClock.state == 2)) { + if (SeqPage::recording && (MidiClock.state == 2) && + !note_interface.notes_on) { if (param != midi_active_peering.get_device(UART2_PORT)->get_mute_cc()) { mcl_seq.ext_tracks[n].record_track_locks(param, value, SeqPage::slide); } @@ -917,7 +1005,9 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { } MD.parseCC(channel, param, &track, &track_param); - if (track > 15) { return; } + if (track > 15) { + return; + } uint8_t start_track; if (track_param == 32) { return; @@ -927,17 +1017,17 @@ void SeqPtcMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { for (uint8_t n = 0; n < 16; n++) { if (IS_BIT_SET16(mcl_cfg.poly_mask, n) && (n != track)) { - if ((track_param < 24 && track_param > 7) || (track_param < 8 && MD.kit.models[n] == MD.kit.models[track])) { - mcl_seq.md_tracks[n].update_param(track_param, value); - MD.setTrackParam(n, track_param, value, nullptr, true); - display_polylink = 1; - } + if ((track_param < 24 && track_param > 7) || + (track_param < 8 && MD.kit.models[n] == MD.kit.models[track])) { + MD.setTrackParam(n, track_param, value, nullptr, true); + display_polylink = 1; } + } // in_sysex = 0; } } - if (display_polylink && GUI.currentPage() != &mixer_page) { + if (display_polylink && mcl.currentPage() != MIXER_PAGE) { oled_display.textbox("POLY-", "LINK"); } } @@ -984,10 +1074,10 @@ void SeqPtcMidiEvents::setup_callbacks() { return; } if (mcl_cfg.midi_ctrl_port == 1 || mcl_cfg.midi_ctrl_port == 3) { - setup_midi(&Midi2); + setup_midi(&Midi2); } if (mcl_cfg.midi_ctrl_port == 2 || mcl_cfg.midi_ctrl_port == 3) { - setup_midi(&MidiUSB); + setup_midi(&MidiUSB); } Midi.addOnControlChangeCallback( this, @@ -995,7 +1085,6 @@ void SeqPtcMidiEvents::setup_callbacks() { state = true; } - void SeqPtcMidiEvents::remove_callbacks() { if (!state) { return; diff --git a/avr/cores/megacommand/MCL/SeqPtcPage.h b/avr/cores/megacommand/MCL/SeqPtcPage.h index 2cc156e77..5ce462a39 100644 --- a/avr/cores/megacommand/MCL/SeqPtcPage.h +++ b/avr/cores/megacommand/MCL/SeqPtcPage.h @@ -26,8 +26,12 @@ class SeqPtcMidiEvents : public MidiCallback { void setup_callbacks(); void remove_callbacks(); + void note_on(uint8_t *msg, uint8_t channel_event); + void note_off(uint8_t *msg, uint8_t channel_event); + void onNoteOnCallback_Midi2(uint8_t *msg); void onNoteOffCallback_Midi2(uint8_t *msg); + void onControlChangeCallback_Midi(uint8_t *msg); void onControlChangeCallback_Midi2(uint8_t *msg); @@ -51,6 +55,9 @@ class SeqPtcPage : public SeqPage, public ClockCallback { bool scale_padding; bool cc_link_enable; + uint8_t octs[NUM_DEVS]; + uint8_t fine_tunes[NUM_DEVS]; + uint8_t find_arp_track(uint8_t channel_event); SeqPtcMidiEvents midi_events; @@ -74,12 +81,14 @@ class SeqPtcPage : public SeqPage, public ClockCallback { uint8_t track_number = 255, MidiUartParent *uart_ = nullptr); + void buffer_notesoff_ext(uint8_t track_number); + void clear_trig_fromext(uint8_t note_num); uint8_t get_note_from_machine_pitch(uint8_t pitch); uint8_t is_md_midi(uint8_t channel); - void config_encoders(); + virtual void config_encoders(); void init_poly(); void render_arp(bool recalc_notemask_, MidiDevice *midi_dev, uint8_t track); diff --git a/avr/cores/megacommand/MCL/SeqStepPage.cpp b/avr/cores/megacommand/MCL/SeqStepPage.cpp index f4e4fd116..0222ececb 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.cpp +++ b/avr/cores/megacommand/MCL/SeqStepPage.cpp @@ -6,16 +6,15 @@ void SeqStepPage::setup() { SeqPage::setup(); } void SeqStepPage::config() { - seq_param3.cur = mcl_seq.md_tracks[last_md_track].length; - seq_param3.old = seq_param3.cur; + tuning_t const *tuning = MD.getKitModelTuning(last_md_track); - seq_param4.cur = 0; - seq_param4.old = 0; if (tuning) { seq_param4.max = tuning->len - 1 + tuning->base; } else { seq_param4.max = 1; } + seq_param4.cur = 0; + seq_param4.old = 0; // config info labels const char *str1 = getMDMachineNameShort(MD.kit.get_model(last_md_track), 1); const char *str2 = getMDMachineNameShort(MD.kit.get_model(last_md_track), 2); @@ -37,6 +36,9 @@ void SeqStepPage::config() { } void SeqStepPage::config_encoders() { + if (show_seq_menu) { + return; + } uint8_t timing_mid = mcl_seq.md_tracks[last_md_track].get_timing_mid(); seq_param3.cur = mcl_seq.md_tracks[last_md_track].length; seq_param3.old = seq_param3.cur; @@ -49,10 +51,12 @@ void SeqStepPage::init() { DEBUG_PRINT_FN(); DEBUG_PRINTLN(F("init seqstep")); SeqPage::init(); - opt_midi_device_capture = &MD; pitch_param = 255; seq_menu_page.menu.enable_entry(SEQ_MENU_MASK, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_SOUND, true); + seq_menu_page.menu.enable_entry(SEQ_MENU_LENGTH_MD, true); + SeqPage::midi_device = midi_active_peering.get_device(UART1_PORT); midi_events.setup_callbacks(); @@ -101,6 +105,9 @@ void SeqStepPage::cleanup() { params_reset(); MD.set_rec_mode(0); MD.popup_text(127, 2); // clear persistent trig mode popup + if (MD.encoder_interface) { + MD.deactivate_encoder_interface(); + } } void SeqStepPage::display() { @@ -145,7 +152,7 @@ void SeqStepPage::display() { if (mcl_gui.show_encoder_value(&seq_param4) && (seq_param4.cur > 0) && (note_interface.notes_count_on() > 0) && (!show_seq_menu) && - (!show_step_menu) && (tuning != NULL) && !(recording)) { + (tuning != NULL) && !(recording)) { uint64_t note_mask[2] = {}; uint8_t note = seq_param4.cur; // + tuning->base; SET_BIT64(note_mask, note); @@ -165,7 +172,7 @@ void SeqStepPage::display() { SeqPage::display(); if (mcl_gui.show_encoder_value(&seq_param2) && (note_interface.notes_count_on() > 0) && (!show_seq_menu) && - (!show_step_menu) && (!recording)) { + (!recording)) { mcl_gui.draw_microtiming(mcl_seq.md_tracks[last_md_track].speed, seq_param2.cur); @@ -181,7 +188,7 @@ void SeqStepPage::display() { void SeqStepPage::loop() { if (MD.global.extendedMode != 2) { - GUI.setPage(&grid_page); + mcl.setPage(GRID_PAGE); return; } SeqPage::loop(); @@ -263,7 +270,7 @@ void SeqStepPage::loop() { } if (note_interface.notes_all_off_md() && !grid_page.bank_popup) { - mcl_gui.init_encoders_used_clock(); + init_encoders_used_clock(); // active_track.reset_params(); MD.deactivate_encoder_interface(); @@ -271,10 +278,6 @@ void SeqStepPage::loop() { update_params_clock = slowclock; note_interface.init_notes(); - if (reset_on_release) { - active_track.reset_params(); - reset_on_release = false; - } } MidiUartParent::handle_midi_lock = _midi_lock_tmp; } @@ -312,7 +315,13 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { if (device != &MD) { return true; } - + if (show_seq_menu) { + opt_trackid = track + 1; + note_interface.ignoreNextEvent(track); + select_track(device, track); + seq_menu_page.select_item(0); + return true; + } uint8_t step = track + (page_select * 16); step_select = track; @@ -361,7 +370,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { tuning_t const *tuning = MD.getKitModelTuning(last_md_track); uint8_t pitch = active_track.get_track_lock_implicit(step, 0); if (pitch > 127) { - pitch = MD.kit.params[last_md_track][0]; + pitch = MD.kit.params[last_md_track][0]; } /* if (pitch == 255) { @@ -386,12 +395,13 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { seq_param2.cur = utiming; seq_param2.old = utiming; if (!active_track.get_step(step, mask_type)) { + reset_undo(); bool cond_plock; active_track.steps[step].cond_id = translate_to_step_conditional(condition, &cond_plock); active_track.steps[step].cond_plock = cond_plock; active_track.timing[step] = utiming; - CLEAR_BIT64(active_track.oneshot_mask, step); + CLEAR_BIT64(active_track.mute_mask, step); active_track.set_step(step, mask_type, true); SET_BIT16(ignore_release, track); } @@ -413,6 +423,7 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { if (clock_diff(note_interface.note_hold[port], slowclock) < TRIG_HOLD_TIME) { + reset_undo(); active_track.set_step(step, mask_type, false); if (mask_type == MASK_PATTERN) { active_track.steps[step].cond_id = 0; @@ -529,20 +540,19 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { } break; } - case MDX_KEY_YES: { - if (step == 255) { - return true; - } - active_track.send_parameter_locks(step, true); - reset_on_release = true; - MD.triggerTrack(last_md_track, 127); - break; - } case MDX_KEY_NO: { if (mask_type != MASK_PATTERN) { mask_type = MASK_PATTERN; config_mask_info(false); } + else { + for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { + if (note_interface.is_note_on(n)) { + uint8_t s = n + (page_select * 16); + TOGGLE_BIT64(active_track.mute_mask,s); + } + } + } break; } case MDX_KEY_BANKB: { @@ -579,35 +589,33 @@ bool SeqStepPage::handleEvent(gui_event_t *event) { } break; } - case MDX_KEY_UP: { - if (step == 255) { - return; - } - seq_param1.cur += 1; - return true; } - case MDX_KEY_DOWN: { - if (step == 255) { - return; + if (step != 255) { + switch (key) { + case MDX_KEY_YES: { + active_track.send_parameter_locks(step, true); + reset_on_release = true; + MD.triggerTrack(last_md_track, 127); + break; } - seq_param1.cur -= 1; - return; - } - case MDX_KEY_LEFT: { - if (step == 255) { - return; + case MDX_KEY_UP: { + seq_param1.cur += 1; + break; + } + case MDX_KEY_DOWN: { + seq_param1.cur -= 1; + break; + } + case MDX_KEY_LEFT: { + seq_param2.cur -= 1; + break; + } + case MDX_KEY_RIGHT: { + seq_param2.cur += 1; + break; } - seq_param2.cur -= 1; - return true; - } - case MDX_KEY_RIGHT: { - if (step == 255) { - return; } - seq_param2.cur += 1; - return true; - } } return true; } @@ -687,15 +695,12 @@ void SeqStepMidiEvents::onControlChangeCallback_Midi(uint8_t *msg) { } seq_step_page.config_encoders(); - mcl_seq.md_tracks[track].update_param(track_param, value); - - MD.kit.params[track][track_param] = value; mcl_seq.md_tracks[track].record_track_locks(track_param, value); return; } uint8_t store_lock = 255; - for (int i = 0; i < 16; i++) { + for (uint8_t i = 0; i < 16; i++) { if ((note_interface.is_note_on(i))) { step = i + (SeqPage::page_select * 16); if (step < active_track.length) { diff --git a/avr/cores/megacommand/MCL/SeqStepPage.h b/avr/cores/megacommand/MCL/SeqStepPage.h index 0ee944d07..e9c195d70 100644 --- a/avr/cores/megacommand/MCL/SeqStepPage.h +++ b/avr/cores/megacommand/MCL/SeqStepPage.h @@ -20,11 +20,13 @@ class SeqStepPage : public SeqPage { bool reset_on_release = false; bool update_params_queue; bool prepare = false; + uint8_t pitch_param; uint16_t ignore_release; uint16_t update_params_clock; uint8_t last_param_id; uint8_t last_rec_event; + PageIndex last_page = NULL_PAGE; SeqStepMidiEvents midi_events; SeqStepPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, Encoder *e4 = NULL) diff --git a/avr/cores/megacommand/MCL/SeqTrack.cpp b/avr/cores/megacommand/MCL/SeqTrack.cpp index b4b4b9534..3771e307a 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.cpp +++ b/avr/cores/megacommand/MCL/SeqTrack.cpp @@ -127,3 +127,105 @@ void SeqSlideTrack::send_slides(volatile uint8_t *locks_params, uint8_t channel) } } } + +uint8_t SeqTrackBase::get_quantized_step(uint8_t &utiming, uint8_t quant) { + if (quant == 255) { quant = mcl_cfg.rec_quant; } + + uint8_t timing_mid = get_timing_mid(); + + int8_t mod12 = mod12_counter - 1; + + + uint8_t step = step_count; +/* + if ((step == 0) && (mod12 < 0)) { + mod12 += timing_mid; + step = length - 1; + } +*/ + utiming = mod12 + timing_mid; + + if (quant) { + if (mod12 > timing_mid / 2) { + step++; + if (step == length) { + step = 0; + } + } + utiming = timing_mid; + } + return step; +} + +bool SeqTrack::conditional(uint8_t condition) { + bool send_note = false; + uint8_t random_byte = 0; + if (condition >= 9) { random_byte = get_random_byte(); } + + switch (condition) { + case 0: + case 1: + send_note = true; + break; + case 2: + if (!IS_BIT_SET(iterations_8, 0)) { + send_note = true; + } + break; + case 3: + if ((iterations_6 == 3) || (iterations_6 == 6)) { + send_note = true; + } + break; + case 6: + if (iterations_6 == 6) { + send_note = true; + } + break; + case 4: + if ((iterations_8 == 4) || (iterations_8 == 8)) { + send_note = true; + } + break; + case 8: + if (iterations_8 == 8) { + send_note = true; + } + case 5: + if (iterations_5 == 5) { + send_note = true; + } + break; + case 7: + if (iterations_7 == 7) { + send_note = true; + } + break; + case 9: + if (random_byte <= 26) { + send_note = true; + } + break; + case 10: + if (random_byte <= 64) { + send_note = true; + } + break; + case 11: + if (random_byte <= 128) { + send_note = true; + } + break; + case 12: + if (random_byte <= 192) { + send_note = true; + } + break; + case 13: + if (random_byte <= 230) { + send_note = true; + } + break; + } + return send_note; +} diff --git a/avr/cores/megacommand/MCL/SeqTrack.h b/avr/cores/megacommand/MCL/SeqTrack.h index 662ea0312..44109a442 100644 --- a/avr/cores/megacommand/MCL/SeqTrack.h +++ b/avr/cores/megacommand/MCL/SeqTrack.h @@ -4,7 +4,7 @@ #define SEQTRACK_H__ #include "MCLMemory.h" -#include "MidiActivePeering.h" +//#include "MidiActivePeering.h" #include "MidiUartParent.h" #include "WProgram.h" @@ -20,6 +20,7 @@ #define SEQ_SPEED_1_2X 4 #define SEQ_SPEED_1_4X 5 #define SEQ_SPEED_1_8X 6 +#define SEQ_SPEED_4X 7 #define MASK_PATTERN 0 #define MASK_LOCK 1 @@ -29,6 +30,17 @@ #define NUM_LOCKS 8 +#define TRIG_FALSE 0 +#define TRIG_TRUE 1 +#define TRIG_ONESHOT 3 + +#define UART1_PORT 1 + +// Sequencer editing constants +#define DIR_LEFT 0 +#define DIR_RIGHT 1 +#define DIR_REVERSE 2 + class SeqTrack_270 {}; class SlideData { @@ -59,6 +71,8 @@ class SeqTrackBase { MidiUartParent *uart = &MidiUart; uint8_t mute_state = SEQ_MUTE_OFF; + bool record_mutes; + uint8_t length; uint8_t speed; uint8_t track_number; @@ -66,7 +80,9 @@ class SeqTrackBase { uint8_t step_count; uint8_t mod12_counter; - SeqTrackBase() { active = EMPTY_TRACK_TYPE; } + uint8_t count_down; + + SeqTrackBase() { active = EMPTY_TRACK_TYPE; record_mutes = false; } ALWAYS_INLINE() void step_count_inc() { if (step_count == length - 1) { @@ -77,11 +93,31 @@ class SeqTrackBase { } } + ALWAYS_INLINE() void seq() { + uint8_t timing_mid = get_timing_mid(); + mod12_counter++; + if (count_down) { + count_down--; + if (count_down == 0) { + reset(); + mod12_counter = 0; + } + } + if (mod12_counter == timing_mid) { + count_down = 0; + mod12_counter = 0; + step_count_inc(); + } + } + + ALWAYS_INLINE() void reset() { mod12_counter = -1; step_count = 0; } + void toggle_mute() { mute_state = !mute_state; } + uint8_t get_timing_mid(uint8_t speed_) { uint8_t timing_mid; switch (speed_) { @@ -92,6 +128,9 @@ class SeqTrackBase { case SEQ_SPEED_2X: timing_mid = 6; break; + case SEQ_SPEED_4X: + timing_mid = 3; + break; case SEQ_SPEED_3_4X: timing_mid = 16; // 12 * (4.0/3.0); break; @@ -123,6 +162,9 @@ class SeqTrackBase { case SEQ_SPEED_2X: timing_mid = 6; break; + case SEQ_SPEED_4X: + timing_mid = 3; + break; case SEQ_SPEED_3_4X: timing_mid = 16; // 12 * (4.0/3.0); break; @@ -144,6 +186,46 @@ class SeqTrackBase { float get_speed_multiplier() { return get_speed_multiplier(speed); } + void get_speed_multiplier(uint8_t speed_, uint8_t &n, uint8_t &d) { + n = 1; + d = 1; + switch (speed_) { + default: + case SEQ_SPEED_1X: + //n = 1; + //d = 1; + break; + case SEQ_SPEED_2X: + //n = 1; + d = 2; + break; + case SEQ_SPEED_4X: + //n = 1; + d = 4; + break; + case SEQ_SPEED_3_4X: + n = 4; + d = 3; + break; + case SEQ_SPEED_3_2X: + n = 2; + d = 3; + break; + case SEQ_SPEED_1_2X: + n = 2; + //d = 1; + break; + case SEQ_SPEED_1_4X: + n = 4; + //d = 1; + break; + case SEQ_SPEED_1_8X: + n = 8; + //d = 1; + break; + } + } + float get_speed_multiplier(uint8_t speed_) { float multi; switch (speed_) { @@ -154,6 +236,9 @@ class SeqTrackBase { case SEQ_SPEED_2X: multi = 0.5; break; + case SEQ_SPEED_4X: + multi = 0.25; + break; case SEQ_SPEED_3_4X: multi = (4.0 / 3.0); break; @@ -172,6 +257,12 @@ class SeqTrackBase { } return multi; } + + uint8_t get_quantized_step() { + uint8_t u = 0; + return get_quantized_step(u); + } + uint8_t get_quantized_step(uint8_t &utiming, uint8_t quant = 255); }; class SeqTrack : public SeqTrackBase { @@ -183,8 +274,6 @@ class SeqTrack : public SeqTrackBase { uint8_t iterations_7; uint8_t iterations_8; - uint8_t count_down; - uint16_t cur_event_idx; uint8_t ignore_step; @@ -245,6 +334,7 @@ class SeqTrack : public SeqTrackBase { step_count++; } } + bool conditional(uint8_t condition); }; class SeqSlideTrack : public SeqTrack { @@ -255,6 +345,14 @@ class SeqSlideTrack : public SeqTrack { uint8_t locks_slides_recalc = 255; uint16_t locks_slides_idx = 0; + ALWAYS_INLINE() void reset() { + for (uint8_t n = 0; n < NUM_LOCKS; n++) { + locks_slide_data[n].init(); + } + SeqTrack::reset(); + } + + void prepare_slide(uint8_t lock_idx, int16_t x0, int16_t x1, int8_t y0, int8_t y1); void send_slides(volatile uint8_t *locks_params, uint8_t channel = 0); diff --git a/avr/cores/megacommand/MCL/Shared.h b/avr/cores/megacommand/MCL/Shared.h index 9d7e0b407..a322def5f 100644 --- a/avr/cores/megacommand/MCL/Shared.h +++ b/avr/cores/megacommand/MCL/Shared.h @@ -3,7 +3,7 @@ #ifndef SHARED_H__ #define SHARED_H__ -#include "MCL.h" +#include "mcl.h" #include "math.h" struct MusicalNotes { diff --git a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp index 5ec186012..54dd0f6f5 100644 --- a/avr/cores/megacommand/MCL/SoundBrowserPage.cpp +++ b/avr/cores/megacommand/MCL/SoundBrowserPage.cpp @@ -1,76 +1,35 @@ #include "MCL_impl.h" #include "ResourceManager.h" -const char *c_sound_root = "/Sounds/MD"; -const char *c_wav_root = "/Samples/WAV"; -const char *c_syx_root = "/Samples/SYX"; +const char *c_snd_root = "/Sounds"; const char *c_snd_suffix = ".snd"; -const char *c_wav_suffix = ".wav"; -const char *c_syx_suffix = ".syx"; - -const char *c_snd_name = "SOUND"; -const char *c_wav_name = "WAV"; -const char *c_syx_name = "SYSEX"; static bool s_query_returned = false; void SoundBrowserPage::setup() { - SD.mkdir(c_sound_root, true); - SD.mkdir(c_wav_root, true); - SD.mkdir(c_syx_root, true); - show_samplemgr = false; - sysex = &(Midi.midiSysex); + SD.mkdir(c_snd_root, true); FileBrowserPage::setup(); - chdir_type(); -} - -void SoundBrowserPage::chdir_type() { - DEBUG_PRINTLN("chdir type"); - if (filetype_idx == FT_WAV) { - _cd(c_wav_root); - } - else if (filetype_idx == FT_SND) { - _cd(c_sound_root); - } - else { - _cd(c_syx_root); - } + _cd(c_snd_root); + position.reset(); } void SoundBrowserPage::init() { + FileBrowserPage::selection_change = true; + file_types.reset(); + file_types.add(c_snd_suffix); + trig_interface.off(); - filemenu_active = false; - select_dirs = false; - filetypes[0] = c_snd_suffix; - filetypes[1] = c_wav_suffix; - filetypes[2] = c_syx_suffix; - filetype_names[0] = c_snd_name; - filetype_names[1] = c_wav_name; - filetype_names[2] = c_syx_name; - filetype_max = FT_SYX; + strcpy(title, "SOUND"); + show_dirs = true; + show_save = true; + show_filemenu = true; + show_new_folder = true; + show_parent = true; + SD.chdir(lwd); + query_filesystem(); - show_overwrite = false; - if (show_samplemgr) { - strcpy(title, "MD-ROM"); - show_dirs = false; - show_save = false; - show_filemenu = false; - show_new_folder = false; - show_filetypes = false; - show_parent = false; - query_sample_slots(); - } else { - strcpy(match, ".snd"); - strcpy(title, "Select:"); - show_dirs = true; - show_save = (filetype_idx != FT_SYX); - show_filemenu = true; - show_new_folder = true; - show_filetypes = true; - show_parent = true; - query_filesystem(); - } + strcpy(str_save, "[ SAVE ]"); R.Clear(); R.use_machine_names_short(); @@ -125,134 +84,26 @@ void SoundBrowserPage::load_sound() { } } -// send current selected sample file to slot -void SoundBrowserPage::send_sample(int slot, bool is_syx, char *newname, bool silent) { - bool success; - if (file.isOpen()) { - char temp_entry[FILE_ENTRY_SIZE]; - file.getName(temp_entry, FILE_ENTRY_SIZE); - file.close(); - if (!silent) { - if (!mcl_gui.wait_for_confirm("Sample Slot", "Overwrite?")) { - return; - } - } - if (is_syx) { - success = midi_sds.sendSyx(temp_entry, slot); - } else { - char *ptr = newname; - if (newname == nullptr) { - if (isdigit(temp_entry[0]) && isdigit(temp_entry[1]) && (temp_entry[2] != '.') && (temp_entry[2] != '\0')) { ptr = temp_entry + 2; } - } - success = midi_sds.sendWav(temp_entry, ptr, slot, /* show progress */ true); - } - if (!silent) { - if (success) { - gfx.alert("Sample sent", temp_entry); - } else { - gfx.alert("Send failed", temp_entry); - } - } - } -} -void SoundBrowserPage::recv_wav(int slot, bool silent) { - char wav_name[FILE_ENTRY_SIZE] = ""; - // should be of form "ID - NAME..." - // ^--~~~~~~~ - // memmove - get_entry(slot, wav_name); - memmove(wav_name + 2, wav_name + 5, FILE_ENTRY_SIZE - 5); - wav_name[FILE_ENTRY_SIZE - 3] = '\0'; - wav_name[FILE_ENTRY_SIZE - 2] = '\0'; - wav_name[FILE_ENTRY_SIZE - 1] = '\0'; - - if (!silent) { - if (!mcl_gui.wait_for_input(wav_name, "Sample Name", - sizeof(wav_name) - 1)) { - return; - } - } - char temp_entry[FILE_ENTRY_SIZE]; - strncpy(temp_entry, wav_name, sizeof(wav_name) - 1); - strcat(temp_entry, ".wav"); - DEBUG_PRINTLN("bulk recv"); - DEBUG_PRINTLN(temp_entry); - bool ret = midi_sds.recvWav(temp_entry, slot); - if (!silent) { - if (ret) { - gfx.alert("Sample received", temp_entry); - } else { - gfx.alert("Receive failed", temp_entry); - } - } -} void SoundBrowserPage::on_new() { - if (!show_samplemgr) { - switch (filetype_idx) { - case FT_SND: - save_sound(); - break; - case FT_WAV: - pending_action = PA_NEW; - show_samplemgr = true; - show_ram_slots = true; - break; - } - init(); - } else { - // shouldn't happen. - // show_save = false for samplemgr. - show_samplemgr = false; - init(); - } + save_sound(); + init(); } void SoundBrowserPage::on_cancel() { - pending_action = 0; - if (show_samplemgr) { - show_samplemgr = false; - } else { - // TODO cd .. ? - _cd_up(); - } + if (strcmp(lwd, "/") == 0) { mcl.popPage(); return; } + _cd_up(); } void SoundBrowserPage::on_select(const char *__) { - if (!show_samplemgr) { - switch (filetype_idx) { - case FT_SND: - load_sound(); - break; - case FT_WAV: - case FT_SYX: - pending_action = PA_SELECT; - show_samplemgr = true; - show_ram_slots = false; - init(); - break; - } - } else { - auto slot = encoders[1]->cur; - switch (pending_action) { - case PA_NEW: - recv_wav(slot); - break; - case PA_SELECT: - send_sample(slot, (filetype_idx == FT_SYX)); - break; - } - pending_action = 0; - show_samplemgr = false; - init(); - } + load_sound(); } bool SoundBrowserPage::handleEvent(gui_event_t *event) { if (EVENT_PRESSED(event, Buttons.BUTTON3) && show_filemenu) { FileBrowserPage::handleEvent(event); - bool state = (param2->cur == 0) && filetype_idx == FILETYPE_WAV; + bool state = (param2->cur == 0); file_menu_page.menu.enable_entry(FM_NEW_FOLDER, !state); file_menu_page.menu.enable_entry(FM_DELETE, !state); // delete file_menu_page.menu.enable_entry(FM_RENAME, !state); // rename @@ -263,150 +114,13 @@ bool SoundBrowserPage::handleEvent(gui_event_t *event) { } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.popPage(); return true; } return FileBrowserPage::handleEvent(event); } -void SoundBrowserPage::query_sample_slots() { - encoders[1]->cur = 0; - encoders[1]->old = 0; - numEntries = 0; - cur_file = 255; // XXX why 255? - cur_row = 0; - uint8_t data[2] = {0x70, 0x34}; - call_handle_filemenu = false; - s_query_returned = false; - - sysex->addSysexListener(this); - MD.sendRequest(data, 2); - auto time_start = read_slowclock(); - auto time_now = time_start; - do { - handleIncomingMidi(); - time_now = read_slowclock(); - } while (!s_query_returned && clock_diff(time_start, time_now) < 1000); - - if (!s_query_returned) { - add_entry("ERROR"); - } else if (numEntries == 0) { - add_entry("NON-UW MODEL"); - } else if (show_ram_slots) { - bool mk1 = numEntries < 48; - char ram[] = "R1"; - add_entry(ram); - ram[1]++; - add_entry(ram); - if (!mk1) { - ram[1]++; - add_entry(ram); - ram[1]++; - add_entry(ram); - } - } - ((MCLEncoder *)encoders[1])->max = numEntries - 1; - sysex->removeSysexListener(this); -} - -// MidiSysexListenerClass implementation - -bool SoundBrowserPage::_handle_filemenu() { - if (FileBrowserPage::_handle_filemenu()) { - return true; - } - switch (file_menu_page.menu.get_item_index(file_menu_encoder.cur)) { - case FM_RECVALL: - show_samplemgr = true; - show_ram_slots = true; - init(); - if (numEntries == 0) { - gfx.alert("NON", "UW"); - goto end; - } - if (!mcl_gui.wait_for_confirm("Receive all", "Overwrite?")) { - goto end; - } - DEBUG_PRINTLN("Recv samples"); - DEBUG_PRINTLN(numEntries); - for (uint8_t n = 0; n < numEntries; n++) { - DEBUG_PRINTLN("Recv wav"); - char wav_name[FILE_ENTRY_SIZE] = ""; - get_entry(n, wav_name); - DEBUG_PRINTLN(wav_name); - if (wav_name[5] != '[') { recv_wav(n, true); } - } - end: - show_samplemgr = false; - show_ram_slots = false; - init(); - return true; - case FM_SENDALL: - if (!mcl_gui.wait_for_confirm("Send all", "Overwrite?")) { - return; - } - char wav_name[FILE_ENTRY_SIZE] = ""; - for (uint8_t n = 0; n < numEntries; n++) { - get_entry(n, wav_name); - DEBUG_PRINTLN(wav_name); - if (!isdigit(wav_name[0]) || !isdigit(wav_name[1])) continue; - uint8_t slot = (wav_name[0] - '0') * 10 + wav_name[1] - '0' - 1; - DEBUG_PRINTLN("slot pos:"); - DEBUG_PRINTLN(slot); - DEBUG_PRINTLN((uint8_t) wav_name[0]); - DEBUG_PRINTLN((uint8_t) wav_name[1]); - if (slot > 48) { continue; } - - file.open(wav_name); - mcl_gui.draw_progress("Send Samples", n, numEntries); - send_sample(slot, false, wav_name + 2, true); - } - break; - } -} -void SoundBrowserPage::start() {} - -void SoundBrowserPage::end() { - if (sysex->getByte(3) != 0x02) - return; - if (sysex->getByte(4) != 0x00) - return; - if (sysex->getByte(5) != 0x72) - return; - if (sysex->getByte(6) != 0x34) - return; - int nr_samplecount = sysex->getByte(7); - if (nr_samplecount > 48) - return; - - char s_tmpbuf[5]; - char temp_entry[FILE_ENTRY_SIZE]; - - for (int i = 0, j = 7; i < nr_samplecount; ++i) { - for (int k = 0; k < 5; ++k) { - s_tmpbuf[k] = sysex->getByte(++j); - } - bool slot_occupied = s_tmpbuf[4]; - s_tmpbuf[4] = 0; - strcpy(temp_entry, "00 - "); - if (i < 9) { - mcl_gui.put_value_at(i + 1, temp_entry + 1); - } else { - mcl_gui.put_value_at(i + 1, temp_entry); - } - // put_value_at null-terminates the string. undo that. - temp_entry[2] = ' '; - if (slot_occupied) { - strcat(temp_entry, s_tmpbuf); - } else { - strcat(temp_entry, "[EMPTY]"); - } - add_entry(temp_entry); - } - - s_query_returned = true; -} MCLEncoder soundbrowser_param1(0, 1, ENCODER_RES_SYS); MCLEncoder soundbrowser_param2(0, 36, ENCODER_RES_SYS); diff --git a/avr/cores/megacommand/MCL/SoundBrowserPage.h b/avr/cores/megacommand/MCL/SoundBrowserPage.h index c611ce831..b33ff7c51 100644 --- a/avr/cores/megacommand/MCL/SoundBrowserPage.h +++ b/avr/cores/megacommand/MCL/SoundBrowserPage.h @@ -4,47 +4,29 @@ #define SOUNDBROWSERPAGE_H__ #include "FileBrowserPage.h" -#include "MidiSysex.h" - -#define FT_SND 0 -#define FT_WAV 1 -#define FT_SYX 2 #define PA_NEW 0 #define PA_SELECT 1 -class SoundBrowserPage : public FileBrowserPage, public MidiSysexListenerClass { +class SoundBrowserPage : public FileBrowserPage { public: SoundBrowserPage(Encoder *e1 = NULL, Encoder *e2 = NULL, Encoder *e3 = NULL, - Encoder *e4 = NULL) : FileBrowserPage(e1, e2, e3, e4), MidiSysexListenerClass(){ - ids[0] = 0; - ids[1] = 0x20; - ids[2] = 0x3c; + Encoder *e4 = NULL) : FileBrowserPage(e1, e2, e3, e4) { } - uint8_t pending_action = 0; - bool show_ram_slots = false; - virtual void on_new(); virtual void on_select(const char*); virtual void on_cancel(); - virtual void chdir_type(); - virtual bool handleEvent(gui_event_t *event); - void draw_scrollbar(uint8_t x_offset); - void init(); - void setup(); + void save_sound(); void load_sound(); - void send_sample(int slot, bool is_syx, char *newname = nullptr, bool silent = false); - void recv_wav(int slot, bool silent = false); - - // MidiSysexListenerClass - virtual void start(); - virtual void end(); - virtual bool _handle_filemenu(); - protected: - void query_sample_slots(); + + virtual bool handleEvent(gui_event_t *event); + + virtual void init(); + void setup(); + }; extern SoundBrowserPage sound_browser; diff --git a/avr/cores/megacommand/MCL/TextInputPage.cpp b/avr/cores/megacommand/MCL/TextInputPage.cpp index ab313e1a1..d75ecfc45 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.cpp +++ b/avr/cores/megacommand/MCL/TextInputPage.cpp @@ -7,7 +7,7 @@ inline char _getchar(uint8_t i) { if (i >= sz_allowedchar) i = sz_allowedchar - 1; return i - ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_&@-=! "]; + ["abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_&@-=!"]; } // chr -> idx @@ -26,7 +26,10 @@ uint8_t _findchar(char chr) { void TextInputPage::setup() {} -void TextInputPage::init() { oled_display.setTextColor(WHITE, BLACK); } +void TextInputPage::init() { + oled_display.setTextColor(WHITE, BLACK); + mcl_gui.draw_popup(title,false,24); +} void TextInputPage::init_text(char *text_, const char *title_, uint8_t len) { textp = text_; @@ -34,6 +37,11 @@ void TextInputPage::init_text(char *text_, const char *title_, uint8_t len) { length = len; max_length = len; strncpy(text, text_, len); + //Replace null characeters with space, it will be added back in upon exit. + for (uint8_t n = 0; n < len; n++) { + if (text[n] == '\0') { text[n] = ' '; } + } + text[sizeof(text) - 1] = '\0'; cursor_position = 0; config_normal(); } @@ -58,7 +66,6 @@ void TextInputPage::config_normal() { update_char(); #ifdef OLED_DISPLAY // redraw popup body - mcl_gui.draw_popup(title); #endif // update clock last_clock = slowclock; @@ -83,7 +90,20 @@ static void calc_charpane_coord(uint8_t &x, uint8_t &y) { } void TextInputPage::loop() { - if (normal_mode == false) { + if (normal_mode) { + if (encoders[0]->hasChanged()) { + update_char(); + last_clock = slowclock; + } + + if (encoders[1]->hasChanged()) { + last_clock = slowclock; + encoders[1]->old = encoders[1]->cur; + text[cursor_position] = _getchar(encoders[1]->getValue()); + } + + } + else { if (encoders[1]->cur == ((MCLEncoder *)encoders[1])->max) { ((MCLEncoder *)encoders[0])->max = charpane_w - 4; } @@ -97,7 +117,6 @@ void TextInputPage::loop() { // E0 -> x axis [0..17] // E1 -> y axis [0..3] void TextInputPage::config_charpane() { -#ifdef OLED_DISPLAY // char pane not supported on 1602 displays ((MCLEncoder *)encoders[0])->max = charpane_w - 1; @@ -111,26 +130,6 @@ void TextInputPage::config_charpane() { encoders[1]->cur = chridx / charpane_w; encoders[1]->old = encoders[1]->cur; - oled_display.setFont(&TomThumb); - oled_display.clearDisplay(); - oled_display.drawRect(0, 0, 128, 32, WHITE); - uint8_t chidx = 0; - for (uint8_t y = 0; y < charpane_h; ++y) { - for (uint8_t x = 0; x < charpane_w; ++x) { - auto sx = x, sy = y; - calc_charpane_coord(sx, sy); - oled_display.setCursor(sx + charpane_padx, sy + charpane_pady); - oled_display.print(_getchar(chidx)); - ++chidx; - } - } - - // initial highlight of selected char - uint8_t sx = encoders[0]->cur, sy = encoders[1]->cur; - calc_charpane_coord(sx, sy); - oled_display.fillRect(sx, sy, 5, 7, INVERT); - oled_display.display(); -#endif } void TextInputPage::display_normal() { @@ -142,16 +141,6 @@ void TextInputPage::display_normal() { // Check to see that the character chosen is in the list of allowed // characters - if (encoders[0]->hasChanged()) { - update_char(); - last_clock = slowclock; - } - - if (encoders[1]->hasChanged()) { - last_clock = slowclock; - encoders[1]->old = encoders[1]->cur; - text[cursor_position] = _getchar(encoders[1]->getValue()); - } auto time = clock_diff(last_clock, slowclock); // mcl_gui.clear_popup(); <-- E_TOOSLOW @@ -173,32 +162,33 @@ void TextInputPage::display_normal() { last_clock = slowclock; } oled_display.setFont(oldfont); - oled_display.display(); } void TextInputPage::display_charpane() { -#ifdef OLED_DISPLAY - if (encoders[0]->hasChanged() || encoders[1]->hasChanged()) { - // clear old highlight - uint8_t sx = encoders[0]->old, sy = encoders[1]->old; - calc_charpane_coord(sx, sy); - oled_display.fillRect(sx, sy, 5, 7, INVERT); + oled_display.setFont(&TomThumb); + oled_display.clearDisplay(); + oled_display.drawRect(0, 0, 128, 32, WHITE); + uint8_t chidx = 0; + for (uint8_t y = 0; y < charpane_h; ++y) { + for (uint8_t x = 0; x < charpane_w; ++x) { + auto sx = x, sy = y; + calc_charpane_coord(sx, sy); + oled_display.setCursor(sx + charpane_padx, sy + charpane_pady); + oled_display.print(_getchar(chidx)); + ++chidx; + } + } + // draw new highlight - sx = encoders[0]->cur; - sy = encoders[1]->cur; + uint8_t sx = encoders[0]->cur; + uint8_t sy = encoders[1]->cur; calc_charpane_coord(sx, sy); oled_display.fillRect(sx, sy, 5, 7, INVERT); // update text. in charpane mode, cursor_position remains constant uint8_t chridx = encoders[0]->cur + encoders[1]->cur * charpane_w; text[cursor_position] = _getchar(chridx); - // mark encoders as unchanged - encoders[0]->old = encoders[0]->cur; - encoders[1]->old = encoders[1]->cur; - } last_clock = slowclock; - oled_display.display(); -#endif } void TextInputPage::display() { @@ -206,6 +196,8 @@ void TextInputPage::display() { display_normal(); else display_charpane(); + + oled_display.display(); } bool TextInputPage::handleEvent(gui_event_t *event) { @@ -224,10 +216,10 @@ bool TextInputPage::handleEvent(gui_event_t *event) { // trig_interface.ignoreNextEvent(MDX_KEY_NO); goto NO; case MDX_KEY_UP: - encoders[1]->cur -= inc; + encoders[1]->cur += normal_mode ? inc : -1 * inc; break; case MDX_KEY_DOWN: - encoders[1]->cur += inc; + encoders[1]->cur += normal_mode ? -1 * inc : inc; break; case MDX_KEY_LEFT: encoders[0]->cur -= inc; @@ -263,6 +255,7 @@ bool TextInputPage::handleEvent(gui_event_t *event) { cursor_position = length - 1; } // then, config normal input line + init(); config_normal(); return true; } @@ -274,7 +267,7 @@ bool TextInputPage::handleEvent(gui_event_t *event) { DEBUG_PRINTLN("pop a"); return_state = false; GUI.ignoreNextEvent(event->source); - GUI.popPage(); + mcl.popPage(); return true; } @@ -314,7 +307,7 @@ bool TextInputPage::handleEvent(gui_event_t *event) { strncpy(textp, text, cpy_len); textp[cpy_len] = '\0'; GUI.ignoreNextEvent(event->source); - GUI.popPage(); + mcl.popPage(); return true; } diff --git a/avr/cores/megacommand/MCL/TextInputPage.h b/avr/cores/megacommand/MCL/TextInputPage.h index d8f787b09..b568a3539 100644 --- a/avr/cores/megacommand/MCL/TextInputPage.h +++ b/avr/cores/megacommand/MCL/TextInputPage.h @@ -22,6 +22,7 @@ class TextInputPage : public LightPage { Encoder *e4 = NULL) : LightPage(e1, e2, e3, e4) {} virtual bool handleEvent(gui_event_t *event); + void config_normal(); void config_charpane(); void display(); diff --git a/avr/cores/megacommand/MCL/TrackInfoEncoder.cpp b/avr/cores/megacommand/MCL/TrackInfoEncoder.cpp deleted file mode 100644 index c57a0bb1c..000000000 --- a/avr/cores/megacommand/MCL/TrackInfoEncoder.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "TrackInfoEncoder.h" - -int TrackInfoEncoder::update(encoder_t *enc) { - uint8_t amount = abs(enc->normal); - int inc = 0; - - while (amount > 0) { - if (enc->normal > 0) { - rot_counter_up += 1; - if (rot_counter_up > rot_res) { - rot_counter_up = 0; - inc += 1; - } - rot_counter_down = 0; - } - if (enc->normal < 0) { - rot_counter_down += 1; - if (rot_counter_down > rot_res) { - rot_counter_down = 0; - inc -= 1; - } - - rot_counter_up = 0; - } - amount--; - } - - inc = inc + enc->normal; - cur = limit_value(cur, inc, min, max); - - return cur; -} diff --git a/avr/cores/megacommand/MCL/TrackInfoEncoder.h b/avr/cores/megacommand/MCL/TrackInfoEncoder.h deleted file mode 100644 index c038ca449..000000000 --- a/avr/cores/megacommand/MCL/TrackInfoEncoder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2018, Justin Mammarella jmamma@gmail.com */ - -#ifndef TRACKINFOENCODER_H__ -#define TRACKINFOENCODER_H__ -#include "MCL.h" - -class TrackInfoEncoder : public Encoder { - /** - \addtogroup gui_rangeencoder_class - @{ - **/ - - public: - /** Minimum value of the encoder. **/ - int8_t min; - /** Maximum value of the encoder. **/ - int8_t max; - - /** - Create a new range-limited encoder with max and min value, short - name, initial value, and handling function. The initRangeEncoder - will be called with the constructor arguments. - **/ - TrackInfoEncoder(int _max = 127, int _min = 0, int res = 1) : Encoder() { - initTrackInfoEncoder(_max, _min, (int) 0, res, (encoder_handle_t) NULL); - } - - - /** - Initialize the encoder with the same argument as the constructor. - - The initRangeEncoder functions automatically determines which of - min and max is the minimum value. As of now this can't be used to - have an "inverted" encoder. - - The initial value is called without calling the handling function. - **/ - void initTrackInfoEncoder(int _max = 128, int _min = 0, int init = 0, int res = 1, encoder_handle_t _handler = NULL) { - rot_res = res; - // setName(_name); - handler = _handler; - if (_min > _max) { - min = _max; - max = _min; - } else { - min = _min; - max = _max; - } - setValue(init); - } - - /** - Update the value of the encoder according to pressmode and - fastmode, and limit the resulting value using limit_value(). - **/ - virtual int update(encoder_t *enc); - // virtual void displayAt(int i); - - /* @} */ -}; - -#endif /* TRACKINFOENCODER_H__ */ diff --git a/avr/cores/megacommand/MCL/TrigInterface.cpp b/avr/cores/megacommand/MCL/TrigInterface.cpp index b31563315..85c3a0887 100644 --- a/avr/cores/megacommand/MCL/TrigInterface.cpp +++ b/avr/cores/megacommand/MCL/TrigInterface.cpp @@ -19,9 +19,9 @@ void TrigInterfaceTask::run() { key = MDX_KEY_DOWN; } - if (key == 255) { - GUI.removeTask(&trig_interface_task); - return; + if (key == 255) { + GUI.removeTask(&trig_interface_task); + return; } gui_event_t event; @@ -29,7 +29,7 @@ void TrigInterfaceTask::run() { event.mask = EVENT_BUTTON_PRESSED; event.port = UART1_PORT; EventRB.putp(&event); - + } */ @@ -54,7 +54,9 @@ void TrigInterface::disable_listener() { sysex->removeSysexListener(this); } bool TrigInterface::on(bool clear_states) { note_interface.init_notes(); - if (clear_states) { cmd_key_state = 0; } + if (clear_states) { + cmd_key_state = 0; + } note_interface.note_proceed = true; if (state) { return false; @@ -82,6 +84,15 @@ bool TrigInterface::off() { return true; } +bool TrigInterface::check_key_throttle() { + if (clock_diff(last_clock, slowclock) < 30) { + return true; + } else { + throttle = false; + } + return false; +} + void TrigInterface::end() { // if (!state) { @@ -101,6 +112,19 @@ void TrigInterface::end() { key_release = true; key -= 0x40; } + + if (key == MDX_KEY_YES) { + if (!key_release && throttle) { + if (check_key_throttle()) { + return; + } + } + if (!throttle) { + throttle = true; + last_clock = slowclock; + } + } + if (key_release) { CLEAR_BIT64(cmd_key_state, key); } else { @@ -124,8 +148,7 @@ void TrigInterface::end() { if (key == MDX_KEY_PATSONG) { event.source = Buttons.BUTTON3; - } - else { + } else { event.source = key + 64; // EVENT_CMD } event.mask = key_release ? EVENT_BUTTON_RELEASED : EVENT_BUTTON_PRESSED; diff --git a/avr/cores/megacommand/MCL/TrigInterface.h b/avr/cores/megacommand/MCL/TrigInterface.h index ff350b276..97e15ce46 100644 --- a/avr/cores/megacommand/MCL/TrigInterface.h +++ b/avr/cores/megacommand/MCL/TrigInterface.h @@ -15,6 +15,7 @@ #define MDX_KEY_REC 0x20 #define MDX_KEY_GLOBAL 0x21 #define MDX_KEY_PATSONGKIT 0x22 +#define MDX_KEY_KIT 0x23 #define MDX_KEY_FUNC 0x25 #define MDX_KEY_LEFT 0x26 #define MDX_KEY_RIGHT 0x27 @@ -23,6 +24,7 @@ #define MDX_KEY_SCALE 0x2A #define MDX_KEY_MUTE 0x2B #define MDX_KEY_SONG 0x2C +#define MDX_KEY_EXTENDED 0x2D #define MDX_KEY_UP 0x30 #define MDX_KEY_DOWN 0x31 #define MDX_KEY_STOP 0x32 @@ -65,6 +67,8 @@ class TrigInterface : public MidiSysexListenerClass { bool state = false; uint64_t cmd_key_state; uint64_t ignore_next_mask; + uint16_t last_clock; + bool throttle; TrigInterface() : MidiSysexListenerClass() { ids[0] = 0x7F; @@ -79,9 +83,9 @@ class TrigInterface : public MidiSysexListenerClass { bool on(bool clear_states = true); bool off(); + bool check_key_throttle(); void enable_listener(); void disable_listener(); - virtual void start(); virtual void end(); bool is_key_down(uint8_t key) { return IS_BIT_SET64(cmd_key_state, key); } diff --git a/avr/cores/megacommand/MCL/Wav.cpp b/avr/cores/megacommand/MCL/Wav.cpp index 8ce2da2ee..9dcc9f228 100644 --- a/avr/cores/megacommand/MCL/Wav.cpp +++ b/avr/cores/megacommand/MCL/Wav.cpp @@ -508,7 +508,7 @@ bool Wav::apply_gain(float gain, uint8_t channel, uint32_t num_samples, } else { - uint32_t num_of_samples = + num_of_samples = (header.data.chunk_size / header.fmt.numChannels) / sample_size; } diff --git a/avr/cores/megacommand/MCL/Wav.h b/avr/cores/megacommand/MCL/Wav.h index dab10ca23..0a51c90e0 100644 --- a/avr/cores/megacommand/MCL/Wav.h +++ b/avr/cores/megacommand/MCL/Wav.h @@ -158,6 +158,10 @@ struct WavHeader { datachunk_t data; smplchunk_t smpl; + uint32_t get_length() { + return (data.chunk_size / fmt.numChannels) / (fmt.bitRate / 8); + } + uint32_t total_len() const { uint32_t sz = 12; sz += fmt.total_len(); @@ -222,6 +226,7 @@ class Wav { char filename[16]; File file; Wav() {} + bool open(const char *file_name, bool write = false, uint16_t numChannels = 1, uint32_t sampleRate = 44100, uint8_t bitRate = 16, bool loop = false); diff --git a/avr/cores/megacommand/MCL/WavDesigner.cpp b/avr/cores/megacommand/MCL/WavDesigner.cpp index 9f3dbb6c8..03ee2769c 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.cpp +++ b/avr/cores/megacommand/MCL/WavDesigner.cpp @@ -8,23 +8,21 @@ void WavDesigner::prompt_send() { oled_display.textbox("Render", ""); oled_display.display(); //Order of statements important for directory switching. - GUI.pushPage(&sound_browser); - sound_browser.show_samplemgr = true; - sound_browser.pending_action = PA_SELECT; - sound_browser.filetype_idx = FT_WAV; - sound_browser.setup(); - sound_browser.show_samplemgr = true; + mcl.pushPage(SAMPLE_BROWSER); + sample_browser.show_samplemgr = true; + sample_browser.pending_action = PA_SELECT; + sample_browser.setup(); wd.render(); - sound_browser.init(); - if (sound_browser.file.open(WAV_NAME, O_READ)) { - while (GUI.currentPage() == &sound_browser && - sound_browser.pending_action == PA_SELECT && sound_browser.show_samplemgr) { + sample_browser.init(true); + if (sample_browser.file.open(WAV_NAME, O_READ)) { + while (mcl.currentPage() == SAMPLE_BROWSER && + sample_browser.pending_action == PA_SELECT && sample_browser.show_samplemgr) { GUI.loop(); } } DEBUG_PRINTLN("cleaning up"); - sound_browser.file.close(); - GUI.setPage(&wd.mixer); + sample_browser.file.close(); + mcl.setPage(WD_MIXER_PAGE); // oled_display.textbox("Sending..",""); // // oled_display.display(); diff --git a/avr/cores/megacommand/MCL/WavDesigner.h b/avr/cores/megacommand/MCL/WavDesigner.h index 71e13d44d..51dae15ed 100644 --- a/avr/cores/megacommand/MCL/WavDesigner.h +++ b/avr/cores/megacommand/MCL/WavDesigner.h @@ -3,7 +3,7 @@ #ifndef WAVDESIGNER_H__ #define WAVDESIGNER_H__ -#include "MCL.h" +#include "mcl.h" #include "math.h" #include "OscPage.h" #include "OscMixerPage.h" @@ -16,7 +16,7 @@ class WavDesigner { OscMixerPage mixer; uint32_t loop_start; uint32_t loop_end; - LightPage *last_page; + PageIndex last_page; WavDesigner() { for (uint8_t i = 0; i < 3; i++) { pages[i].id = i; @@ -24,7 +24,7 @@ class WavDesigner { mixer.id = MIXER_ID; pages[0].osc_waveform = 1; mixer.enc4.cur = 0; - last_page = &(pages[0]); + last_page = WD_PAGE_0; } void prompt_send(); bool render(); diff --git a/avr/cores/megacommand/MCL/WavDesignerPage.cpp b/avr/cores/megacommand/MCL/WavDesignerPage.cpp index 5ed066e28..0479369c0 100644 --- a/avr/cores/megacommand/MCL/WavDesignerPage.cpp +++ b/avr/cores/megacommand/MCL/WavDesignerPage.cpp @@ -19,9 +19,9 @@ void wavdesign_menu_handler() { } WavDesignerPage::last_mode = WavDesignerPage::opt_mode; if (WavDesignerPage::opt_mode == 3) { - GUI.setPage(&wd.mixer); + mcl.setPage(WD_MIXER_PAGE); } else { - GUI.setPage(&wd.pages[WavDesignerPage::opt_mode]); + mcl.setPage(WD_PAGE_0 + WavDesignerPage::opt_mode); } } @@ -49,16 +49,10 @@ bool WavDesignerPage::handleEvent(gui_event_t *event) { uint8_t inc = 1; // if (show_menu) { switch (key) { - case MDX_KEY_YES: - // trig_interface.ignoreNextEvent(MDX_KEY_YES); - return true; - case MDX_KEY_NO: - // trig_interface.ignoreNextEvent(MDX_KEY_NO); - return true; - case MDX_KEY_UP: + case MDX_KEY_DOWN: encoders[1]->cur -= inc; break; - case MDX_KEY_DOWN: + case MDX_KEY_UP: encoders[1]->cur += inc; break; case MDX_KEY_LEFT: @@ -103,7 +97,7 @@ bool WavDesignerPage::handleEvent(gui_event_t *event) { return true; } if (EVENT_PRESSED(event, Buttons.BUTTON2)) { - GUI.setPage(&page_select_page); + mcl.setPage(PAGE_SELECT_PAGE); return true; } return false; diff --git a/avr/cores/megacommand/MCL/WavDesignerPage.h b/avr/cores/megacommand/MCL/WavDesignerPage.h index bce37bd1f..70187e449 100644 --- a/avr/cores/megacommand/MCL/WavDesignerPage.h +++ b/avr/cores/megacommand/MCL/WavDesignerPage.h @@ -3,7 +3,7 @@ #ifndef WAVDESIGNERPAGE_H__ #define WAVDESIGNERPAGE_H__ -#include "MCL.h" +#include "mcl.h" extern void wavdesign_menu_handler(); extern void wav_render(); diff --git a/avr/cores/megacommand/MD/MD.cpp b/avr/cores/megacommand/MD/MD.cpp index 8d2f9ab01..e78159017 100644 --- a/avr/cores/megacommand/MD/MD.cpp +++ b/avr/cores/megacommand/MD/MD.cpp @@ -143,21 +143,31 @@ void MDClass::setExternalSync() { sendRequest(data, sizeof(data)); } -void MDClass::init_grid_devices() { +void MDClass::init_grid_devices(uint8_t device_idx) { uint8_t grid_idx = 0; + GridDeviceTrack gdt; for (uint8_t i = 0; i < NUM_MD_TRACKS; i++) { - add_track_to_grid(grid_idx, i, &(mcl_seq.md_tracks[i]), MD_TRACK_TYPE); + gdt.init(MD_TRACK_TYPE, GROUP_DEV, device_idx, &(mcl_seq.md_tracks[i])); + add_track_to_grid(grid_idx, i, &gdt); } grid_idx = 1; - add_track_to_grid(grid_idx, MDFX_TRACK_NUM, &(mcl_seq.aux_tracks[0]), - MDFX_TRACK_TYPE, GROUP_AUX, 0); - add_track_to_grid(grid_idx, MDROUTE_TRACK_NUM, &(mcl_seq.aux_tracks[1]), - MDROUTE_TRACK_TYPE, GROUP_AUX, 0); - add_track_to_grid(grid_idx, MDLFO_TRACK_NUM, &(mcl_seq.aux_tracks[2]), - MDLFO_TRACK_TYPE, GROUP_AUX, 0); - add_track_to_grid(grid_idx, MDTEMPO_TRACK_NUM, &(mcl_seq.aux_tracks[3]), - MDTEMPO_TRACK_TYPE, GROUP_TEMPO, 0); + + gdt.init(MDFX_TRACK_TYPE, GROUP_DEV, device_idx, (SeqTrack*) &(mcl_seq.mdfx_track), 0); + add_track_to_grid(grid_idx, MDFX_TRACK_NUM, &gdt); + + gdt.init(MDLFO_TRACK_TYPE, GROUP_PERF, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[0]), 0); + add_track_to_grid(grid_idx, MDLFO_TRACK_NUM, &gdt); + + gdt.init(MDROUTE_TRACK_TYPE, GROUP_AUX, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[1]), 0); + add_track_to_grid(grid_idx, MDROUTE_TRACK_NUM, &gdt); + + gdt.init(MDTEMPO_TRACK_TYPE, GROUP_TEMPO, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[2]), 0); + add_track_to_grid(grid_idx, MDTEMPO_TRACK_NUM, &gdt); + + gdt.init(PERF_TRACK_TYPE, GROUP_PERF, device_idx, (SeqTrack*) &(mcl_seq.aux_tracks[3]), 0); + add_track_to_grid(grid_idx, PERF_TRACK_NUM, &gdt); + } void MDClass::get_mutes() { @@ -192,7 +202,8 @@ bool MDClass::probe() { uint16_t fw_caps_mask = ((uint16_t)FW_CAP_MASTER_FX | (uint16_t)FW_CAP_TRIG_LEDS | (uint16_t)FW_CAP_UNDOKIT_SYNC | (uint16_t)FW_CAP_TONAL | - (uint16_t)FW_CAP_ENHANCED_GUI | (uint16_t)FW_CAP_ENHANCED_MIDI) | (uint16_t)FW_CAP_MACHINE_CACHE; + (uint16_t)FW_CAP_ENHANCED_GUI | (uint16_t)FW_CAP_ENHANCED_MIDI) | + (uint16_t)FW_CAP_MACHINE_CACHE | (uint16_t)FW_CAP_UNDO_CACHE; while ((!get_fw_caps() || ((fw_caps & fw_caps_mask) != fw_caps_mask)) && count) { @@ -233,6 +244,7 @@ bool MDClass::probe() { md_track_select.on(); activate_enhanced_gui(); activate_enhanced_midi(); + MD.set_key_repeat(1); MD.set_trigleds(0, TRIGLED_EXCLUSIVE); MD.global.extendedMode = 2; seq_ptc_page.setup(); @@ -250,6 +262,8 @@ bool MDClass::probe() { // Caller is responsible to make sure icons_device is loaded in RM uint8_t *MDClass::icon() { return R.icons_device->icon_md; } +MCLGIF *MDClass::gif() { return R.icons_logo->machinedrum_gif; } +uint8_t *MDClass::gif_data() { return R.icons_logo->machinedrum_gif_data; } uint8_t MDClass::noteToTrack(uint8_t pitch) { uint8_t i; @@ -348,20 +362,11 @@ void MDClass::parallelTrig(uint16_t mask, MidiUartParent *uart_) { void MDClass::restore_kit_params() { memcpy(kit.params, kit.params_orig, sizeof(kit.params)); - for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { - mcl_seq.md_tracks[n].update_params(); - } - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].update_params_offset(); - } } void MDClass::restore_kit_param(uint8_t track, uint8_t param) { if (MD.kit.params[track][param] != MD.kit.params_orig[track][param]) { MD.setTrackParam(track, param, MD.kit.params_orig[track][param], nullptr, true); - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].check_and_update_params_offset(track + 1, param, MD.kit.params_orig[track][param]); - } } } @@ -395,7 +400,12 @@ void MDClass::setTrackParam_inline(uint8_t track, uint8_t param, uint8_t value, } else { return; } + if (update_kit) { uart_->sendCC(channel + global.baseChannel, cc, value); + } + else { + uart_->sendPolyKeyPressure(channel + global.baseChannel, cc, value); + } } void MDClass::setSampleName(uint8_t slot, char *name) { @@ -409,6 +419,12 @@ void MDClass::setSampleName(uint8_t slot, char *name) { sendRequest(data, 6); } +uint8_t MDClass::assignFXParamsBulk(uint8_t *values, bool send) { + uint8_t data[2 + 8 * 4] = {0x70, 0x5a}; + memcpy(&data[2], values, 8 * 4); + return sendRequest(data, sizeof(data), send); +} + uint8_t MDClass::sendFXParamsBulk(uint8_t *values, bool send) { uint8_t data[2 + 8 * 4] = {0x70, 0x61}; memcpy(&data[2], values, 8 * 4); @@ -689,23 +705,21 @@ uint8_t MDClass::assignMachineBulk(uint8_t track, MDMachine *machine, } data[i++] = machine->trigGroup; data[i++] = machine->muteGroup; - bool set_level = false; if (level != 255) { data[i++] = level; - set_level = true; } end: return sendRequest(data, i, send); } -void MDClass::loadMachinesCache(uint16_t track_mask) { +void MDClass::loadMachinesCache(uint32_t track_mask, MidiUartParent *uart_) { DEBUG_PRINTLN("load machine cache"); uint8_t a = track_mask & 0x7F; uint8_t b = (track_mask >> 7) & 0x7F; uint8_t c = (track_mask >> 14) & 0x7F; uint8_t data[5] = { 0x70, 0x62, a, b, c }; - sendRequest(data, countof(data)); + sendRequest(data, countof(data), uart_); } void MDClass::setOrigParams(uint8_t track, MDMachine *machine) { @@ -772,14 +786,16 @@ uint8_t MDClass::sendMachine(uint8_t track, MDMachine *machine, bool send_level, return bytes; } -void MDClass::muteTrack(uint8_t track, bool mute) { +void MDClass::muteTrack(uint8_t track, bool mute, MidiUartParent *uart_) { if (global.baseChannel == 127) return; - + if (uart_ == nullptr) { + uart_ = uart; + } uint8_t channel = track >> 2; uint8_t b = track & 3; uint8_t cc = 12 + b; - uart->sendCC(channel + global.baseChannel, cc, mute ? 1 : 0); + uart_->sendCC(channel + global.baseChannel, cc, (uint8_t) mute); } void MDClass::setGlobal(uint8_t id) { @@ -1145,9 +1161,6 @@ void MDClass::updateKitParams() { for (uint8_t n = 0; n < NUM_MD_TRACKS; n++) { old_mutes[n] = mcl_seq.md_tracks[n].mute_state; mcl_seq.md_tracks[n].mute_state = SEQ_MUTE_ON; - mcl_seq.md_tracks[n].update_kit_params(); - //Perform silent reset, to prevent MDkit copying running parameter locks in to undo kit - mcl_seq.md_tracks[n].reset_params(); } undokit_sync(); diff --git a/avr/cores/megacommand/MD/MD.h b/avr/cores/megacommand/MD/MD.h index d32be5ed4..15ca21bc2 100644 --- a/avr/cores/megacommand/MD/MD.h +++ b/avr/cores/megacommand/MD/MD.h @@ -61,9 +61,10 @@ class MDClass : public ElektronDevice { virtual bool probe(); virtual void setup(); - virtual void init_grid_devices(); + virtual void init_grid_devices(uint8_t device_idx); virtual uint8_t* icon(); - + virtual MCLGIF *gif(); + virtual uint8_t* gif_data(); // TODO not necessary if we have FW_CAP_READ_LIVE_KIT virtual bool canReadWorkspaceKit() { return true; } virtual bool canReadKit() { return true; } @@ -139,6 +140,7 @@ class MDClass : public ElektronDevice { **/ // Send multiple values simultaneously (single sysex message); + uint8_t assignFXParamsBulk(uint8_t *values, bool send = true); uint8_t sendFXParamsBulk(uint8_t *values, bool send = true); uint8_t sendFXParams(uint8_t *values, uint8_t type, bool send = true); @@ -264,7 +266,7 @@ class MDClass : public ElektronDevice { return sendMachine(track + 16, machine, send_level, send); } - void loadMachinesCache(uint16_t track_mask); + void loadMachinesCache(uint32_t track_mask, MidiUartParent *uart_ = nullptr); /** * Inserts a machine in to the MDKit object @@ -276,7 +278,7 @@ class MDClass : public ElektronDevice { * Mute/unmute the given track (0 to 15) by sending a CC * message. This uses the global channel settings. **/ - void muteTrack(uint8_t track, bool mute = true); + void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr); /** Unmute the given track. **/ void unmuteTrack(uint8_t track) { muteTrack(track, false); } diff --git a/avr/cores/megacommand/MD/MDSysex.cpp b/avr/cores/megacommand/MD/MDSysex.cpp index a03e3f6db..1ffd471ca 100644 --- a/avr/cores/megacommand/MD/MDSysex.cpp +++ b/avr/cores/megacommand/MD/MDSysex.cpp @@ -61,7 +61,7 @@ void MDSysexListenerClass::end() { value = sysex->getByte(offset++); fx_type = msgType - MD_SET_RHYTHM_ECHO_PARAM_ID; - if (param > 8) { return; } + if (param > 7) { return; } switch (msgType) { case MD_SET_RHYTHM_ECHO_PARAM_ID: @@ -78,9 +78,10 @@ void MDSysexListenerClass::end() { break; } - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].check_and_update_params_offset(17 + fx_type, param, value); - } + perf_page.learn_param(fx_type + 16, param, value); + lfo_page.learn_param(fx_type + 16, param, value); + if (GUI.currentPage() == &fx_page_a) { fx_page_a.update_encoders(); } + if (GUI.currentPage() == &fx_page_b) { fx_page_b.update_encoders(); } break; @@ -98,11 +99,7 @@ void MDSysexListenerClass::end() { //LFOS, LFOD, LFOM if (4 < param && param < 8) { - mcl_seq.md_tracks[track].update_param(param + 16, value); MD.kit.params[track][param + 16] = value; - for (uint8_t n = 0; n < mcl_seq.num_lfo_tracks; n++) { - mcl_seq.lfo_tracks[n].check_and_update_params_offset(track + 1, param + 16, value); - } } break; diff --git a/avr/cores/megacommand/MNM/MNM.cpp b/avr/cores/megacommand/MNM/MNM.cpp index 2e982b6dd..cf5bb7f77 100644 --- a/avr/cores/megacommand/MNM/MNM.cpp +++ b/avr/cores/megacommand/MNM/MNM.cpp @@ -31,13 +31,16 @@ const ElektronSysexProtocol mnm_protocol = { MNMClass::MNMClass() : ElektronDevice(&Midi2, "MM", DEVICE_MNM, mnm_protocol) { global.baseChannel = 0; - midiuart = &MidiUart2; + uart = &MidiUart2; } -void MNMClass::init_grid_devices() { +void MNMClass::init_grid_devices(uint8_t device_idx) { uint8_t grid_idx = 1; + GridDeviceTrack gdt; + for (uint8_t i = 0; i < NUM_EXT_TRACKS; i++) { - add_track_to_grid(grid_idx, i, &(mcl_seq.ext_tracks[i]), MNM_TRACK_TYPE); + gdt.init(MNM_TRACK_TYPE, GROUP_DEV, device_idx, &(mcl_seq.ext_tracks[i])); + add_track_to_grid(grid_idx, i, &gdt); } } @@ -108,6 +111,8 @@ uint8_t* MNMClass::icon() { return R.icons_device->icon_mnm; } +uint8_t *MNMClass::gif_data() { return R.icons_logo->monomachine_gif_data; ; } +MCLGIF *MNMClass::gif() { return R.icons_logo->monomachine_gif;; } void MNMClass::requestKit(uint8_t kit) { uint8_t workspace = 0; @@ -124,48 +129,49 @@ void MNMClass::requestKit(uint8_t kit) { void MNMClass::triggerTrack(uint8_t track, bool amp, bool lfo, bool filter) { - midiuart->sendNRPN(global.baseChannel, (uint16_t)(0x7F << 7), + uart->sendNRPN(global.baseChannel, (uint16_t)(0x7F << 7), (uint8_t)((track << 3) | (amp ? 4 : 0) | (lfo ? 2 : 0) | (filter ? 1 : 0))); } void MNMClass::setMultiEnvParam(uint8_t param, uint8_t value) { - midiuart->sendNRPN(global.baseChannel, 0x40 + param, value); + uart->sendNRPN(global.baseChannel, 0x40 + param, value); } -void MNMClass::setMute(uint8_t track, bool mute) { - midiuart->sendCC(track + global.baseChannel, 3, mute ? 0 : 1); +void MNMClass::muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr) { + if (uart_ == nullptr) { uart_ = uart; } + uart->sendCC(track + global.baseChannel, 3, mute ? 0 : 1); } void MNMClass::setAutoMute(bool mute) { - midiuart->sendCC(global.autotrackChannel, 3, mute ? 0 : 1); + uart->sendCC(global.autotrackChannel, 3, mute ? 0 : 1); } void MNMClass::setMidiParam(uint8_t track, uint8_t param, uint8_t value) { - midiuart->sendNRPN(global.baseChannel, (track << 7) | (0x38 + param), value); + uart->sendNRPN(global.baseChannel, (track << 7) | (0x38 + param), value); } void MNMClass::setTrackPitch(uint8_t track, uint8_t pitch) { - midiuart->sendNRPN(global.baseChannel, (112 + track) << 7, pitch); + uart->sendNRPN(global.baseChannel, (112 + track) << 7, pitch); } uint8_t MNMClass::setTrackLevel(uint8_t track, uint8_t level, bool send) { if (send) { - midiuart->sendCC(global.baseChannel + track, 7, level); + uart->sendCC(global.baseChannel + track, 7, level); } return 3; } void MNMClass::setAutoParam(uint8_t param, uint8_t value) { if (param < 0x30) { - midiuart->sendCC(global.autotrackChannel, param + 0x30, value); + uart->sendCC(global.autotrackChannel, param + 0x30, value); } else { - midiuart->sendCC(global.autotrackChannel, param + 0x38, value); + uart->sendCC(global.autotrackChannel, param + 0x38, value); } } void MNMClass::setAutoLevel(uint8_t level) { - midiuart->sendCC(global.autotrackChannel, 7, level); + uart->sendCC(global.autotrackChannel, 7, level); } uint8_t MNMClass::setParam(uint8_t track, uint8_t param, uint8_t value, bool send) { @@ -182,7 +188,7 @@ uint8_t MNMClass::setParam(uint8_t track, uint8_t param, uint8_t value, bool sen cc = param + 0x40; } if (send) { - midiuart->sendCC(global.baseChannel + track, cc, value); + uart->sendCC(global.baseChannel + track, cc, value); } return 3; } diff --git a/avr/cores/megacommand/MNM/MNM.h b/avr/cores/megacommand/MNM/MNM.h index f5e9616cc..6139cb967 100644 --- a/avr/cores/megacommand/MNM/MNM.h +++ b/avr/cores/megacommand/MNM/MNM.h @@ -12,15 +12,16 @@ class MNMClass : public ElektronDevice { public: MNMClass(); - MidiUartClass *midiuart; MNMGlobal global; MNMKit kit; // MNMPattern pattern; virtual bool probe(); - virtual void init_grid_devices(); + virtual void init_grid_devices(uint8_t device_idx); virtual uint8_t* icon(); + virtual MCLGIF* gif(); + virtual uint8_t* gif_data(); virtual bool canReadWorkspaceKit() { return true; } virtual bool getWorkSpaceKit() { @@ -110,12 +111,13 @@ class MNMClass : public ElektronDevice { uint8_t setMachine(uint8_t idx) { return setMachine(currentTrack, idx); } uint8_t setMachine(uint8_t track, uint8_t idx, bool send = true); - void setMute(bool mute) { setMute(currentTrack, mute); } - void setMute(uint8_t track, bool mute); + void muteTrack(uint8_t track, bool mute = true, MidiUartParent *uart_ = nullptr); + /* void muteTrack() { muteTrack(currentTrack); } void muteTrack(uint8_t track) { setMute(track, true); } void unmuteTrack() { unmuteTrack(currentTrack); } void unmuteTrack(uint8_t track) { setMute(track, false); } + */ void setAutoMute(bool mute); void muteAutoTrack() { setAutoMute(true); } void unmuteAutoTrack() { setAutoMute(false); } diff --git a/avr/cores/megacommand/MNM/MNMMessages.h b/avr/cores/megacommand/MNM/MNMMessages.h index 73eac1f3e..37a4a50dd 100644 --- a/avr/cores/megacommand/MNM/MNMMessages.h +++ b/avr/cores/megacommand/MNM/MNMMessages.h @@ -96,7 +96,7 @@ class MNMTrackModifier { bool LPKeyTrack; bool HPKeyTrack; void init() { - memset(this, 0, sizeof(this)); + memset(this, 0, sizeof(MNMTrackModifier)); } }; diff --git a/avr/cores/megacommand/Makefile b/avr/cores/megacommand/Makefile index 09e12a7b9..344b2e380 100644 --- a/avr/cores/megacommand/Makefile +++ b/avr/cores/megacommand/Makefile @@ -34,10 +34,10 @@ F_CPU = 16000000L INOFILES=$(wildcard *.pde) -OPTIM_FLAGS = -Os -WARN_FLAGS = -Wall -Wextra +OPTIM_FLAGS = -Os --short-enums +WARN_FLAGS = -Wall -Wextra -Wdouble-promotion COMPILE_FLAGS = -c $(OPTIM_FLAGS) $(WARN_FLAGS) -MMD -FEATURE_FLAGS = -ffunction-sections -fdata-sections -flto=jobserver +FEATURE_FLAGS = -ffunction-sections -fdata-sections -flto=jobserver -fshort-enums LINK_FLAGS = -lm -Wl,--gc-sections,--defsym=__stack=0x801FA1,--section-start,.sdcard=0x801FA2,--section-start,.data=0x802200,--defsym=__heap_end=0x80ffff,--relax ARCH_FLAGS = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR diff --git a/avr/cores/megacommand/Midi/MidiClock.h b/avr/cores/megacommand/Midi/MidiClock.h index 22c85f744..c03a2deac 100644 --- a/avr/cores/megacommand/Midi/MidiClock.h +++ b/avr/cores/megacommand/Midi/MidiClock.h @@ -9,7 +9,6 @@ #include "WProgram.h" #include "midi-common.h" #include - /** * \addtogroup Midi * @@ -126,10 +125,12 @@ class MidiClockClass { CallbackVector1 onMidiStopCallbacks; CallbackVector1 onMidiContinueCallbacks; + /* CallbackVector1 on192Callbacks; CallbackVector1 on96Callbacks; CallbackVector1 on32Callbacks; CallbackVector1 on16Callbacks; + */ void addOnMidiStartImmediateCallback(ClockCallback *obj, midi_clock_callback_ptr_t func) { @@ -176,6 +177,7 @@ class MidiClockClass { void removeOnMidiContinueCallback(ClockCallback *obj) { onMidiContinueCallbacks.remove(obj); } +/* void addOn192Callback(ClockCallback *obj, midi_clock_callback_ptr_t func) { on192Callbacks.add(obj, func); } @@ -207,11 +209,12 @@ class MidiClockClass { on16Callbacks.remove(obj, func); } void removeOn16Callback(ClockCallback *obj) { on16Callbacks.remove(obj); } - +*/ ALWAYS_INLINE() void init(); volatile bool inCallback = false; + /* ALWAYS_INLINE() void callCallbacks(bool isMidiEvent = false) { if (state != STARTED) return; @@ -229,7 +232,6 @@ class MidiClockClass { MidiUartParent::handle_midi_lock = 1; sei(); - on192Callbacks.call(div192th_counter); if (isMidiEvent) { @@ -243,11 +245,10 @@ class MidiClockClass { on32Callbacks.call(div32th_counter); } } - inCallback = false; SREG = _irqlock_tmp; MidiUartParent::handle_midi_lock = _midi_lock_tmp; - } + }*/ ALWAYS_INLINE() void handleImmediateClock() { // if (clock > clock_last_time) { diff --git a/avr/cores/megacommand/Midi/MidiSDS.cpp b/avr/cores/megacommand/Midi/MidiSDS.cpp index fcd9110c0..57ece1b4a 100644 --- a/avr/cores/megacommand/Midi/MidiSDS.cpp +++ b/avr/cores/megacommand/Midi/MidiSDS.cpp @@ -114,13 +114,13 @@ bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) { uint32_t fsize; int show_progress = 0; uint8_t n_retry = 0; - + uint16_t latency_ms = 0; if (state != SDS_READY || !file.open(filename, O_READ)) { return false; } - file.seekEnd(); - fsize = file.position(); + MidiSDSSysexListener.setup(&Midi); + fsize = file.size(); file.seek(0); // 1st packet: sysex request. @@ -131,8 +131,8 @@ bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) { } buf[4] = sample_number & 0x7F; buf[5] = (sample_number >> 7) & 0x7F; - MidiUart.sendRaw(buf, szbuf); state = SDS_SEND; + MidiUart.sendRaw(buf, szbuf); reply = waitForHandshake(); if (reply == MIDI_SDS_CANCEL) { ret = false; @@ -141,7 +141,7 @@ bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) { oled_display.clearDisplay(); - uint16_t latency_ms = (float) (1000 * sizeof(buf) / ( (float) MidiUart.speed * 0.1f)) + 20; + latency_ms = (float) (1000 * sizeof(buf) / ( (float) MidiUart.speed * 0.1f)) + 20; DEBUG_PRINTLN("latency"); DEBUG_PRINTLN(latency_ms); @@ -194,10 +194,10 @@ bool MidiSDSClass::sendSyx(const char *filename, uint16_t sample_number) { } // otherwise, don't expect ACK reply (maybe MD-specific name-setting command) } // later packets - cleanup: file.close(); state = SDS_READY; + MidiSDSSysexListener.cleanup(&Midi); return ret; } @@ -215,8 +215,7 @@ bool MidiSDSClass::sendWav(const char *filename, const char *samplename, uint16_ samplesSoFar = 0; sampleNumber = sample_number; setSampleRate(wav_file.header.fmt.sampleRate); - sampleLength = (wav_file.header.data.chunk_size / wav_file.header.fmt.numChannels) / - (wav_file.header.fmt.bitRate / 8); + sampleLength = wav_file.header.get_length(); sampleFormat = wav_file.header.fmt.bitRate; if (wav_file.header.smpl.is_active()) { diff --git a/avr/cores/megacommand/Midi/MidiSysex.h b/avr/cores/megacommand/Midi/MidiSysex.h index 0fd281a76..7bce09c0c 100644 --- a/avr/cores/megacommand/Midi/MidiSysex.h +++ b/avr/cores/megacommand/Midi/MidiSysex.h @@ -62,7 +62,7 @@ class MidiSysexLedger { public: uint8_t state : 2; uint16_t recordLen : 14; // 16383 max record length - uint8_t *ptr; + volatile unsigned char *ptr; }; #define SYSEX_STATE_NULL 0 @@ -128,7 +128,6 @@ class MidiSysexClass { } void get_next_msg() { - uint8_t n = msg_rd; msg_rd++; if (msg_rd == NUM_SYSEX_MSGS) { msg_rd = 0; @@ -176,7 +175,7 @@ class MidiSysexClass { return get_bank1(src); } - ALWAYS_INLINE() bool recordByte(uint8_t c) { + ALWAYS_INLINE() void recordByte(uint8_t c) { putByte(c); ledger[msg_wr].recordLen++; } diff --git a/avr/cores/megacommand/Midi/MidiUartParent.h b/avr/cores/megacommand/Midi/MidiUartParent.h index 988b8d769..d6848e821 100644 --- a/avr/cores/megacommand/Midi/MidiUartParent.h +++ b/avr/cores/megacommand/Midi/MidiUartParent.h @@ -79,10 +79,11 @@ class MidiUartParent { } virtual void initSerial() { } - virtual uint8_t m_getc() {} - virtual void m_putc(uint8_t *src, uint16_t size) { } - virtual void m_putc(uint8_t c) {} + virtual uint8_t m_getc() = 0; + virtual void m_putc(uint8_t *src, uint16_t size) = 0; + virtual void m_putc(uint8_t c) = 0; virtual void m_putc_immediate(uint8_t c) { m_putc(c); } + virtual void m_recv(uint8_t *src, uint16_t size) = 0; virtual bool avail() { return false; } virtual uint8_t getc() { return 0; } @@ -170,9 +171,9 @@ class MidiUartParent { } ALWAYS_INLINE() - void sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) { + void sendNoteOff(uint8_t channel, uint8_t note) { #ifdef MIDI_VALIDATE - if ((channel >= 16) || (note >= 128) || (velocity >= 128)) + if ((channel >= 16) || (note >= 128)) return; #endif diff --git a/avr/cores/megacommand/MidiUart.cpp b/avr/cores/megacommand/MidiUart.cpp index e71527bb7..bb11aa07c 100644 --- a/avr/cores/megacommand/MidiUart.cpp +++ b/avr/cores/megacommand/MidiUart.cpp @@ -1,4 +1,4 @@ -#define IS_ISR_ROUTINE +//#define IS_ISR_ROUTINE #include "WProgram.h" @@ -13,6 +13,8 @@ #include #include +#include "MCLSeq.h" + MidiUartClass::MidiUartClass(volatile uint8_t *udr_, volatile uint8_t *rx_buf, uint16_t rx_buf_size, volatile uint8_t *tx_buf, uint16_t tx_buf_size) @@ -87,7 +89,14 @@ void MidiUartClass::realtime_isr(uint8_t c) { if (c == MIDI_CLOCK) { if (MidiClock.uart_clock_recv == this) { MidiClock.handleClock(); - MidiClock.callCallbacks(true); + if (MidiClock.state != 2 || MidiClock.inCallback) { return; } + MidiClock.inCallback = true; + uint8_t _midi_lock_tmp = MidiUartParent::handle_midi_lock; + MidiUartParent::handle_midi_lock = 1; + sei(); + mcl_seq.seq(); + MidiUartParent::handle_midi_lock = _midi_lock_tmp; + MidiClock.inCallback = false; } } else if (MidiClock.uart_transport_recv1 == this || MidiClock.uart_transport_recv2 == this) { diff --git a/avr/cores/megacommand/MidiUart.h b/avr/cores/megacommand/MidiUart.h index 7c332cee0..15c8928d9 100644 --- a/avr/cores/megacommand/MidiUart.h +++ b/avr/cores/megacommand/MidiUart.h @@ -6,9 +6,9 @@ #include #include #include "Midi.h" -//#define TXEN 3 -//#define RXEN 4 -//#define RXCIE 7 +// #define TXEN 3 +// #define RXEN 4 +// #define RXCIE 7 #ifdef MEGACOMMAND #define TIMER1_CHECK_INT() IS_BIT_SET8(TIFR1, OCF1A) @@ -87,7 +87,7 @@ #define TX_IRQ 1 -//#define RX_BUF_SIZE 2048 +// #define RX_BUF_SIZE 2048 #if (RX_BUF_SIZE >= 256) #define RX_BUF_TYPE uint16_t #else @@ -120,10 +120,10 @@ class MidiUartClass : public MidiUartParent { int8_t in_message_tx; - #ifdef RUNNING_STATUS_OUT +#ifdef RUNNING_STATUS_OUT uint8_t running_status; bool running_status_enabled; - #endif +#endif volatile uint8_t *udr; volatile uint8_t *ubrrh() { return udr - 1; } @@ -132,14 +132,14 @@ class MidiUartClass : public MidiUartParent { volatile uint8_t *ucsrb() { return udr - 5; } volatile uint8_t *ucsra() { return udr - 6; } - #ifdef RUNNING_STATUS_OUT +#ifdef RUNNING_STATUS_OUT ALWAYS_INLINE() bool write_char(uint8_t c) { if (!running_status_enabled) { *udr = c; return true; } if (MIDI_IS_STATUS_BYTE(c) && MIDI_IS_VOICE_STATUS_BYTE(c)) { - if (c != running_status) { + if (c != running_status) { running_status = c; *udr = c; return true; @@ -150,11 +150,9 @@ class MidiUartClass : public MidiUartParent { return true; } } - #else - ALWAYS_INLINE() void write_char(uint8_t c) { - *udr = c; - } - #endif +#else + ALWAYS_INLINE() void write_char(uint8_t c) { *udr = c; } +#endif uint8_t read_char() { return *udr; } bool check_empty_tx() { @@ -192,7 +190,7 @@ class MidiUartClass : public MidiUartParent { } switch (midi->live_state) { - case midi_wait_sysex: { + case midi_wait_sysex: if (MIDI_IS_STATUS_BYTE(c)) { if (c != MIDI_SYSEX_END) { @@ -207,28 +205,23 @@ class MidiUartClass : public MidiUartParent { midi->midiSysex.handleByte(c); } break; - } - case midi_wait_status: { + case midi_wait_status: if (c == MIDI_SYSEX_START) { midi->live_state = midi_wait_sysex; midi->midiSysex.reset(); - } else { - rxRb.put_h_isr(c); + break; } - } break; - default: { + default: rxRb.put_h_isr(c); break; } - } } - ALWAYS_INLINE() void tx_isr() { #ifdef RUNNING_STATUS_OUT bool rs = 1; + again: #endif - again: if ((txRb_sidechannel != nullptr) && (in_message_tx == 0)) { // sidechannel mounted, and no active messages in normal channel // ==> flush the sidechannel now @@ -305,13 +298,19 @@ class MidiUartClass : public MidiUartParent { clear_tx(); } #ifdef RUNNING_STATUS_OUT - if (!rs) { goto again; } + if (!rs) { + goto again; + } #endif if (txRb.isEmpty_isr() && (txRb_sidechannel == nullptr)) { clear_tx(); } } + ALWAYS_INLINE() void m_recv(uint8_t *src, uint16_t size) { + rxRb.put_h_isr(src, size); + } + ALWAYS_INLINE() void m_putc(uint8_t *src, uint16_t size) { txRb.put_h_isr(src, size); set_tx(); diff --git a/avr/cores/megacommand/ResourceManager.cpp b/avr/cores/megacommand/ResourceManager.cpp index c1703b8d0..cb7c1ad08 100644 --- a/avr/cores/megacommand/ResourceManager.cpp +++ b/avr/cores/megacommand/ResourceManager.cpp @@ -45,53 +45,40 @@ void ResourceManager::Restore(uint8_t *buf, size_t sz) { void ResourceManager::restore_page_entry_deps() { // calibrate references - R.page_entries->Entries[0].Page = &grid_page; R.page_entries->Entries[0].IconData = R.icons_page->icon_grid; - R.page_entries->Entries[1].Page = &mixer_page; R.page_entries->Entries[1].IconData = R.icons_page->icon_mixer; - R.page_entries->Entries[2].Page = &route_page; - R.page_entries->Entries[2].IconData = R.icons_page->icon_route; - R.page_entries->Entries[3].Page = &lfo_page; - R.page_entries->Entries[3].IconData = R.icons_page->icon_lfo; + R.page_entries->Entries[2].IconData = R.icons_page->icon_perf; + R.page_entries->Entries[3].IconData = R.icons_page->icon_route; + - R.page_entries->Entries[4].Page = &seq_step_page; R.page_entries->Entries[4].IconData = R.icons_page->icon_step; + R.page_entries->Entries[5].IconData = R.icons_page->icon_lfo; + R.page_entries->Entries[6].IconData = R.icons_page->icon_pianoroll; + R.page_entries->Entries[7].IconData = R.icons_page->icon_chroma; - R.page_entries->Entries[5].Page = &seq_extstep_page; - R.page_entries->Entries[5].IconData = R.icons_page->icon_pianoroll; - R.page_entries->Entries[6].Page = &seq_ptc_page; - R.page_entries->Entries[6].IconData = R.icons_page->icon_chroma; - uint8_t idx = 7; + uint8_t idx = 8; #ifdef SOUND_PAGE - R.page_entries->Entries[idx].Page = &sound_browser; - R.page_entries->Entries[idx].IconData = R.icons_page->icon_sound; + R.page_entries->Entries[idx].IconData = R.icons_page->icon_sample; ++idx; #endif #ifdef WAV_DESIGNER - R.page_entries->Entries[idx].Page = &wd.pages[0]; R.page_entries->Entries[idx].IconData = R.icons_page->icon_wavd; ++idx; #endif #ifdef LOUDNESS_PAGE - R.page_entries->Entries[idx].Page = &loudness_page; R.page_entries->Entries[idx].IconData = R.icons_page->icon_loudness; ++idx; #endif - R.page_entries->Entries[idx].Page = &fx_page_a; R.page_entries->Entries[idx].IconData = R.icons_page->icon_rhytmecho; ++idx; - R.page_entries->Entries[idx].Page = &fx_page_b; R.page_entries->Entries[idx].IconData = R.icons_page->icon_gatebox; ++idx; - R.page_entries->Entries[idx].Page = &ram_page_a; R.page_entries->Entries[idx].IconData = R.icons_page->icon_ram1; ++idx; - R.page_entries->Entries[idx].Page = &ram_page_b; R.page_entries->Entries[idx].IconData = R.icons_page->icon_ram2; // calibration complete - } size_t ResourceManager::Size() { @@ -107,7 +94,6 @@ void ResourceManager::restore_menu_layout_deps() { ram_config_page.set_layout(R.menu_layouts->rampage1_menu_layout); file_menu_page.set_layout(R.menu_layouts->file_menu_layout); seq_menu_page.set_layout(R.menu_layouts->seq_menu_layout); - step_menu_page.set_layout(R.menu_layouts->step_menu_layout); grid_slot_page.set_layout(R.menu_layouts->slot_menu_layout); wavdesign_menu_page.set_layout(R.menu_layouts->wavdesign_menu_layout); md_import_page.set_layout(R.menu_layouts->mdimport_menu_layout); @@ -118,6 +104,7 @@ void ResourceManager::restore_menu_layout_deps() { midiclock_menu_page.set_layout(R.menu_layouts->midiclock_menu_layout); midiroute_menu_page.set_layout(R.menu_layouts->midiroute_menu_layout); midimachinedrum_menu_page.set_layout(R.menu_layouts->midimachinedrum_menu_layout); + perf_menu_page.set_layout(R.menu_layouts->perf_menu_layout); } ResourceManager R; diff --git a/avr/cores/megacommand/WProgram.h b/avr/cores/megacommand/WProgram.h index 7d44eec57..39fb718e1 100644 --- a/avr/cores/megacommand/WProgram.h +++ b/avr/cores/megacommand/WProgram.h @@ -29,12 +29,12 @@ #define DEBUG_PRINTLN(x) MidiUartUSB.println(x) #define DEBUG_DUMP(x) { \ } -// __PRETTY_FUNCTION__ is a gcc extension -// #define DEBUG_PRINT_FN(x) { \ -// DEBUG_PRINT(F("func_call: ")); \ -// Serial.println(__PRETTY_FUNCTION__); \ -// } -// +/* __PRETTY_FUNCTION__ is a gcc extension + #define DEBUG_PRINT_FN(x) { \ + DEBUG_PRINT(F("func_call: ")); \ + Serial.println(__PRETTY_FUNCTION__); \ + } +*/ #define DEBUG_CHECK_STACK() { if ((int) SP < 0x200 || (int)SP > 0x2200) { cli(); setLed2(); setLed(); while (1); } } #define DEBUG_PRINT_FN(x) diff --git a/avr/cores/megacommand/global.cpp b/avr/cores/megacommand/global.cpp index a4f914f7d..6ea4f2daa 100644 --- a/avr/cores/megacommand/global.cpp +++ b/avr/cores/megacommand/global.cpp @@ -4,20 +4,20 @@ // -- Midi UART devices -MidiUartClass seq_tx1(&UDR1,(volatile uint8_t *)nullptr, - (size_t) 0, +MidiUartClass seq_tx1(&UDR1,(volatile uint8_t *)BANK1_UART1_RX_BUFFER_START, + UART1_RX_BUFFER_LEN, (volatile uint8_t *)BANK1_UARTSEQ_TX1_BUFFER_START, TX_SEQBUF_SIZE); -MidiUartClass seq_tx2(&UDR1,(volatile uint8_t *)nullptr, - (size_t) 0, +MidiUartClass seq_tx2(&UDR1,(volatile uint8_t *)BANK1_UART1_RX_BUFFER_START, + UART1_RX_BUFFER_LEN, (volatile uint8_t *)BANK1_UARTSEQ_TX2_BUFFER_START, TX_SEQBUF_SIZE); -MidiUartClass seq_tx3(&UDR2,(volatile uint8_t *)nullptr, - (size_t) 0, +MidiUartClass seq_tx3(&UDR2,(volatile uint8_t *)BANK1_UART2_RX_BUFFER_START, + UART2_RX_BUFFER_LEN, (volatile uint8_t *)BANK1_UARTSEQ_TX3_BUFFER_START, TX_SEQBUF_SIZE); -MidiUartClass seq_tx4(&UDR2,(volatile uint8_t *)nullptr, - (size_t) 0, +MidiUartClass seq_tx4(&UDR2,(volatile uint8_t *)BANK1_UART2_RX_BUFFER_START, + UART2_RX_BUFFER_LEN, (volatile uint8_t *)BANK1_UARTSEQ_TX4_BUFFER_START, TX_SEQBUF_SIZE); diff --git a/avr/cores/megacommand/main.cpp b/avr/cores/megacommand/main.cpp index cc0a0e98a..83b7fb13c 100644 --- a/avr/cores/megacommand/main.cpp +++ b/avr/cores/megacommand/main.cpp @@ -13,6 +13,8 @@ extern "C" { #include } +#include "MCLSeq.h" + #define OLED_CLK 52 #define OLED_MOSI 51 @@ -177,7 +179,14 @@ ISR(TIMER1_COMPA_vect) { MidiClock.increment192Counter(); MidiClock.div192th_countdown = 0; MidiClock.div192th_counter_last = MidiClock.div192th_counter; - MidiClock.callCallbacks(); + if (MidiClock.inCallback) { return; } + MidiClock.inCallback = true; + uint8_t _midi_lock_tmp = MidiUartParent::handle_midi_lock; + MidiUartParent::handle_midi_lock = 1; + sei(); + mcl_seq.seq(); + MidiUartParent::handle_midi_lock = _midi_lock_tmp; + MidiClock.inCallback = false; } } } @@ -202,10 +211,10 @@ ALWAYS_INLINE() void gui_poll() { static bool inGui = false; if (inGui) { return; - } else { - inGui = true; } + inGui = true; + uint16_t sr = SR165.read16(); if (sr != oldsr) { Buttons.clear(); diff --git a/avr/cores/megacommand/memory.h b/avr/cores/megacommand/memory.h index c01e0bd4a..ee121551a 100644 --- a/avr/cores/megacommand/memory.h +++ b/avr/cores/megacommand/memory.h @@ -150,25 +150,25 @@ FORCED_INLINE() extern inline uint8_t get_byte_bank1(volatile uint8_t *dst) { FORCED_INLINE() extern inline void get_bank2(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); - memcpy((void*)dst, (void*)src + 0x4000, len); + memcpy((void*)dst, (uint8_t*)src + 0x4000, len); } FORCED_INLINE() extern inline void get_bank3(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); select_bank(1); - memcpy((void*)dst, (void*)src + 0x4000, len); + memcpy((void*)dst, (uint8_t*)src + 0x4000, len); } FORCED_INLINE() extern inline void put_bank2(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); - memcpy((void*)dst + 0x4000, (void*)src, len); + memcpy((uint8_t*)dst + 0x4000, (uint8_t*)src, len); } FORCED_INLINE() extern inline void put_bank3(volatile void *dst, volatile const void *src, uint16_t len) { ram_access_fringe(); select_bank(1); - memcpy((void*)dst + 0x4000, (void*)src, len); + memcpy((uint8_t*)dst + 0x4000, (uint8_t*)src, len); } @@ -176,9 +176,11 @@ FORCED_INLINE() extern inline void put_bank3(volatile void *dst, volatile const extern volatile uint8_t *rand_ptr; FORCED_INLINE() extern inline uint8_t get_random_byte() { - return (pgm_read_byte(rand_ptr++) ^ get_byte_bank1(rand_ptr) ^ slowclock) & 0x7F; + return (pgm_read_byte(rand_ptr++) ^ get_byte_bank1(rand_ptr) ^ slowclock); } +extern inline uint8_t get_random(uint8_t range) { return get_random_byte() % range; } + #endif// __cplusplus #endif /* MEMORY_H__ */ diff --git a/avr/cores/megacommand/resources/R.h b/avr/cores/megacommand/resources/R.h index 19055c4fd..821477b57 100644 --- a/avr/cores/megacommand/resources/R.h +++ b/avr/cores/megacommand/resources/R.h @@ -2,66 +2,21 @@ #include #include "MCL.h" #include "MCL_impl.h" -extern const unsigned char __R_font_default[] PROGMEM; -struct __T_font_default { - union { - unsigned char font[0]; - char zz__font[1280]; - }; - static constexpr size_t countof_font = 1280 / sizeof(unsigned char); - static constexpr size_t sizeofof_font = 1280; - static constexpr size_t __total_size = 1280; -}; - -extern const unsigned char __R_font_elektrothic[] PROGMEM; -struct __T_font_elektrothic { - union { - GFXglyph ElektrothicGlyphs[0]; - char zz__ElektrothicGlyphs[665]; - }; - static constexpr size_t countof_ElektrothicGlyphs = 665 / sizeof(GFXglyph); - static constexpr size_t sizeofof_ElektrothicGlyphs = 665; - union { - unsigned char ElektrothicBitmaps[0]; - char zz__ElektrothicBitmaps[593]; - }; - static constexpr size_t countof_ElektrothicBitmaps = 593 / sizeof(unsigned char); - static constexpr size_t sizeofof_ElektrothicBitmaps = 593; - static constexpr size_t __total_size = 1258; -}; - -extern const unsigned char __R_font_tomthumb[] PROGMEM; -struct __T_font_tomthumb { - union { - GFXglyph TomThumbGlyphs[0]; - char zz__TomThumbGlyphs[665]; - }; - static constexpr size_t countof_TomThumbGlyphs = 665 / sizeof(GFXglyph); - static constexpr size_t sizeofof_TomThumbGlyphs = 665; - union { - unsigned char TomThumbBitmaps[0]; - char zz__TomThumbBitmaps[418]; - }; - static constexpr size_t countof_TomThumbBitmaps = 418 / sizeof(unsigned char); - static constexpr size_t sizeofof_TomThumbBitmaps = 418; - static constexpr size_t __total_size = 1083; -}; - extern const unsigned char __R_icons_boot[] PROGMEM; struct __T_icons_boot { union { unsigned char evilknievel_bitmap[0]; - char zz__evilknievel_bitmap[192]; + char zz__evilknievel_bitmap[155]; }; - static constexpr size_t countof_evilknievel_bitmap = 192 / sizeof(unsigned char); - static constexpr size_t sizeofof_evilknievel_bitmap = 192; + static constexpr size_t countof_evilknievel_bitmap = 155 / sizeof(unsigned char); + static constexpr size_t sizeofof_evilknievel_bitmap = 155; union { unsigned char mcl_logo_bitmap[0]; char zz__mcl_logo_bitmap[152]; }; static constexpr size_t countof_mcl_logo_bitmap = 152 / sizeof(unsigned char); static constexpr size_t sizeofof_mcl_logo_bitmap = 152; - static constexpr size_t __total_size = 344; + static constexpr size_t __total_size = 307; }; extern const unsigned char __R_icons_device[] PROGMEM; @@ -152,8 +107,103 @@ struct __T_icons_knob { static constexpr size_t __total_size = 325; }; +extern const unsigned char __R_icons_logo[] PROGMEM; +struct __T_icons_logo { + union { + unsigned char metronome_gif_data[0]; + char zz__metronome_gif_data[360]; + }; + static constexpr size_t countof_metronome_gif_data = 360 / sizeof(unsigned char); + static constexpr size_t sizeofof_metronome_gif_data = 360; + union { + unsigned char monomachine_gif_data[0]; + char zz__monomachine_gif_data[270]; + }; + static constexpr size_t countof_monomachine_gif_data = 270 / sizeof(unsigned char); + static constexpr size_t sizeofof_monomachine_gif_data = 270; + union { + unsigned char midi_gif_data[0]; + char zz__midi_gif_data[216]; + }; + static constexpr size_t countof_midi_gif_data = 216 / sizeof(unsigned char); + static constexpr size_t sizeofof_midi_gif_data = 216; + union { + unsigned char machinedrum_gif_data[0]; + char zz__machinedrum_gif_data[216]; + }; + static constexpr size_t countof_machinedrum_gif_data = 216 / sizeof(unsigned char); + static constexpr size_t sizeofof_machinedrum_gif_data = 216; + union { + unsigned char analog_gif_data[0]; + char zz__analog_gif_data[189]; + }; + static constexpr size_t countof_analog_gif_data = 189 / sizeof(unsigned char); + static constexpr size_t sizeofof_analog_gif_data = 189; + union { + unsigned char route_gif_data[0]; + char zz__route_gif_data[100]; + }; + static constexpr size_t countof_route_gif_data = 100 / sizeof(unsigned char); + static constexpr size_t sizeofof_route_gif_data = 100; + union { + unsigned char perf_gif_data[0]; + char zz__perf_gif_data[189]; + }; + static constexpr size_t countof_perf_gif_data = 189 / sizeof(unsigned char); + static constexpr size_t sizeofof_perf_gif_data = 189; + union { + MCLGIF midi_gif[0]; + char zz__midi_gif[13]; + }; + static constexpr size_t countof_midi_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_midi_gif = 13; + union { + MCLGIF machinedrum_gif[0]; + char zz__machinedrum_gif[13]; + }; + static constexpr size_t countof_machinedrum_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_machinedrum_gif = 13; + union { + MCLGIF monomachine_gif[0]; + char zz__monomachine_gif[13]; + }; + static constexpr size_t countof_monomachine_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_monomachine_gif = 13; + union { + MCLGIF analog_gif[0]; + char zz__analog_gif[13]; + }; + static constexpr size_t countof_analog_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_analog_gif = 13; + union { + MCLGIF route_gif[0]; + char zz__route_gif[13]; + }; + static constexpr size_t countof_route_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_route_gif = 13; + union { + MCLGIF perf_gif[0]; + char zz__perf_gif[13]; + }; + static constexpr size_t countof_perf_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_perf_gif = 13; + union { + MCLGIF metronome_gif[0]; + char zz__metronome_gif[13]; + }; + static constexpr size_t countof_metronome_gif = 13 / sizeof(MCLGIF); + static constexpr size_t sizeofof_metronome_gif = 13; + static constexpr size_t __total_size = 1631; +}; + extern const unsigned char __R_icons_page[] PROGMEM; struct __T_icons_page { + union { + unsigned char icon_perf[0]; + char zz__icon_perf[54]; + }; + static constexpr size_t countof_icon_perf = 54 / sizeof(unsigned char); + static constexpr size_t sizeofof_icon_perf = 54; union { unsigned char icon_chroma[0]; char zz__icon_chroma[75]; @@ -179,17 +229,17 @@ struct __T_icons_page { static constexpr size_t countof_icon_ram2 = 75 / sizeof(unsigned char); static constexpr size_t sizeofof_icon_ram2 = 75; union { - unsigned char icon_sound[0]; - char zz__icon_sound[57]; + unsigned char icon_sample[0]; + char zz__icon_sample[75]; }; - static constexpr size_t countof_icon_sound = 57 / sizeof(unsigned char); - static constexpr size_t sizeofof_icon_sound = 57; + static constexpr size_t countof_icon_sample = 75 / sizeof(unsigned char); + static constexpr size_t sizeofof_icon_sample = 75; union { unsigned char icon_route[0]; - char zz__icon_route[48]; + char zz__icon_route[42]; }; - static constexpr size_t countof_icon_route = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_icon_route = 48; + static constexpr size_t countof_icon_route = 42 / sizeof(unsigned char); + static constexpr size_t sizeofof_icon_route = 42; union { unsigned char icon_rhytmecho[0]; char zz__icon_rhytmecho[75]; @@ -210,22 +260,16 @@ struct __T_icons_page { static constexpr size_t sizeofof_icon_mixer = 48; union { unsigned char icon_step[0]; - char zz__icon_step[75]; + char zz__icon_step[63]; }; - static constexpr size_t countof_icon_step = 75 / sizeof(unsigned char); - static constexpr size_t sizeofof_icon_step = 75; + static constexpr size_t countof_icon_step = 63 / sizeof(unsigned char); + static constexpr size_t sizeofof_icon_step = 63; union { unsigned char icon_wavd[0]; char zz__icon_wavd[57]; }; static constexpr size_t countof_icon_wavd = 57 / sizeof(unsigned char); static constexpr size_t sizeofof_icon_wavd = 57; - union { - unsigned char icon_loudness[0]; - char zz__icon_loudness[48]; - }; - static constexpr size_t countof_icon_loudness = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_icon_loudness = 48; union { unsigned char icon_lfo[0]; char zz__icon_lfo[72]; @@ -238,7 +282,7 @@ struct __T_icons_page { }; static constexpr size_t countof_icon_grid = 45 / sizeof(unsigned char); static constexpr size_t sizeofof_icon_grid = 45; - static constexpr size_t __total_size = 900; + static constexpr size_t __total_size = 906; }; extern const unsigned char __R_machine_names_long[] PROGMEM; @@ -295,278 +339,141 @@ struct __T_machine_param_names { extern const unsigned char __R_menu_layouts[] PROGMEM; struct __T_menu_layouts { union { - menu_t<3> wavdesign_menu_layout[0]; - char zz__wavdesign_menu_layout[75]; + menu_t perf_menu_layout[0]; + char zz__perf_menu_layout[53]; }; - static constexpr size_t countof_wavdesign_menu_layout = 75 / sizeof(menu_t<3>); - static constexpr size_t sizeofof_wavdesign_menu_layout = 75; + static constexpr size_t countof_perf_menu_layout = 53 / sizeof(menu_t); + static constexpr size_t sizeofof_perf_menu_layout = 53; union { - menu_t slot_menu_layout[0]; - char zz__slot_menu_layout[243]; + menu_t wavdesign_menu_layout[0]; + char zz__wavdesign_menu_layout[74]; }; - static constexpr size_t countof_slot_menu_layout = 243 / sizeof(menu_t); - static constexpr size_t sizeofof_slot_menu_layout = 243; + static constexpr size_t countof_wavdesign_menu_layout = 74 / sizeof(menu_t); + static constexpr size_t sizeofof_wavdesign_menu_layout = 74; union { - menu_t<4> step_menu_layout[0]; - char zz__step_menu_layout[96]; + menu_t slot_menu_layout[0]; + char zz__slot_menu_layout[200]; }; - static constexpr size_t countof_step_menu_layout = 96 / sizeof(menu_t<4>); - static constexpr size_t sizeofof_step_menu_layout = 96; + static constexpr size_t countof_slot_menu_layout = 200 / sizeof(menu_t); + static constexpr size_t sizeofof_slot_menu_layout = 200; union { - menu_t<20> seq_menu_layout[0]; - char zz__seq_menu_layout[432]; + menu_t seq_menu_layout[0]; + char zz__seq_menu_layout[515]; }; - static constexpr size_t countof_seq_menu_layout = 432 / sizeof(menu_t<20>); - static constexpr size_t sizeofof_seq_menu_layout = 432; + static constexpr size_t countof_seq_menu_layout = 515 / sizeof(menu_t); + static constexpr size_t sizeofof_seq_menu_layout = 515; union { - menu_t<7> file_menu_layout[0]; - char zz__file_menu_layout[159]; + menu_t file_menu_layout[0]; + char zz__file_menu_layout[158]; }; - static constexpr size_t countof_file_menu_layout = 159 / sizeof(menu_t<7>); - static constexpr size_t sizeofof_file_menu_layout = 159; + static constexpr size_t countof_file_menu_layout = 158 / sizeof(menu_t); + static constexpr size_t sizeofof_file_menu_layout = 158; union { - menu_t<1> mclconfig_menu_layout[0]; - char zz__mclconfig_menu_layout[33]; + menu_t mclconfig_menu_layout[0]; + char zz__mclconfig_menu_layout[32]; }; - static constexpr size_t countof_mclconfig_menu_layout = 33 / sizeof(menu_t<1>); - static constexpr size_t sizeofof_mclconfig_menu_layout = 33; + static constexpr size_t countof_mclconfig_menu_layout = 32 / sizeof(menu_t); + static constexpr size_t sizeofof_mclconfig_menu_layout = 32; union { - menu_t<4> mdimport_menu_layout[0]; - char zz__mdimport_menu_layout[96]; + menu_t mdimport_menu_layout[0]; + char zz__mdimport_menu_layout[95]; }; - static constexpr size_t countof_mdimport_menu_layout = 96 / sizeof(menu_t<4>); - static constexpr size_t sizeofof_mdimport_menu_layout = 96; + static constexpr size_t countof_mdimport_menu_layout = 95 / sizeof(menu_t); + static constexpr size_t sizeofof_mdimport_menu_layout = 95; union { - menu_t<3> mdconfig_menu_layout[0]; - char zz__mdconfig_menu_layout[75]; + menu_t mdconfig_menu_layout[0]; + char zz__mdconfig_menu_layout[53]; }; - static constexpr size_t countof_mdconfig_menu_layout = 75 / sizeof(menu_t<3>); - static constexpr size_t sizeofof_mdconfig_menu_layout = 75; + static constexpr size_t countof_mdconfig_menu_layout = 53 / sizeof(menu_t); + static constexpr size_t sizeofof_mdconfig_menu_layout = 53; union { - menu_t<3> midimachinedrum_menu_layout[0]; - char zz__midimachinedrum_menu_layout[75]; + menu_t midimachinedrum_menu_layout[0]; + char zz__midimachinedrum_menu_layout[74]; }; - static constexpr size_t countof_midimachinedrum_menu_layout = 75 / sizeof(menu_t<3>); - static constexpr size_t sizeofof_midimachinedrum_menu_layout = 75; + static constexpr size_t countof_midimachinedrum_menu_layout = 74 / sizeof(menu_t); + static constexpr size_t sizeofof_midimachinedrum_menu_layout = 74; union { - menu_t<4> midiroute_menu_layout[0]; - char zz__midiroute_menu_layout[96]; + menu_t midiroute_menu_layout[0]; + char zz__midiroute_menu_layout[95]; }; - static constexpr size_t countof_midiroute_menu_layout = 96 / sizeof(menu_t<4>); - static constexpr size_t sizeofof_midiroute_menu_layout = 96; + static constexpr size_t countof_midiroute_menu_layout = 95 / sizeof(menu_t); + static constexpr size_t sizeofof_midiroute_menu_layout = 95; union { - menu_t<4> midiclock_menu_layout[0]; - char zz__midiclock_menu_layout[96]; + menu_t midiclock_menu_layout[0]; + char zz__midiclock_menu_layout[95]; }; - static constexpr size_t countof_midiclock_menu_layout = 96 / sizeof(menu_t<4>); - static constexpr size_t sizeofof_midiclock_menu_layout = 96; + static constexpr size_t countof_midiclock_menu_layout = 95 / sizeof(menu_t); + static constexpr size_t sizeofof_midiclock_menu_layout = 95; union { - menu_t<3> midiprogram_menu_layout[0]; - char zz__midiprogram_menu_layout[75]; + menu_t midiprogram_menu_layout[0]; + char zz__midiprogram_menu_layout[74]; }; - static constexpr size_t countof_midiprogram_menu_layout = 75 / sizeof(menu_t<3>); - static constexpr size_t sizeofof_midiprogram_menu_layout = 75; + static constexpr size_t countof_midiprogram_menu_layout = 74 / sizeof(menu_t); + static constexpr size_t sizeofof_midiprogram_menu_layout = 74; union { - menu_t<5> midiport_menu_layout[0]; - char zz__midiport_menu_layout[117]; + menu_t midiport_menu_layout[0]; + char zz__midiport_menu_layout[116]; }; - static constexpr size_t countof_midiport_menu_layout = 117 / sizeof(menu_t<5>); - static constexpr size_t sizeofof_midiport_menu_layout = 117; + static constexpr size_t countof_midiport_menu_layout = 116 / sizeof(menu_t); + static constexpr size_t sizeofof_midiport_menu_layout = 116; union { - menu_t<5> midiconfig_menu_layout[0]; - char zz__midiconfig_menu_layout[117]; + menu_t midiconfig_menu_layout[0]; + char zz__midiconfig_menu_layout[116]; }; - static constexpr size_t countof_midiconfig_menu_layout = 117 / sizeof(menu_t<5>); - static constexpr size_t sizeofof_midiconfig_menu_layout = 117; + static constexpr size_t countof_midiconfig_menu_layout = 116 / sizeof(menu_t); + static constexpr size_t sizeofof_midiconfig_menu_layout = 116; union { - menu_t<1> rampage1_menu_layout[0]; - char zz__rampage1_menu_layout[33]; + menu_t rampage1_menu_layout[0]; + char zz__rampage1_menu_layout[32]; }; - static constexpr size_t countof_rampage1_menu_layout = 33 / sizeof(menu_t<1>); - static constexpr size_t sizeofof_rampage1_menu_layout = 33; + static constexpr size_t countof_rampage1_menu_layout = 32 / sizeof(menu_t); + static constexpr size_t sizeofof_rampage1_menu_layout = 32; union { - menu_t<1> auxconfig_menu_layout[0]; - char zz__auxconfig_menu_layout[33]; + menu_t auxconfig_menu_layout[0]; + char zz__auxconfig_menu_layout[32]; }; - static constexpr size_t countof_auxconfig_menu_layout = 33 / sizeof(menu_t<1>); - static constexpr size_t sizeofof_auxconfig_menu_layout = 33; + static constexpr size_t countof_auxconfig_menu_layout = 32 / sizeof(menu_t); + static constexpr size_t sizeofof_auxconfig_menu_layout = 32; union { - menu_t<6> system_menu_layout[0]; - char zz__system_menu_layout[138]; + menu_t system_menu_layout[0]; + char zz__system_menu_layout[137]; }; - static constexpr size_t countof_system_menu_layout = 138 / sizeof(menu_t<6>); - static constexpr size_t sizeofof_system_menu_layout = 138; + static constexpr size_t countof_system_menu_layout = 137 / sizeof(menu_t); + static constexpr size_t sizeofof_system_menu_layout = 137; union { - menu_t<2> start_menu_layout[0]; - char zz__start_menu_layout[54]; + menu_t start_menu_layout[0]; + char zz__start_menu_layout[53]; }; - static constexpr size_t countof_start_menu_layout = 54 / sizeof(menu_t<2>); - static constexpr size_t sizeofof_start_menu_layout = 54; + static constexpr size_t countof_start_menu_layout = 53 / sizeof(menu_t); + static constexpr size_t sizeofof_start_menu_layout = 53; union { - menu_t<4> boot_menu_layout[0]; - char zz__boot_menu_layout[96]; + menu_t boot_menu_layout[0]; + char zz__boot_menu_layout[95]; }; - static constexpr size_t countof_boot_menu_layout = 96 / sizeof(menu_t<4>); - static constexpr size_t sizeofof_boot_menu_layout = 96; - static constexpr size_t __total_size = 2139; + static constexpr size_t countof_boot_menu_layout = 95 / sizeof(menu_t); + static constexpr size_t sizeofof_boot_menu_layout = 95; + static constexpr size_t __total_size = 2099; }; extern const unsigned char __R_menu_options[] PROGMEM; struct __T_menu_options { union { menu_option_t MENU_OPTIONS[0]; - char zz__MENU_OPTIONS[936]; + char zz__MENU_OPTIONS[1089]; }; - static constexpr size_t countof_MENU_OPTIONS = 936 / sizeof(menu_option_t); - static constexpr size_t sizeofof_MENU_OPTIONS = 936; - static constexpr size_t __total_size = 936; + static constexpr size_t countof_MENU_OPTIONS = 1089 / sizeof(menu_option_t); + static constexpr size_t sizeofof_MENU_OPTIONS = 1089; + static constexpr size_t __total_size = 1089; }; extern const unsigned char __R_page_entries[] PROGMEM; struct __T_page_entries { union { PageSelectEntry Entries[0]; - char zz__Entries[312]; - }; - static constexpr size_t countof_Entries = 312 / sizeof(PageSelectEntry); - static constexpr size_t sizeofof_Entries = 312; - static constexpr size_t __total_size = 312; -}; - -extern const unsigned char __R_tuning[] PROGMEM; -struct __T_tuning { - union { - unsigned char tonal_tuning[0]; - char zz__tonal_tuning[64]; - }; - static constexpr size_t countof_tonal_tuning = 64 / sizeof(unsigned char); - static constexpr size_t sizeofof_tonal_tuning = 64; - union { - unsigned char e12_lt_tuning[0]; - char zz__e12_lt_tuning[40]; - }; - static constexpr size_t countof_e12_lt_tuning = 40 / sizeof(unsigned char); - static constexpr size_t sizeofof_e12_lt_tuning = 40; - union { - unsigned char e12_cb_tuning[0]; - char zz__e12_cb_tuning[48]; - }; - static constexpr size_t countof_e12_cb_tuning = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_e12_cb_tuning = 48; - union { - unsigned char e12_bc_tuning[0]; - char zz__e12_bc_tuning[48]; - }; - static constexpr size_t countof_e12_bc_tuning = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_e12_bc_tuning = 48; - union { - unsigned char efm_cy_tuning[0]; - char zz__efm_cy_tuning[30]; - }; - static constexpr size_t countof_efm_cy_tuning = 30 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_cy_tuning = 30; - union { - unsigned char efm_cb_tuning[0]; - char zz__efm_cb_tuning[30]; - }; - static constexpr size_t countof_efm_cb_tuning = 30 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_cb_tuning = 30; - union { - unsigned char trx_rs_tuning[0]; - char zz__trx_rs_tuning[12]; - }; - static constexpr size_t countof_trx_rs_tuning = 12 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_rs_tuning = 12; - union { - unsigned char trx_b2_tuning[0]; - char zz__trx_b2_tuning[24]; - }; - static constexpr size_t countof_trx_b2_tuning = 24 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_b2_tuning = 24; - union { - unsigned char gnd_sn_tuning[0]; - char zz__gnd_sn_tuning[96]; - }; - static constexpr size_t countof_gnd_sn_tuning = 96 / sizeof(unsigned char); - static constexpr size_t sizeofof_gnd_sn_tuning = 96; - union { - unsigned char rom_tuning[0]; - char zz__rom_tuning[48]; - }; - static constexpr size_t countof_rom_tuning = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_rom_tuning = 48; - union { - unsigned char trx_s2_tuning[0]; - char zz__trx_s2_tuning[19]; - }; - static constexpr size_t countof_trx_s2_tuning = 19 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_s2_tuning = 19; - union { - unsigned char trx_bd_tuning[0]; - char zz__trx_bd_tuning[24]; - }; - static constexpr size_t countof_trx_bd_tuning = 24 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_bd_tuning = 24; - union { - unsigned char trx_xt_tuning[0]; - char zz__trx_xt_tuning[24]; - }; - static constexpr size_t countof_trx_xt_tuning = 24 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_xt_tuning = 24; - union { - unsigned char trx_xc_tuning[0]; - char zz__trx_xc_tuning[24]; - }; - static constexpr size_t countof_trx_xc_tuning = 24 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_xc_tuning = 24; - union { - unsigned char trx_sd_tuning[0]; - char zz__trx_sd_tuning[12]; - }; - static constexpr size_t countof_trx_sd_tuning = 12 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_sd_tuning = 12; - union { - unsigned char trx_cl_tuning[0]; - char zz__trx_cl_tuning[21]; - }; - static constexpr size_t countof_trx_cl_tuning = 21 / sizeof(unsigned char); - static constexpr size_t sizeofof_trx_cl_tuning = 21; - union { - unsigned char efm_bd_tuning[0]; - char zz__efm_bd_tuning[48]; - }; - static constexpr size_t countof_efm_bd_tuning = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_bd_tuning = 48; - union { - unsigned char efm_xt_tuning[0]; - char zz__efm_xt_tuning[24]; - }; - static constexpr size_t countof_efm_xt_tuning = 24 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_xt_tuning = 24; - union { - unsigned char efm_sd_tuning[0]; - char zz__efm_sd_tuning[30]; - }; - static constexpr size_t countof_efm_sd_tuning = 30 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_sd_tuning = 30; - union { - unsigned char efm_cp_tuning[0]; - char zz__efm_cp_tuning[66]; - }; - static constexpr size_t countof_efm_cp_tuning = 66 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_cp_tuning = 66; - union { - unsigned char efm_hh_tuning[0]; - char zz__efm_hh_tuning[30]; - }; - static constexpr size_t countof_efm_hh_tuning = 30 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_hh_tuning = 30; - union { - unsigned char efm_rs_tuning[0]; - char zz__efm_rs_tuning[48]; + char zz__Entries[322]; }; - static constexpr size_t countof_efm_rs_tuning = 48 / sizeof(unsigned char); - static constexpr size_t sizeofof_efm_rs_tuning = 48; - static constexpr size_t __total_size = 810; + static constexpr size_t countof_Entries = 322 / sizeof(PageSelectEntry); + static constexpr size_t sizeofof_Entries = 322; + static constexpr size_t __total_size = 322; }; diff --git a/avr/cores/megacommand/resources/R_icons_boot.cpp b/avr/cores/megacommand/resources/R_icons_boot.cpp index 7c6546fba..66d3887f1 100644 --- a/avr/cores/megacommand/resources/R_icons_boot.cpp +++ b/avr/cores/megacommand/resources/R_icons_boot.cpp @@ -1,233 +1,205 @@ #include "R.h" const unsigned char __R_icons_boot[] PROGMEM = { - 229, + 242, 0, - 127, - 255, - 186, + 15, + 224, 0, - 5, - 213, - 111, - 111, - 232, - 42, - 255, + 238, + 127, + 248, + 4, + 219, + 223, 252, + 3, + 1, + 221, + 193, + 238, + 4, 128, + 155, + 246, 0, - 119, - 128, - 5, - 127, - 189, - 98, - 0, + 123, + 47, 2, - 217, - 11, - 112, 0, + 31, + 154, + 128, + 15, 91, - 23, - 96, - 109, - 11, - 191, - 189, - 5, - 32, - 0, + 6, 1, - 155, - 11, - 41, - 172, - 40, - 11, - 125, + 110, + 192, + 4, + 203, + 7, + 224, + 7, + 219, + 227, + 224, + 7, + 207, + 219, 63, - 135, - 242, - 254, - 221, - 59, - 215, - 253, - 126, + 224, + 22, + 127, + 187, 219, - 5, + 4, + 175, + 243, + 151, + 32, 239, - 254, - 11, - 251, + 242, + 55, 199, - 255, - 252, - 5, - 247, - 254, - 236, - 29, - 118, + 226, + 160, + 47, 195, - 253, - 212, - 5, - 247, - 30, - 128, - 250, - 11, - 91, - 21, - 71, - 84, - 111, - 5, - 26, - 128, - 2, - 151, - 168, + 130, + 96, + 110, 29, - 192, - 203, - 5, - 120, - 10, - 238, - 226, - 10, - 252, - 11, - 109, - 23, - 92, - 190, - 5, - 11, - 192, - 10, - 190, - 95, - 61, - 192, - 21, - 95, - 255, 128, - 7, - 254, - 232, - 10, - 191, + 3, + 235, + 39, + 64, + 44, + 251, + 48, + 15, 240, + 4, + 115, + 126, 31, - 255, - 255, - 208, - 23, - 95, - 248, + 109, + 131, 63, - 255, - 232, - 205, - 15, - 191, - 0, - 246, - 31, - 127, - 248, - 127, - 140, + 100, 238, - 62, - 191, - 5, - 218, - 192, - 125, - 11, - 222, - 176, - 250, - 250, + 3, + 51, 255, - 237, - 5, - 127, - 245, - 189, - 11, + 4, + 229, 1, + 252, + 188, + 237, + 131, + 249, + 222, + 99, + 238, + 255, + 227, + 108, + 4, + 219, + 198, + 100, + 49, + 255, + 255, + 12, + 119, + 0, + 29, + 126, + 48, + 89, + 128, 255, + 123, + 32, + 96, + 142, + 0, + 242, + 96, + 129, + 219, + 135, + 128, + 24, 243, - 174, + 110, 1, - 120, - 176, - 3, + 254, + 0, + 214, + 42, 7, - 100, + 12, 7, - 25, + 131, 15, - 6, + 32, + 200, 31, - 65, - 147, + 50, 63, - 119, - 232, - 243, + 13, + 127, + 187, + 5, 248, 3, - 116, 7, + 164, 255, - 129, - 176, + 13, + 128, 23, - 29, + 239, 63, 223, - 254, 7, + 242, 127, 192, 31, 159, - 79, + 121, 15, 31, - 39, + 61, 6, - 188, 31, + 246, 63, - 51, - 23, + 127, + 227, + 179, 7, - 57, + 147, 0, - 57, + 144, 126, - 6, + 100, 124, - 65, - 144, + 25, 120, - 66, - 54, - 128, + 7, + 112, 0, 0, 0, 0, - 2, - 127, + 0, + 0, + 4, + 255, 255, }; diff --git a/avr/cores/megacommand/resources/R_icons_logo.cpp b/avr/cores/megacommand/resources/R_icons_logo.cpp new file mode 100644 index 000000000..766e29957 --- /dev/null +++ b/avr/cores/megacommand/resources/R_icons_logo.cpp @@ -0,0 +1,713 @@ +#include "R.h" +const unsigned char __R_icons_logo[] PROGMEM = { + 230, + 0, + 0, + 0, + 55, + 3, + 192, + 128, + 251, + 3, + 65, + 0, + 6, + 38, + 2, + 124, + 166, + 0, + 12, + 152, + 190, + 144, + 0, + 24, + 40, + 95, + 72, + 0, + 48, + 132, + 47, + 4, + 0, + 63, + 246, + 248, + 0, + 15, + 240, + 42, + 29, + 2, + 182, + 44, + 194, + 2, + 219, + 76, + 41, + 44, + 109, + 2, + 176, + 249, + 41, + 12, + 176, + 152, + 44, + 7, + 4, + 109, + 2, + 8, + 182, + 41, + 216, + 2, + 219, + 88, + 41, + 48, + 98, + 44, + 235, + 2, + 208, + 44, + 25, + 136, + 41, + 218, + 16, + 0, + 15, + 219, + 41, + 240, + 2, + 109, + 96, + 41, + 182, + 32, + 2, + 224, + 230, + 41, + 44, + 50, + 136, + 83, + 64, + 99, + 2, + 192, + 107, + 179, + 2, + 173, + 64, + 41, + 117, + 47, + 160, + 141, + 134, + 144, + 128, + 44, + 59, + 1, + 0, + 2, + 27, + 128, + 44, + 7, + 7, + 32, + 36, + 11, + 178, + 7, + 6, + 0, + 107, + 38, + 89, + 23, + 134, + 91, + 7, + 44, + 13, + 33, + 93, + 16, + 237, + 223, + 11, + 181, + 192, + 2, + 204, + 44, + 89, + 118, + 14, + 144, + 47, + 183, + 21, + 25, + 8, + 100, + 44, + 123, + 252, + 252, + 2, + 242, + 204, + 204, + 19, + 207, + 204, + 207, + 192, + 200, + 26, + 108, + 12, + 2, + 109, + 15, + 23, + 117, + 2, + 60, + 173, + 23, + 2, + 96, + 17, + 216, + 12, + 26, + 93, + 0, + 175, + 23, + 2, + 149, + 204, + 133, + 26, + 44, + 2, + 38, + 3, + 219, + 23, + 3, + 26, + 43, + 185, + 12, + 2, + 139, + 192, + 2, + 179, + 60, + 0, + 48, + 17, + 108, + 12, + 26, + 45, + 132, + 0, + 176, + 26, + 172, + 96, + 76, + 47, + 2, + 100, + 0, + 79, + 60, + 178, + 0, + 219, + 42, + 138, + 2, + 170, + 35, + 178, + 126, + 17, + 63, + 254, + 231, + 2, + 8, + 216, + 124, + 26, + 66, + 26, + 243, + 188, + 219, + 14, + 106, + 26, + 0, + 236, + 160, + 80, + 108, + 170, + 26, + 14, + 1, + 205, + 80, + 151, + 107, + 170, + 96, + 26, + 200, + 128, + 108, + 134, + 135, + 128, + 42, + 186, + 179, + 97, + 128, + 192, + 26, + 29, + 171, + 64, + 141, + 80, + 64, + 148, + 26, + 216, + 128, + 80, + 216, + 64, + 134, + 191, + 56, + 15, + 131, + 219, + 192, + 31, + 2, + 63, + 229, + 135, + 128, + 127, + 242, + 255, + 143, + 0, + 119, + 227, + 39, + 190, + 66, + 93, + 2, + 188, + 110, + 26, + 130, + 0, + 89, + 0, + 2, + 221, + 53, + 129, + 45, + 128, + 163, + 26, + 48, + 118, + 255, + 142, + 26, + 19, + 14, + 150, + 3, + 3, + 198, + 80, + 131, + 219, + 53, + 129, + 26, + 101, + 136, + 144, + 188, + 109, + 8, + 53, + 183, + 28, + 26, + 62, + 7, + 45, + 7, + 141, + 80, + 135, + 182, + 26, + 162, + 23, + 219, + 176, + 2, + 184, + 43, + 26, + 109, + 3, + 2, + 182, + 49, + 53, + 120, + 223, + 2, + 252, + 15, + 0, + 118, + 182, + 15, + 26, + 30, + 219, + 20, + 142, + 2, + 108, + 132, + 161, + 27, + 31, + 23, + 109, + 15, + 2, + 182, + 199, + 53, + 99, + 221, + 2, + 49, + 190, + 173, + 189, + 2, + 216, + 4, + 60, + 188, + 77, + 63, + 187, + 23, + 23, + 143, + 104, + 88, + 134, + 221, + 3, + 161, + 252, + 27, + 234, + 66, + 111, + 68, + 33, + 0, + 47, + 176, + 161, + 2, + 92, + 11, + 237, + 17, + 15, + 156, + 182, + 32, + 248, + 137, + 251, + 36, + 0, + 19, + 146, + 47, + 108, + 210, + 2, + 23, + 11, + 59, + 17, + 7, + 216, + 11, + 48, + 240, + 91, + 42, + 8, + 111, + 89, + 228, + 0, + 5, + 176, + 244, + 2, + 92, + 11, + 231, + 17, + 23, + 109, + 0, + 224, + 5, + 182, + 16, + 11, + 72, + 217, + 2, + 232, + 14, + 72, + 231, + 17, + 23, + 36, + 218, + 111, + 160, + 11, + 216, + 1, + 80, + 2, + 119, + 16, + 17, + 38, + 245, + 97, + 2, + 200, + 224, + 75, + 20, + 6, + 0, + 230, + 32, + 2, + 0, + 187, + 0, + 30, + 60, + 255, + 60, + 120, + 48, + 96, + 253, + 248, + 120, + 240, + 106, + 5, + 238, + 98, + 96, + 72, + 144, + 239, + 7, + 60, + 30, + 120, + 60, + 255, + 96, + 49, + 248, + 252, + 240, + 120, + 96, + 48, + 100, + 19, + 255, + 0, + 120, + 30, + 96, + 61, + 248, + 48, + 243, + 240, + 252, + 96, + 120, + 111, + 120, + 144, + 47, + 96, + 41, + 108, + 19, + 22, + 83, + 66, + 251, + 3, + 1, + 135, + 127, + 34, + 17, + 192, + 68, + 9, + 128, + 255, + 132, + 9, + 64, + 132, + 40, + 64, + 164, + 72, + 253, + 64, + 98, + 16, + 128, + 225, + 225, + 236, + 42, + 26, + 185, + 41, + 25, + 8, + 41, + 145, + 73, + 144, + 8, + 14, + 201, + 230, + 80, + 26, + 16, + 242, + 137, + 128, + 133, + 17, + 207, + 9, + 133, + 33, + 12, + 132, + 156, + 136, + 151, + 27, + 224, + 8, + 18, + 9, + 123, + 36, + 0, + 12, + 43, + 150, + 10, + 1, + 73, + 144, + 7, + 31, + 20, + 5, + 14, + 10, + 96, + 25, + 95, + 45, + 8, + 17, + 178, + 15, + 12, + 64, + 0, + 0, + 0, + 0, + 1, + 63, + 255, +}; diff --git a/avr/cores/megacommand/resources/R_icons_page.cpp b/avr/cores/megacommand/resources/R_icons_page.cpp index c94985e02..b59f74460 100644 --- a/avr/cores/megacommand/resources/R_icons_page.cpp +++ b/avr/cores/megacommand/resources/R_icons_page.cpp @@ -1,172 +1,191 @@ #include "R.h" const unsigned char __R_icons_page[] PROGMEM = { - 255, + 202, 0, 0, + 98, + 13, + 112, + 191, + 2, + 96, 0, - 117, - 119, + 28, + 80, + 0, + 207, + 99, + 8, + 255, + 207, + 132, + 16, + 128, + 230, + 8, + 127, + 0, + 246, + 5, + 28, 0, - 69, - 85, - 254, 3, - 71, - 101, + 30, + 216, + 7, + 47, + 75, + 16, + 173, 15, - 117, - 87, + 2, + 150, 57, - 223, - 13, 231, - 0, - 3, + 217, + 10, 156, - 255, - 0, - 15, + 125, 241, 0, 63, 194, - 0, - 255, - 255, + 191, + 53, 9, 3, 252, 100, 15, + 255, 240, 178, 55, - 255, 194, 89, 215, 9, 45, + 255, 220, 100, 150, - 255, 112, 178, 89, 130, 89, + 255, 103, 201, 45, - 255, 158, 236, 150, 120, 118, + 255, 89, 224, 59, - 255, 103, 128, 29, 158, 0, + 255, 14, 120, 0, - 251, 6, 224, 0, 2, 128, + 107, 5, - 91, 60, + 119, 254, - 185, 0, 5, - 155, + 51, 8, + 96, 2, - 7, + 243, 6, 7, - 153, 192, - 128, + 48, + 23, 23, - 186, 5, + 92, 62, - 230, 2, + 203, 32, - 93, + 185, 248, - 204, 2, + 144, 56, - 133, - 131, + 176, 0, + 127, 31, - 251, 255, 248, 32, 0, 4, + 103, 2, - 63, 35, 255, + 255, 196, 36, - 255, 194, 100, 37, 66, 164, + 253, 38, 67, 36, - 236, 35, 129, 196, + 131, 23, - 29, 255, + 185, 4, - 204, 35, + 159, 44, - 255, 7, 56, 112, + 253, 15, 188, 240, - 237, 13, 182, 192, + 175, 2, - 124, 5, + 151, 15, - 190, 7, 54, - 112, - 0, + 10, + 4, 194, 74, 23, @@ -194,158 +213,171 @@ const unsigned char __R_icons_page[] PROGMEM = { 219, 11, 56, - 190, + 176, + 224, + 71, + 237, 224, - 24, + 44, + 182, + 48, + 2, + 56, + 91, + 60, + 53, + 237, 3, - 223, - 5, + 62, + 182, 63, - 224, - 1, - 255, - 108, 2, 252, - 178, + 89, 192, - 83, + 11, + 151, 195, - 44, 199, - 251, - 7, + 196, + 255, + 35, 199, - 125, - 125, - 195, - 128, - 15, - 192, - 182, - 71, + 132, + 39, + 131, + 4, + 39, 128, - 149, - 178, - 129, - 93, - 61, + 107, + 113, + 122, + 152, + 2, + 44, + 101, + 183, + 0, + 127, + 1, + 248, + 252, + 3, 241, - 237, 248, - 7, - 227, - 74, - 221, 3, - 0, + 221, + 1, + 128, 2, - 31, - 183, - 143, - 35, + 15, + 251, + 199, + 224, 7, - 128, - 115, + 131, + 192, 8, - 110, - 157, + 156, + 203, + 238, 8, - 25, - 189, - 140, - 14, - 204, - 43, - 176, - 7, + 12, + 198, + 96, + 230, + 5, + 116, + 30, 254, 63, - 126, + 251, 2, 252, - 0, - 221, - 108, + 48, + 127, + 252, 7, 225, - 223, - 56, 248, - 15, - 199, + 7, + 227, + 183, + 248, + 44, 240, 15, - 237, + 220, 255, 240, - 31, - 125, - 107, + 140, + 208, 2, - 133, - 127, + 191, + 168, 127, 128, 63, 31, 192, + 253, 126, - 251, 15, 224, 126, 7, 240, + 221, 44, - 187, 123, 219, 124, + 223, 2, - 190, 99, 27, 108, 123, 31, - 119, + 59, 8, - 51, + 153, 17, - 96, - 75, - 134, - 86, - 182, + 176, + 114, + 67, + 98, + 91, 30, - 92, + 98, 126, - 217, - 155, + 237, + 224, + 1, + 254, + 110, 254, - 127, 255, 144, 3, 254, 112, 12, - 182, 249, + 219, 74, 38, - 223, 2, + 127, 220, 240, 239, 211, - 237, 55, 15, + 133, 223, - 122, + 55, 255, 159, 240, @@ -400,161 +432,112 @@ const unsigned char __R_icons_page[] PROGMEM = { 2, 32, 13, - 214, + 209, 0, 215, - 243, - 254, + 190, + 87, 221, 0, 12, 245, + 23, + 57, + 119, 0, - 56, - 55, - 97, + 255, 224, 60, - 255, 3, 128, 127, 15, 1, 222, + 255, 57, 135, - 255, 56, 214, 204, 225, 217, 251, + 255, 134, 127, - 255, 254, 25, 167, 152, 103, 222, + 241, 97, 158, - 198, 233, 134, - 75, - 242, + 188, + 87, 25, 224, 58, - 23, - 0, - 183, - 119, - 50, - 66, - 69, - 253, - 0, - 114, - 103, - 0, - 18, - 68, - 183, - 5, - 116, - 75, - 91, + 132, + 176, + 63, + 109, 136, 2, + 150, 204, - 44, 170, - 47, + 23, 210, 153, 17, + 247, 16, - 109, - 20, + 0, + 18, 168, - 210, 2, + 75, 32, - 203, 81, + 47, 138, - 252, 116, 169, + 242, 4, 16, 170, 0, - 140, + 50, 238, - 189, + 247, 170, 16, 68, - 208, 35, + 82, 187, - 129, - 74, - 133, - 46, - 255, - 17, - 255, - 136, - 37, - 195, - 164, - 41, - 153, + 12, + 22, + 222, 237, - 148, - 41, - 165, - 2, - 220, - 181, - 148, - 8, - 231, - 14, - 20, - 5, - 202, - 239, - 128, - 1, - 231, - 2, - 115, - 8, - 38, - 89, - 49, - 97, - 227, - 190, + 255, 16, 30, - 0, - 8, + 54, + 249, 96, 214, 2, - 22, + 77, 220, 9, - 116, + 68, 219, 0, 12, @@ -569,7 +552,7 @@ const unsigned char __R_icons_page[] PROGMEM = { 62, 133, 28, - 128, + 68, 247, 62, 192, @@ -577,7 +560,7 @@ const unsigned char __R_icons_page[] PROGMEM = { 99, 2, 133, - 123, + 63, 182, 224, 2, @@ -588,30 +571,31 @@ const unsigned char __R_icons_page[] PROGMEM = { 96, 62, 14, - 222, + 220, 96, 28, 29, - 215, - 2, - 196, - 119, + 25, + 137, + 221, + 136, 54, 219, 108, + 214, 2, - 89, 0, 8, - 7, + 65, + 211, 1, - 28, - 23, + 74, 0, 0, 0, 0, 0, - 9, + 2, + 127, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_layouts.cpp b/avr/cores/megacommand/resources/R_menu_layouts.cpp index 4989a395e..7a568ff98 100644 --- a/avr/cores/megacommand/resources/R_menu_layouts.cpp +++ b/avr/cores/megacommand/resources/R_menu_layouts.cpp @@ -5,714 +5,711 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 0, 0, 35, - 69, - 246, - 68, - 73, + 67, + 255, 84, + 82, + 76, + 32, + 83, + 69, + 76, 58, + 103, 14, - 95, 4, + 255, 4, + 59, + 255, + 0, + 117, + 82, + 69, + 78, + 246, + 65, + 77, + 69, + 0, + 0, + 3, + 255, + 176, + 30, + 13, + 63, + 69, + 68, + 73, + 84, + 102, + 48, + 193, + 52, + 151, 40, - 111, - 4, 80, 87, + 236, 65, - 176, 86, - 19, - 31, - 0, + 58, + 35, + 7, 6, 6, + 182, 41, - 111, - 4, + 20, 74, - 84, - 82, - 253, + 223, + 93, 65, 78, 83, 70, + 216, 69, 82, - 128, - 24, - 255, + 73, + 15, 22, 0, 23, - 0, + 246, 83, 108, 111, - 179, 116, 13, - 253, + 127, 71, 82, 73, 68, 58, + 178, 32, - 147, 28, + 123, 2, - 219, 2, 31, - 4, 52, - 246, - 77, - 79, - 68, - 69, - 75, - 95, - 1, - 4, - 3, - 119, - 32, - 20, + 118, + 52, 76, - 69, - 181, - 78, - 40, - 172, - 0, - 20, - 62, + 126, + 182, + 19, + 32, + 195, + 21, + 251, + 1, 65, 0, 39, - 230, + 255, 6, + 89, 20, - 67, + 12, 129, - 39, + 159, 79, - 216, 79, 80, - 83, - 15, + 96, + 62, + 61, 64, 0, 33, - 187, - 0, - 138, + 220, + 20, + 74, 85, 77, - 96, - 20, - 125, + 129, + 251, 128, 128, 34, - 214, + 255, 4, + 109, 67, 63, - 246, + 236, 65, 82, 58, - 125, - 3, + 104, + 7, 36, - 182, - 0, + 255, + 109, 44, 67, - 219, + 183, 61, 89, 84, - 153, + 50, 20, - 115, + 230, 37, - 125, + 251, 80, 65, 83, 84, 69, - 129, 41, - 221, + 3, + 184, 38, 20, - 73, - 111, - 219, - 82, - 79, - 87, - 100, - 21, - 247, - 127, - 1, - 50, + 32, + 17, + 15, 20, - 91, - 82, - 146, - 65, - 216, - 77, - 69, - 240, - 11, - 187, - 187, 0, 21, - 0, - 62, - 108, - 80, + 11, + 55, + 81, + 96, 13, - 22, - 116, - 83, - 30, + 187, 231, - 0, - 15, - 30, - 186, - 32, - 98, - 80, - 203, - 53, - 216, - 16, - 0, - 116, - 176, - 21, - 191, + 67, + 75, + 9, + 71, + 63, + 1, 17, 0, - 77, - 85, - 100, - 19, - 126, - 0, - 18, + 14, + 255, + 254, + 3, 0, - 19, - 221, - 95, + 68, 69, - 81, - 130, - 13, - 27, - 115, + 86, + 73, 67, - 75, - 182, - 32, - 15, - 76, - 198, - 99, + 201, + 74, + 247, 1, - 222, - 49, - 14, - 0, - 3, - 18, - 178, - 187, - 15, 3, - 108, - 48, + 2, + 50, + 136, + 4, + 59, + 167, + 15, + 255, + 217, + 4, + 48, 20, - 135, + 15, 9, 1, - 183, 16, - 4, + 111, + 41, 54, 67, - 216, 67, + 176, 58, - 187, - 31, + 112, + 62, 133, 5, 17, - 111, - 4, + 222, + 20, 55, 83, 76, - 10, - 166, - 194, - 254, - 109, + 21, + 48, + 132, + 157, + 219, 18, - 4, - 183, + 20, 25, - 197, + 111, + 217, 80, 69, - 252, 71, + 248, 71, 73, 65, 84, 79, - 33, - 223, - 218, - 10, + 67, + 104, + 119, + 211, + 75, + 69, + 89, + 96, + 63, 125, - 17, - 241, - 236, - 80, - 79, - 83, - 45, - 27, 12, - 154, - 93, - 5, + 12, + 19, + 184, + 41, + 104, 86, - 98, - 140, - 18, - 124, - 195, - 17, - 6, - 7, + 68, + 233, + 37, + 27, 225, - 79, + 0, + 20, + 48, + 130, + 6, + 236, 78, 68, - 229, + 21, + 191, 1, - 237, 15, 15, 21, - 5, - 219, + 110, + 20, 60, 83, + 219, 82, 69, - 96, 21, - 56, + 1, + 252, 7, 7, - 220, - 46, + 22, + 255, 5, 41, 55, - 229, + 132, 71, 84, 72, - 146, + 132, 58, - 71, - 65, - 91, + 153, + 191, + 23, + 255, 6, - 62, + 0, + 97, + 20, + 121, + 2, + 129, + 28, + 67, 72, - 109, - 104, + 45, + 248, 78, 146, - 87, - 235, - 230, + 108, + 27, + 16, 24, - 45, - 97, + 255, + 194, + 7, 0, - 187, - 33, - 252, + 111, + 67, 3, + 248, 3, 25, - 0, + 255, 8, 27, - 33, - 112, - 110, + 66, + 153, + 221, 20, - 181, 26, - 234, - 128, - 20, - 120, + 200, + 255, + 9, + 7, 10, + 132, 30, - 66, - 229, - 221, + 153, + 45, + 223, 20, 27, - 254, - 0, + 255, 11, 27, 83, + 225, 72, 73, 70, - 16, - 38, - 30, + 59, + 1, + 252, 5, 5, 28, - 216, - 213, + 255, + 12, 35, - 86, - 229, - 211, - 220, + 43, + 174, + 232, + 118, 82, - 228, - 201, + 83, + 43, + 178, 41, - 246, + 127, 29, - 0, + 255, 13, 27, + 80, + 79, 246, - 251, 76, 89, 80, 72, - 214, - 97, + 235, + 217, 89, - 82, - 45, - 173, + 44, + 54, + 11, 2, - 41, - 246, - 67, - 32, + 237, 81, 85, - 171, - 180, - 66, - 32, - 58, - 204, + 167, + 132, + 84, + 79, + 14, 42, - 23, - 146, + 96, + 182, + 121, + 32, + 65, + 133, + 125, + 101, + 20, + 205, + 30, + 83, + 194, + 79, + 85, + 38, + 132, + 144, + 12, + 107, + 129, + 2, + 123, + 14, 70, 73, - 104, - 128, - 193, - 15, + 169, + 82, + 73, + 11, + 72, 109, - 27, 67, - 182, - 199, - 0, - 0, - 22, - 220, - 217, + 240, + 24, + 34, + 75, + 2, + 66, + 2, + 225, 87, 32, - 46, - 157, + 219, + 118, 82, 46, - 194, 20, - 66, - 130, - 181, + 6, + 57, + 23, + 173, 51, - 172, - 159, + 200, + 100, 41, - 132, - 101, - 111, - 110, - 0, - 186, + 35, + 97, + 43, + 117, + 20, 79, - 157, + 212, + 198, 87, - 149, - 90, - 133, + 173, + 34, 44, - 187, - 137, + 97, + 41, + 127, + 67, 86, 32, - 216, 65, 76, - 106, - 91, - 195, - 66, - 133, - 178, + 144, + 76, + 150, + 236, + 181, + 156, + 145, 20, - 151, - 22, - 67, + 186, + 21, 89, - 9, - 88, + 26, + 49, 77, - 116, - 194, - 73, - 147, - 225, + 246, + 13, + 132, + 133, + 208, + 198, 76, 65, - 85, - 66, - 250, - 77, + 17, + 178, + 210, + 109, 13, - 184, - 4, + 31, + 236, 23, 1, - 219, - 134, - 68, - 42, - 39, + 77, + 208, + 158, + 83, 82, 67, - 76, - 88, - 144, - 89, - 27, + 153, + 51, + 32, + 52, + 49, 43, - 4, - 154, - 170, - 212, - 63, - 132, - 110, - 207, + 205, + 171, + 168, + 106, + 62, + 66, + 73, + 103, 44, - 79, - 134, - 85, - 6, - 9, - 241, - 35, - 6, - 111, + 10, + 7, + 16, + 49, + 24, + 1, + 219, + 66, 45, - 149, - 107, + 147, + 218, 19, - 123, - 11, - 12, - 30, - 214, - 3, - 95, + 25, + 26, + 132, + 189, + 218, + 25, 3, + 203, + 94, + 165, 73, - 74, - 184, - 54, - 96, + 146, + 27, + 155, 84, - 192, - 31, - 225, - 11, + 96, 31, - 155, + 112, + 33, + 205, + 28, 18, + 183, 77, - 111, - 181, + 178, 73, 90, - 69, - 8, - 85, - 116, - 8, + 10, + 167, 193, - 48, - 127, - 227, - 32, - 86, - 130, - 91, - 194, - 71, - 127, - 75, - 74, - 30, + 147, + 182, + 8, + 73, + 16, + 238, + 52, 32, 77, 73, 208, - 198, - 244, - 106, + 174, + 254, + 81, 72, - 177, - 175, + 82, + 79, 32, - 236, - 56, - 53, - 251, - 18, + 61, + 72, + 159, + 31, + 17, 2, 9, - 4, - 158, - 53, - 194, + 44, + 18, + 59, + 197, 20, - 67, - 116, - 70, + 9, + 151, + 46, 88, - 198, - 181, - 67, - 132, + 84, + 11, + 35, + 71, + 97, 20, - 221, + 55, 57, - 4, + 41, + 109, 24, - 107, - 172, - 193, - 66, - 83, - 11, - 81, - 254, - 32, - 49, - 32, - 70, - 87, - 53, - 173, - 39, + 82, + 169, + 8, + 57, + 47, 80, + 248, + 32, + 49, + 32, + 70, + 87, + 212, + 209, + 157, + 116, 7, - 28, - 254, - 198, + 182, + 31, + 10, 20, 50, - 64, - 109, + 50, + 3, 51, - 4, - 246, + 47, 92, 85, 83, + 176, 66, 17, - 10, - 65, - 122, - 183, + 82, + 158, + 13, 52, - 4, + 177, + 20, 96, - 67, - 26, + 203, + 15, + 105, + 194, + 60, + 93, + 11, + 184, 20, - 188, - 166, - 37, - 85, - 187, - 211, 86, 24, - 12, - 118, - 53, - 11, - 97, - 37, - 211, - 79, - 197, - 7, - 178, - 140, + 80, + 92, + 161, + 240, + 250, + 5, + 169, + 29, + 253, + 131, + 151, + 198, 58, - 96, - 233, + 110, + 118, 5, - 13, - 146, - 92, + 31, + 214, + 7, + 250, 44, 20, 14, @@ -720,299 +717,314 @@ const unsigned char __R_menu_layouts[] PROGMEM = { 102, 41, 97, - 199, + 172, 152, - 116, - 118, + 115, + 112, 6, - 4, - 216, + 182, + 40, 100, 41, - 176, + 44, 20, - 57, + 14, 54, - 155, - 95, + 222, + 41, + 100, + 24, 80, - 109, - 192, + 219, + 190, 71, - 161, - 25, - 215, - 156, + 24, + 67, + 188, + 181, 9, - 208, - 223, - 37, - 103, 186, - 128, + 220, + 77, + 79, + 102, + 246, + 126, + 29, 49, - 219, - 4, + 183, + 31, 90, 20, - 236, + 225, 73, - 242, - 88, - 245, - 48, + 78, + 135, + 39, + 18, + 2, + 134, 47, - 207, - 10, + 7, + 123, 20, - 115, - 246, + 244, + 156, 21, - 15, - 17, - 2, - 185, + 16, + 7, + 110, 48, 20, - 193, - 74, - 148, - 171, + 135, + 24, + 122, + 172, 83, - 112, - 63, + 166, + 252, 85, 82, 66, 79, - 10, - 11, - 203, - 224, - 185, + 43, + 8, + 221, + 47, 2, - 79, - 156, + 255, + 107, + 78, 20, + 57, 50, - 151, + 46, 3, - 36, - 134, - 16, - 176, + 73, + 13, + 13, 58, + 96, 20, - 102, + 205, 55, - 133, 68, - 106, - 28, - 173, - 214, + 10, + 102, + 57, + 144, + 172, 42, - 137, - 77, + 136, + 155, 4, - 214, - 82, - 67, - 192, - 239, - 76, - 32, + 189, + 96, + 84, + 197, + 65, + 235, 98, - 89, - 196, - 182, + 250, + 54, 41, + 222, 56, - 196, - 191, - 38, - 199, - 230, - 0, - 126, - 33, - 235, - 9, + 189, + 16, + 194, 92, - 106, - 19, - 62, - 96, - 0, - 107, - 251, - 130, - 179, - 45, - 212, - 176, + 189, + 250, + 26, + 32, + 232, + 98, + 70, + 86, + 162, + 97, + 12, + 34, + 112, + 152, + 97, + 59, + 133, + 47, + 199, + 36, + 68, + 57, + 186, + 182, + 210, 71, 20, - 21, - 161, - 251, - 8, - 13, - 128, + 3, + 37, + 104, + 252, + 65, + 6, + 96, 20, - 198, - 13, - 40, - 88, - 16, - 131, - 49, - 206, - 161, - 39, - 110, - 138, + 56, + 35, + 0, + 195, + 35, + 96, + 20, + 55, + 38, + 3, + 57, + 38, + 184, + 136, 65, 71, - 26, - 247, + 107, + 242, 76, - 218, - 71, + 70, + 107, 75, - 203, - 200, - 117, - 170, + 231, + 45, + 212, + 168, 1, - 143, - 7, + 253, + 13, 65, 85, 88, - 99, - 32, + 141, + 31, 83, - 103, - 42, + 159, + 41, 97, - 217, 103, 101, - 35, - 112, - 8, - 236, - 204, - 167, - 176, - 182, - 171, + 101, + 34, + 195, + 31, + 198, + 50, + 164, + 194, + 165, + 218, 65, - 100, - 187, - 124, + 97, + 232, + 121, 74, - 69, - 106, - 225, - 65, - 6, + 81, + 189, + 131, + 180, + 25, 72, - 236, + 203, 176, 19, - 183, - 90, - 50, - 234, - 214, - 142, - 91, - 161, - 163, + 182, + 252, + 198, + 2, + 89, + 44, + 200, + 46, + 26, + 232, + 158, 65, - 147, - 90, - 131, - 5, - 33, - 74, - 52, - 195, - 186, + 214, + 139, + 129, + 129, + 62, + 82, + 21, 176, - 4, - 126, - 17, - 37, - 124, - 164, - 192, - 4, - 9, - 75, + 183, + 236, + 27, + 125, + 5, + 147, + 41, + 29, + 72, + 160, + 108, + 62, + 12, + 78, + 104, + 193, + 101, 97, - 54, - 216, - 102, - 44, - 137, - 32, - 221, - 3, + 136, + 19, + 0, + 141, 66, - 26, - 170, - 193, - 15, - 2, - 216, - 133, - 190, - 134, + 161, + 96, + 14, + 225, + 79, + 83, + 184, + 97, 80, - 57, - 172, + 52, + 134, + 49, + 164, + 140, + 150, + 127, + 241, 68, - 89, - 186, - 27, - 220, - 34, 70, 85, - 98, - 75, - 192, - 108, + 138, + 68, 64, - 163, - 77, - 246, - 215, - 59, - 88, + 161, + 90, + 169, + 61, + 237, + 117, + 25, 75, + 128, 20, - 12, + 196, 28, - 27, - 134, + 181, + 221, 88, - 90, - 147, - 146, - 236, - 27, - 29, - 3, - 128, + 169, + 112, + 203, + 33, + 112, + 169, 0, 0, 0, 0, - 1, - 63, + 0, + 39, 255, }; diff --git a/avr/cores/megacommand/resources/R_menu_options.cpp b/avr/cores/megacommand/resources/R_menu_options.cpp index d0695cd40..b4379ad48 100644 --- a/avr/cores/megacommand/resources/R_menu_options.cpp +++ b/avr/cores/megacommand/resources/R_menu_options.cpp @@ -78,334 +78,396 @@ const unsigned char __R_menu_options[] PROGMEM = { 53, 217, 17, - 15, - 73, - 78, - 84, - 99, - 7, + 14, + 45, + 45, + 207, + 62, 17, - 246, 79, + 236, 77, 78, 73, 26, - 27, - 80, 54, + 80, + 108, 62, - 31, + 63, 3, 81, 85, - 216, 69, - 0, - 44, - 77, - 1, - 222, + 103, + 36, + 73, + 217, + 78, + 84, + 62, + 187, 8, 43, 69, + 216, 88, 84, - 192, 80, - 90, - 232, - 193, - 135, - 216, - 45, - 45, - 179, - 61, + 13, + 79, + 204, + 43, + 80, + 39, + 1, 84, + 217, 82, 75, - 159, 71, + 246, 65, 76, 76, - 100, 26, - 62, + 67, 76, + 228, 67, 75, 83, - 66, - 30, + 33, + 236, 89, 69, 83, - 200, 44, - 216, + 141, + 135, 224, - 118, 82, + 96, 8, - 15, + 246, 3, 76, 62, - 103, 55, + 125, 4, - 216, 82, 62, + 131, 64, - 54, 32, + 98, 26, - 33, + 16, 94, - 0, - 251, + 15, 3, 51, + 179, 47, 10, - 59, + 180, 2, 8, - 66, + 39, 105, - 123, 4, + 176, 49, 17, - 7, + 114, 5, 49, - 32, - 218, + 13, 6, + 161, 8, - 16, 123, - 91, + 5, + 187, 179, 73, - 177, 71, 44, - 251, + 31, 83, 76, 73, 68, + 177, 69, 125, - 27, + 181, 79, 171, - 88, + 140, 71, - 194, 77, + 40, 22, - 132, + 79, 5, - 246, 88, 0, + 97, 170, - 27, + 176, 116, - 12, - 43, + 194, 227, + 179, 26, - 63, + 246, 128, 80, 82, 71, - 99, 16, + 56, 129, - 132, 80, + 65, 165, - 31, + 246, 130, 67, 72, 80, - 99, 8, + 48, 131, - 8, + 135, 40, - 127, 132, + 251, 76, 69, 65, 82, - 177, 78, 89, - 176, + 27, 49, 215, - 114, + 7, 76, 50, - 28, + 33, + 198, 51, - 96, 0, - 236, + 14, 76, 52, + 207, 8, - 249, 5, 76, + 147, 53, - 62, + 228, 6, 76, 54, - 79, + 249, 7, 76, - 147, 55, - 228, + 62, 8, 76, 56, - 246, + 79, 9, 80, + 96, 71, - 14, + 228, 10, 80, - 65, - 216, + 29, 11, 80, + 131, 53, - 59, 12, + 176, 80, 44, - 7, + 123, 13, 80, - 179, 57, 8, - 225, + 62, 14, 49, 83, + 18, 166, - 35, - 133, + 56, 83, + 86, 203, - 102, 134, - 230, + 110, 251, + 103, 134, - 124, 80, + 198, 85, 76, - 96, 135, - 236, + 14, 65, 87, + 204, 134, - 198, + 108, 77, - 198, 82, + 96, 117, - 14, + 236, 83, 67, - 198, 109, + 110, 1, - 235, 8, + 177, 50, 53, - 23, + 116, 8, - 66, 51, + 39, 31, - 125, 73, + 216, 88, 69, - 143, 37, + 246, 71, 69, 78, - 99, 8, + 59, 1, - 183, 69, 234, + 113, 75, 84, - 24, + 133, 171, - 95, + 241, 45, 62, 50, - 97, - 125, - 140, + 129, 117, - 47, + 125, 0, 66, - 182, 65, + 177, 136, 67, - 49, + 142, 126, - 198, 68, 86, + 50, 225, - 67, + 25, 49, - 37, - 50, + 41, + 147, 49, - 108, + 96, 35, - 3, - 76, + 26, + 102, 14, - 203, 35, - 164, + 93, 50, + 32, 41, + 71, + 65, 8, - 64, + 211, + 123, + 65, + 35, + 35, + 6, + 66, + 195, + 71, + 104, + 148, + 65, + 148, + 176, + 67, + 26, + 118, + 5, + 68, + 17, + 14, + 6, + 68, + 65, + 165, + 7, + 30, + 8, + 148, + 45, + 105, + 8, + 148, + 54, + 70, + 26, + 12, + 10, + 104, + 16, + 65, + 148, + 216, + 71, + 35, + 9, + 48, + 67, + 161, + 104, + 95, + 216, + 116, + 13, + 66, + 135, + 152, + 67, + 97, + 116, + 176, + 98, + 192, 0, 0, 0, diff --git a/avr/cores/megacommand/resources/R_page_entries.cpp b/avr/cores/megacommand/resources/R_page_entries.cpp index ff2e2a0b8..6a8bad035 100644 --- a/avr/cores/megacommand/resources/R_page_entries.cpp +++ b/avr/cores/megacommand/resources/R_page_entries.cpp @@ -7,7 +7,7 @@ const unsigned char __R_page_entries[] PROGMEM = { 68, 0, 18, - 94, + 78, 24, 15, 223, @@ -18,159 +18,189 @@ const unsigned char __R_page_entries[] PROGMEM = { 69, 176, 82, - 21, - 155, + 19, + 29, + 3, 1, - 23, - 109, + 182, + 22, 16, - 5, + 6, + 219, + 80, + 20, + 70, + 96, + 42, + 123, + 40, + 2, + 22, + 109, + 18, + 6, 251, 82, 79, 85, 84, 69, - 23, - 9, - 145, - 2, - 236, - 76, - 70, - 79, - 69, - 134, + 22, + 1, + 203, + 21, 3, - 219, - 23, - 24, - 5, + 14, 109, + 6, 83, - 45, - 253, + 191, + 20, 80, 32, 69, 68, 73, + 176, 84, - 147, - 23, + 22, + 126, + 7, 4, - 237, 1, 24, - 25, + 21, + 222, + 6, + 76, + 70, + 79, + 194, + 111, + 118, + 22, 5, - 253, - 80, + 22, + 221, + 24, + 91, 73, + 246, 65, 78, 79, 32, - 187, - 77, + 74, + 236, 76, 76, - 23, - 14, + 22, + 242, + 8, + 6, + 219, + 25, 6, - 71, 67, + 183, 72, - 111, - 19, + 18, 77, 65, + 236, 84, - 217, 73, 67, - 47, - 54, + 45, + 29, + 9, 7, - 23, - 54, + 143, + 22, 83, - 119, + 65, + 77, 251, - 78, - 68, + 80, + 76, + 69, 32, 77, - 52, - 118, + 51, + 119, 65, 71, - 151, - 15, + 169, + 247, + 12, 8, 2, - 24, - 183, - 19, - 5, + 22, + 255, 87, 65, - 255, 86, 32, 68, 69, 83, + 236, 73, 71, 78, - 97, - 174, - 216, + 190, + 246, + 18, 9, - 23, - 183, + 22, + 218, 19, + 6, + 222, + 18, 76, 65, - 176, 89, - 143, - 157, + 192, + 114, + 123, + 16, 12, 3, - 253, - 71, + 45, + 251, 82, 69, 86, - 182, - 40, + 38, + 108, 66, - 23, - 7, + 22, + 188, + 17, 13, - 39, - 65, - 236, - 77, + 155, + 91, + 118, 45, 49, - 47, - 38, - 14, - 201, + 45, + 3, 23, - 144, + 178, + 14, + 22, + 97, 50, - 153, - 15, - 16, + 39, + 9, + 98, + 22, 0, 0, 0, 0, 0, - 79, + 9, 255, }; diff --git a/avr/cores/megacommand/resources/ResMan.h b/avr/cores/megacommand/resources/ResMan.h index 8642a5d2d..39e041272 100644 --- a/avr/cores/megacommand/resources/ResMan.h +++ b/avr/cores/megacommand/resources/ResMan.h @@ -1,16 +1,12 @@ -__T_font_default *font_default; -void use_font_default() { font_default = (__T_font_default*) __use_resource(__R_font_default); } -__T_font_elektrothic *font_elektrothic; -void use_font_elektrothic() { font_elektrothic = (__T_font_elektrothic*) __use_resource(__R_font_elektrothic); } -__T_font_tomthumb *font_tomthumb; -void use_font_tomthumb() { font_tomthumb = (__T_font_tomthumb*) __use_resource(__R_font_tomthumb); } __T_icons_boot *icons_boot; void use_icons_boot() { icons_boot = (__T_icons_boot*) __use_resource(__R_icons_boot); } __T_icons_device *icons_device; void use_icons_device() { icons_device = (__T_icons_device*) __use_resource(__R_icons_device); } __T_icons_knob *icons_knob; void use_icons_knob() { icons_knob = (__T_icons_knob*) __use_resource(__R_icons_knob); } +__T_icons_logo *icons_logo; +void use_icons_logo() { icons_logo = (__T_icons_logo*) __use_resource(__R_icons_logo); } __T_icons_page *icons_page; void use_icons_page() { icons_page = (__T_icons_page*) __use_resource(__R_icons_page); } __T_machine_names_long *machine_names_long; @@ -24,6 +20,4 @@ void use_menu_layouts() { menu_layouts = (__T_menu_layouts*) __use_resource(__R_ __T_menu_options *menu_options; void use_menu_options() { menu_options = (__T_menu_options*) __use_resource(__R_menu_options); } __T_page_entries *page_entries; -void use_page_entries() { page_entries = (__T_page_entries*) __use_resource(__R_page_entries); } -__T_tuning *tuning; -void use_tuning() { tuning = (__T_tuning*) __use_resource(__R_tuning); } +void use_page_entries() { page_entries = (__T_page_entries*) __use_resource(__R_page_entries); } diff --git a/avr/cores/megacommand/wiring.c b/avr/cores/megacommand/wiring.c index 932f7a117..743ff1152 100644 --- a/avr/cores/megacommand/wiring.c +++ b/avr/cores/megacommand/wiring.c @@ -48,10 +48,11 @@ ISR(TIMER0_OVF_vect) { // copy these to local variables so they can be stored in registers // (volatile variables must be read from memory on every access) - unsigned long m = timer0_millis; - unsigned char f = timer0_fract; - uint8_t old_bank = switch_ram_bank(0); + uint8_t old_bank = switch_ram_bank(0); + + unsigned long m = timer0_millis; + unsigned char f = timer0_fract; m += MILLIS_INC; f += FRACT_INC; diff --git a/resource/font_default.cpp b/resource/font_default.cpp deleted file mode 100644 index 03212840f..000000000 --- a/resource/font_default.cpp +++ /dev/null @@ -1,263 +0,0 @@ -#include -#include "../gfxfont.h" - -// Standard ASCII 5x7 font -unsigned char font[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0xFF, 0x81, 0x81, 0x81, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x41, 0x41, 0x41, 0x41, 0x41, - 0x41, 0x41, 0x7F, 0x41, 0x41, - 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, - 0x00, 0x18, 0x3C, 0x18, 0x00, - 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, - 0x00, 0x18, 0x24, 0x18, 0x00, - 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, - 0x30, 0x48, 0x3A, 0x06, 0x0E, - 0x26, 0x29, 0x79, 0x29, 0x26, - 0x40, 0x7F, 0x05, 0x05, 0x07, - 0x40, 0x7F, 0x05, 0x25, 0x3F, - 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, - 0x7F, 0x3E, 0x1C, 0x1C, 0x08, - 0x08, 0x1C, 0x1C, 0x3E, 0x7F, - 0x14, 0x22, 0x7F, 0x22, 0x14, - 0x5F, 0x5F, 0x00, 0x5F, 0x5F, - 0x06, 0x09, 0x7F, 0x01, 0x7F, - 0x00, 0x66, 0x89, 0x95, 0x6A, - 0x60, 0x60, 0x60, 0x60, 0x60, - 0x94, 0xA2, 0xFF, 0xA2, 0x94, - 0x08, 0x04, 0x7E, 0x04, 0x08, - 0x10, 0x20, 0x7E, 0x20, 0x10, - 0x08, 0x08, 0x2A, 0x1C, 0x08, - 0x08, 0x1C, 0x2A, 0x08, 0x08, - 0x1E, 0x10, 0x10, 0x10, 0x10, - 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, - 0x30, 0x38, 0x3E, 0x38, 0x30, - 0x06, 0x0E, 0x3E, 0x0E, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x5F, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x07, 0x00, - 0x14, 0x7F, 0x14, 0x7F, 0x14, - 0x24, 0x2A, 0x7F, 0x2A, 0x12, - 0x23, 0x13, 0x08, 0x64, 0x62, - 0x36, 0x49, 0x56, 0x20, 0x50, - 0x00, 0x08, 0x07, 0x03, 0x00, - 0x00, 0x1C, 0x22, 0x41, 0x00, - 0x00, 0x41, 0x22, 0x1C, 0x00, - 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, - 0x08, 0x08, 0x3E, 0x08, 0x08, - 0x00, 0x80, 0x70, 0x30, 0x00, - 0x08, 0x08, 0x08, 0x08, 0x08, - 0x00, 0x00, 0x60, 0x60, 0x00, - 0x20, 0x10, 0x08, 0x04, 0x02, - 0x3E, 0x51, 0x49, 0x45, 0x3E, - 0x00, 0x42, 0x7F, 0x40, 0x00, - 0x72, 0x49, 0x49, 0x49, 0x46, - 0x21, 0x41, 0x49, 0x4D, 0x33, - 0x18, 0x14, 0x12, 0x7F, 0x10, - 0x27, 0x45, 0x45, 0x45, 0x39, - 0x3C, 0x4A, 0x49, 0x49, 0x31, - 0x41, 0x21, 0x11, 0x09, 0x07, - 0x36, 0x49, 0x49, 0x49, 0x36, - 0x46, 0x49, 0x49, 0x29, 0x1E, - 0x00, 0x00, 0x14, 0x00, 0x00, - 0x00, 0x40, 0x34, 0x00, 0x00, - 0x00, 0x08, 0x14, 0x22, 0x41, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x00, 0x41, 0x22, 0x14, 0x08, - 0x02, 0x01, 0x59, 0x09, 0x06, - 0x3E, 0x41, 0x5D, 0x59, 0x4E, - 0x7C, 0x12, 0x11, 0x12, 0x7C, - 0x7F, 0x49, 0x49, 0x49, 0x36, - 0x3E, 0x41, 0x41, 0x41, 0x22, - 0x7F, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x49, 0x49, 0x49, 0x41, - 0x7F, 0x09, 0x09, 0x09, 0x01, - 0x3E, 0x41, 0x41, 0x51, 0x73, - 0x7F, 0x08, 0x08, 0x08, 0x7F, - 0x00, 0x41, 0x7F, 0x41, 0x00, - 0x20, 0x40, 0x41, 0x3F, 0x01, - 0x7F, 0x08, 0x14, 0x22, 0x41, - 0x7F, 0x40, 0x40, 0x40, 0x40, - 0x7F, 0x02, 0x1C, 0x02, 0x7F, - 0x7F, 0x04, 0x08, 0x10, 0x7F, - 0x3E, 0x41, 0x41, 0x41, 0x3E, - 0x7F, 0x09, 0x09, 0x09, 0x06, - 0x3E, 0x41, 0x51, 0x21, 0x5E, - 0x7F, 0x09, 0x19, 0x29, 0x46, - 0x26, 0x49, 0x49, 0x49, 0x32, - 0x03, 0x01, 0x7F, 0x01, 0x03, - 0x3F, 0x40, 0x40, 0x40, 0x3F, - 0x1F, 0x20, 0x40, 0x20, 0x1F, - 0x3F, 0x40, 0x38, 0x40, 0x3F, - 0x63, 0x14, 0x08, 0x14, 0x63, - 0x03, 0x04, 0x78, 0x04, 0x03, - 0x61, 0x59, 0x49, 0x4D, 0x43, - 0x00, 0x7F, 0x41, 0x41, 0x41, - 0x02, 0x04, 0x08, 0x10, 0x20, - 0x00, 0x41, 0x41, 0x41, 0x7F, - 0x04, 0x02, 0x01, 0x02, 0x04, - 0x40, 0x40, 0x40, 0x40, 0x40, - 0x00, 0x03, 0x07, 0x08, 0x00, - 0x20, 0x54, 0x54, 0x78, 0x40, - 0x7F, 0x28, 0x44, 0x44, 0x38, - 0x38, 0x44, 0x44, 0x44, 0x28, - 0x38, 0x44, 0x44, 0x28, 0x7F, - 0x38, 0x54, 0x54, 0x54, 0x18, - 0x00, 0x08, 0x7E, 0x09, 0x02, - 0x18, 0xA4, 0xA4, 0x9C, 0x78, - 0x7F, 0x08, 0x04, 0x04, 0x78, - 0x00, 0x44, 0x7D, 0x40, 0x00, - 0x20, 0x40, 0x40, 0x3D, 0x00, - 0x7F, 0x10, 0x28, 0x44, 0x00, - 0x00, 0x41, 0x7F, 0x40, 0x00, - 0x7C, 0x04, 0x78, 0x04, 0x78, - 0x7C, 0x08, 0x04, 0x04, 0x78, - 0x38, 0x44, 0x44, 0x44, 0x38, - 0xFC, 0x18, 0x24, 0x24, 0x18, - 0x18, 0x24, 0x24, 0x18, 0xFC, - 0x7C, 0x08, 0x04, 0x04, 0x08, - 0x48, 0x54, 0x54, 0x54, 0x24, - 0x04, 0x04, 0x3F, 0x44, 0x24, - 0x3C, 0x40, 0x40, 0x20, 0x7C, - 0x1C, 0x20, 0x40, 0x20, 0x1C, - 0x3C, 0x40, 0x30, 0x40, 0x3C, - 0x44, 0x28, 0x10, 0x28, 0x44, - 0x4C, 0x90, 0x90, 0x90, 0x7C, - 0x44, 0x64, 0x54, 0x4C, 0x44, - 0x00, 0x08, 0x36, 0x41, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, - 0x00, 0x41, 0x36, 0x08, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x02, - 0x3C, 0x26, 0x23, 0x26, 0x3C, - 0x1E, 0xA1, 0xA1, 0x61, 0x12, - 0x3A, 0x40, 0x40, 0x20, 0x7A, - 0x38, 0x54, 0x54, 0x55, 0x59, - 0x21, 0x55, 0x55, 0x79, 0x41, - 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut - 0x21, 0x55, 0x54, 0x78, 0x40, - 0x20, 0x54, 0x55, 0x79, 0x40, - 0x0C, 0x1E, 0x52, 0x72, 0x12, - 0x39, 0x55, 0x55, 0x55, 0x59, - 0x39, 0x54, 0x54, 0x54, 0x59, - 0x39, 0x55, 0x54, 0x54, 0x58, - 0x00, 0x00, 0x45, 0x7C, 0x41, - 0x00, 0x02, 0x45, 0x7D, 0x42, - 0x00, 0x01, 0x45, 0x7C, 0x40, - 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut - 0xF0, 0x28, 0x25, 0x28, 0xF0, - 0x7C, 0x54, 0x55, 0x45, 0x00, - 0x20, 0x54, 0x54, 0x7C, 0x54, - 0x7C, 0x0A, 0x09, 0x7F, 0x49, - 0x32, 0x49, 0x49, 0x49, 0x32, - 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut - 0x32, 0x4A, 0x48, 0x48, 0x30, - 0x3A, 0x41, 0x41, 0x21, 0x7A, - 0x3A, 0x42, 0x40, 0x20, 0x78, - 0x00, 0x9D, 0xA0, 0xA0, 0x7D, - 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut - 0x3D, 0x40, 0x40, 0x40, 0x3D, - 0x3C, 0x24, 0xFF, 0x24, 0x24, - 0x48, 0x7E, 0x49, 0x43, 0x66, - 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, - 0xFF, 0x09, 0x29, 0xF6, 0x20, - 0xC0, 0x88, 0x7E, 0x09, 0x03, - 0x20, 0x54, 0x54, 0x79, 0x41, - 0x00, 0x00, 0x44, 0x7D, 0x41, - 0x30, 0x48, 0x48, 0x4A, 0x32, - 0x38, 0x40, 0x40, 0x22, 0x7A, - 0x00, 0x7A, 0x0A, 0x0A, 0x72, - 0x7D, 0x0D, 0x19, 0x31, 0x7D, - 0x26, 0x29, 0x29, 0x2F, 0x28, - 0x26, 0x29, 0x29, 0x29, 0x26, - 0x30, 0x48, 0x4D, 0x40, 0x20, - 0x38, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x38, - 0x2F, 0x10, 0xC8, 0xAC, 0xBA, - 0x2F, 0x10, 0x28, 0x34, 0xFA, - 0x00, 0x00, 0x7B, 0x00, 0x00, - 0x08, 0x14, 0x2A, 0x14, 0x22, - 0x22, 0x14, 0x2A, 0x14, 0x08, - 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code - 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block - 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block - 0x00, 0x00, 0x00, 0xFF, 0x00, - 0x10, 0x10, 0x10, 0xFF, 0x00, - 0x14, 0x14, 0x14, 0xFF, 0x00, - 0x10, 0x10, 0xFF, 0x00, 0xFF, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x14, 0x14, 0x14, 0xFC, 0x00, - 0x14, 0x14, 0xF7, 0x00, 0xFF, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x14, 0x14, 0xF4, 0x04, 0xFC, - 0x14, 0x14, 0x17, 0x10, 0x1F, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0x1F, 0x00, - 0x10, 0x10, 0x10, 0xF0, 0x00, - 0x00, 0x00, 0x00, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0x1F, 0x10, - 0x10, 0x10, 0x10, 0xF0, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0xFF, 0x10, - 0x00, 0x00, 0x00, 0xFF, 0x14, - 0x00, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0x00, 0x1F, 0x10, 0x17, - 0x00, 0x00, 0xFC, 0x04, 0xF4, - 0x14, 0x14, 0x17, 0x10, 0x17, - 0x14, 0x14, 0xF4, 0x04, 0xF4, - 0x00, 0x00, 0xFF, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x14, 0x14, - 0x14, 0x14, 0xF7, 0x00, 0xF7, - 0x14, 0x14, 0x14, 0x17, 0x14, - 0x10, 0x10, 0x1F, 0x10, 0x1F, - 0x14, 0x14, 0x14, 0xF4, 0x14, - 0x10, 0x10, 0xF0, 0x10, 0xF0, - 0x00, 0x00, 0x1F, 0x10, 0x1F, - 0x00, 0x00, 0x00, 0x1F, 0x14, - 0x00, 0x00, 0x00, 0xFC, 0x14, - 0x00, 0x00, 0xF0, 0x10, 0xF0, - 0x10, 0x10, 0xFF, 0x10, 0xFF, - 0x14, 0x14, 0x14, 0xFF, 0x14, - 0x10, 0x10, 0x10, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0xF0, 0x10, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, - 0xFF, 0xFF, 0xFF, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, - 0x38, 0x44, 0x44, 0x38, 0x44, - 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta - 0x7E, 0x02, 0x02, 0x06, 0x06, - 0x02, 0x7E, 0x02, 0x7E, 0x02, - 0x63, 0x55, 0x49, 0x41, 0x63, - 0x38, 0x44, 0x44, 0x3C, 0x04, - 0x40, 0x7E, 0x20, 0x1E, 0x20, - 0x06, 0x02, 0x7E, 0x02, 0x02, - 0x99, 0xA5, 0xE7, 0xA5, 0x99, - 0x1C, 0x2A, 0x49, 0x2A, 0x1C, - 0x4C, 0x72, 0x01, 0x72, 0x4C, - 0x30, 0x4A, 0x4D, 0x4D, 0x30, - 0x30, 0x48, 0x78, 0x48, 0x30, - 0xBC, 0x62, 0x5A, 0x46, 0x3D, - 0x3E, 0x49, 0x49, 0x49, 0x00, - 0x7E, 0x01, 0x01, 0x01, 0x7E, - 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, - 0x44, 0x44, 0x5F, 0x44, 0x44, - 0x40, 0x51, 0x4A, 0x44, 0x40, - 0x40, 0x44, 0x4A, 0x51, 0x40, - 0x00, 0x00, 0xFF, 0x01, 0x03, - 0xE0, 0x80, 0xFF, 0x00, 0x00, - 0x08, 0x08, 0x6B, 0x6B, 0x08, - 0x36, 0x12, 0x36, 0x24, 0x36, - 0x06, 0x0F, 0x09, 0x0F, 0x06, - 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x10, 0x10, 0x00, - 0x30, 0x40, 0xFF, 0x01, 0x01, - 0x00, 0x1F, 0x01, 0x01, 0x1E, - 0x00, 0x19, 0x1D, 0x17, 0x12, - 0x00, 0x3C, 0x3C, 0x3C, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP -}; - diff --git a/resource/font_elektrothic.cpp b/resource/font_elektrothic.cpp deleted file mode 100644 index 1af7c9407..000000000 --- a/resource/font_elektrothic.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include -#include "../gfxfont.h" - -unsigned char ElektrothicBitmaps[] = { - 0xFF, 0xF3, 0xC0, 0xDE, 0xF7, 0xB0, 0x34, 0x59, 0xFB, 0xF2, 0x8F, 0xFF, - 0xB4, 0x68, 0x11, 0x9F, 0xBE, 0x79, 0xE3, 0xDF, 0x8C, 0x73, 0x3E, 0x8D, - 0xE3, 0xF0, 0x7C, 0x02, 0xE1, 0xFC, 0x5F, 0x33, 0x80, 0x30, 0x78, 0x78, - 0x70, 0x77, 0xDE, 0xCC, 0xFE, 0x72, 0xFF, 0x13, 0x7E, 0xCC, 0xCC, 0xE7, - 0x31, 0x8C, 0xE7, 0x33, 0x33, 0x7E, 0xC8, 0x35, 0xFE, 0xE5, 0x00, 0x30, - 0xCF, 0xFF, 0x30, 0xC0, 0xFF, 0xFC, 0xF0, 0x18, 0xCC, 0x63, 0x31, 0x8C, - 0xE6, 0x00, 0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE, 0xFD, 0xB6, 0xDB, 0xFB, - 0xF0, 0xCF, 0x73, 0x0F, 0xFF, 0xFB, 0xF0, 0xCE, 0x38, 0x3F, 0xFE, 0xCF, - 0x3C, 0xFF, 0x7C, 0x30, 0xC3, 0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFF, 0x7F, - 0xFC, 0x3E, 0xFF, 0x3F, 0xDF, 0xFF, 0xF0, 0xC7, 0x39, 0xCE, 0x30, 0x7B, - 0xFC, 0xDE, 0xFF, 0x3F, 0xDE, 0x7B, 0xFC, 0xFF, 0x7C, 0x3F, 0xFE, 0xF0, - 0x3C, 0xF0, 0x3F, 0xC0, 0x04, 0x7F, 0xB0, 0xF8, 0x70, 0x40, 0xFF, 0xF0, - 0x00, 0xFF, 0xF0, 0x83, 0x87, 0xC3, 0x7F, 0x88, 0x00, 0x77, 0xF6, 0x33, - 0x30, 0x0C, 0x60, 0x1E, 0x3F, 0xBE, 0xFF, 0xFF, 0x7F, 0xBD, 0xFE, 0x7E, - 0x1F, 0x00, 0x1C, 0x0E, 0x07, 0x06, 0xC3, 0x63, 0xB9, 0xFC, 0xFE, 0xE3, - 0x80, 0xFB, 0xFC, 0xFE, 0xFF, 0x3C, 0xFF, 0xF8, 0x3E, 0x3F, 0xB8, 0xF8, - 0x7C, 0x06, 0x0F, 0x8E, 0xFE, 0x3E, 0x00, 0xF9, 0xFB, 0x3E, 0x3C, 0x78, - 0xF3, 0xFE, 0xF8, 0xFF, 0xF1, 0xFF, 0xE3, 0x1F, 0xF8, 0xFF, 0xF1, 0x8F, - 0xFF, 0x18, 0xC0, 0x3E, 0x3F, 0xB8, 0xF8, 0x0C, 0xFE, 0x7F, 0x8E, 0xFE, - 0x3E, 0x00, 0xC7, 0x8F, 0x1F, 0xFF, 0xF8, 0xF1, 0xE3, 0xC6, 0xFF, 0xFF, - 0xC0, 0x0C, 0x30, 0xC3, 0x0C, 0x3C, 0xFF, 0x78, 0xCF, 0x9B, 0x67, 0xCF, - 0x1F, 0x36, 0x66, 0xCE, 0xC6, 0x31, 0x8C, 0x63, 0x1F, 0xF8, 0xE3, 0xF1, - 0xFD, 0xFE, 0xFD, 0x5E, 0xAF, 0x77, 0xBB, 0xC9, 0x80, 0xC7, 0xCF, 0x9F, - 0xBD, 0x7B, 0xF3, 0xE7, 0xC6, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C, 0x1E, 0x0F, - 0x8E, 0xFE, 0x3E, 0x00, 0xFB, 0xFC, 0xF3, 0xFF, 0xEC, 0x30, 0xC0, 0x3E, - 0x3F, 0xB8, 0xFF, 0x3F, 0xDE, 0x7F, 0x9C, 0xFF, 0x3D, 0x80, 0xFB, 0xFC, - 0xF3, 0xFF, 0xEF, 0x36, 0xCC, 0x77, 0xF7, 0xC7, 0x0F, 0x7F, 0x70, 0xFF, - 0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xFF, - 0x78, 0xE3, 0x63, 0x67, 0x76, 0x36, 0x36, 0x3C, 0x1C, 0x1C, 0xE6, 0x76, - 0x66, 0x6E, 0x66, 0xF6, 0x6F, 0xC3, 0xBC, 0x39, 0xC3, 0x9C, 0x39, 0x80, - 0xE3, 0xBB, 0x8F, 0x83, 0x81, 0xC1, 0xF0, 0xD8, 0xE6, 0xE3, 0x80, 0xE7, - 0x66, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xF1, 0x8E, 0x31, - 0xC6, 0x3F, 0xFC, 0x7F, 0x6D, 0xB6, 0xDB, 0xB0, 0xC6, 0x18, 0xC6, 0x18, - 0xC6, 0x38, 0xC0, 0xDD, 0xB6, 0xDB, 0x6F, 0xE0, 0x71, 0xCD, 0xB7, 0xFC, - 0xC3, 0x7E, 0xFF, 0x1E, 0x3C, 0x6F, 0xDF, 0x80, 0xC3, 0x0F, 0xBF, 0xCF, - 0x3C, 0xFF, 0xF8, 0x38, 0xFB, 0x1E, 0x0C, 0x6F, 0x8E, 0x00, 0x06, 0x0D, - 0xFB, 0xFC, 0x78, 0xF1, 0xBF, 0x7E, 0x38, 0xFB, 0x1F, 0xFF, 0xEF, 0x8E, - 0x00, 0x37, 0xFF, 0x66, 0x66, 0x60, 0x3E, 0xFF, 0x1E, 0x3C, 0x6F, 0xDF, - 0xE3, 0xFE, 0xF0, 0xC3, 0x0F, 0xBF, 0xCF, 0x3C, 0xF3, 0xCC, 0xFF, 0xFF, - 0xC0, 0x6D, 0xB6, 0xDB, 0x7F, 0x00, 0xC3, 0x0C, 0xF6, 0xF3, 0xCF, 0xB6, - 0xCC, 0xFF, 0xFF, 0xC0, 0xFB, 0xBF, 0xFC, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, - 0xCC, 0xFB, 0xFC, 0xF3, 0xCF, 0x3C, 0xC0, 0x38, 0xFB, 0x1E, 0x3C, 0x6F, - 0x8E, 0x00, 0xFB, 0xFC, 0xF3, 0xCF, 0xFF, 0xB0, 0xC0, 0x7E, 0xFF, 0x1E, - 0x3C, 0x7F, 0xDF, 0x83, 0x06, 0xFF, 0x6D, 0xB0, 0x77, 0xF0, 0xE1, 0xFD, - 0xC0, 0x66, 0xFF, 0x66, 0x66, 0x60, 0xCF, 0x3C, 0xF3, 0xCF, 0xF7, 0xC0, - 0xC6, 0xD9, 0xB3, 0x63, 0x87, 0x0E, 0x00, 0xCC, 0xD3, 0x36, 0xF9, 0xFE, - 0x7B, 0x8C, 0xE3, 0x30, 0xE6, 0x7C, 0x38, 0x38, 0x3C, 0x6E, 0xE7, 0xC6, - 0xD9, 0xB3, 0x63, 0x87, 0x0C, 0x18, 0x70, 0xFF, 0xC4, 0x66, 0x7F, 0xE0, - 0x77, 0x66, 0x6E, 0xE6, 0x66, 0x77, 0xFF, 0xFF, 0xF0, 0xEE, 0x66, 0x67, - 0x76, 0x66, 0xEE, 0xE7, 0xF0}; - -/* {offset, width, height, advance cursor, x offset, y offset} */ -GFXglyph ElektrothicGlyphs[] = { - {0, 0, 0, 4, 0, 1} // ' ' - , - {0, 2, 9, 4, 1, -8} // '!' - , - {3, 5, 5, 6, 0, -5} // '"' - , - {6, 7, 9, 7, 0, -8} // '#' - , - {14, 5, 11, 7, 1, -9} // '$' - , - {21, 10, 9, 11, 0, -8} // '%' - , - {33, 8, 9, 9, 1, -8} // '&' - , - {42, 2, 4, 3, 0, -8} // ''' - , - {43, 4, 12, 6, 1, -8} // '(' - , - {49, 4, 12, 6, 1, -8} // ')' - , - {55, 5, 5, 8, 2, -8} // '*' - , - {59, 6, 6, 7, 1, -5} // '+' - , - {64, 2, 4, 4, 1, -1} // ',' - , - {65, 3, 2, 3, 0, -3} // '-' - , - {66, 2, 2, 4, 1, -1} // '.' - , - {67, 5, 10, 7, 1, -8} // '/' - , - {74, 6, 8, 7, 0, -8} // '0' - , - {80, 3, 8, 4, 0, -8} // '1' - , - {83, 6, 8, 7, 0, -8} // '2' - , - {89, 6, 8, 7, 0, -8} // '3' - , - {95, 6, 8, 7, 0, -8} // '4' - , - {101, 6, 8, 7, 0, -8} // '5' - , - {107, 6, 8, 7, 0, -8} // '6' - , - {113, 6, 8, 7, 0, -8} // '7' - , - {119, 6, 8, 7, 0, -8} // '8' - , - {125, 6, 8, 7, 0, -8} // '9' - , - {131, 2, 7, 4, 1, -6} // ':' - , - {133, 2, 9, 4, 1, -6} // ';' - , - {136, 6, 7, 7, 1, -6} // '<' - , - {142, 6, 6, 7, 1, -5} // '=' - , - {156, 4, 5, 8, 0, -5} // '>' - , - {153, 5, 9, 7, 1, -8} // '?' - , - {159, 9, 9, 10, 0, -8} // '@' - , - {170, 9, 9, 9, 0, -8} // 'A' - , - {181, 6, 9, 8, 1, -8} // 'B' - , - {188, 9, 9, 10, 1, -8} // 'C' - , - {199, 7, 9, 9, 1, -8} // 'D' - , - {207, 5, 9, 6, 1, -8} // 'E' - , - {213, 5, 9, 6, 1, -8} // 'F' - , - {219, 9, 9, 10, 1, -8} // 'G' - , - {230, 7, 9, 9, 1, -8} // 'H' - , - {238, 2, 9, 4, 1, -8} // 'I' - , - {241, 6, 9, 7, 0, -8} // 'J' - , - {248, 7, 9, 8, 1, -8} // 'K' - , - {256, 5, 9, 6, 1, -8} // 'L' - , - {262, 9, 9, 11, 1, -8} // 'M' - , - {273, 7, 9, 9, 1, -8} // 'N' - , - {281, 9, 9, 10, 0, -8} // 'O' - , - {292, 6, 9, 8, 1, -8} // 'P' - , - {299, 9, 9, 11, 1, -8} // 'Q' - , - {310, 6, 9, 8, 1, -8} // 'R' - , - {317, 5, 9, 7, 1, -8} // 'S' - , - {323, 6, 9, 6, 0, -8} // 'T' - , - {330, 6, 9, 8, 1, -8} // 'U' - , - {337, 8, 9, 9, 0, -8} // 'V' - , - {346, 12, 9, 12, 0, -8} // 'W' - , - {360, 9, 9, 9, 0, -8} // 'X' - , - {371, 8, 9, 8, 0, -8} // 'Y' - , - {380, 6, 9, 6, 0, -8} // 'Z' - , - {387, 3, 12, 6, 1, -8} // '[' - , - {392, 5, 10, 7, 1, -8} // '\' - , - {399, 3, 12, 5, 1, -8} // ']' - , - {404, 6, 4, 7, 1, -8} // '^' - , - {407, 6, 1, 6, 0, 2} // '_' - , - {408, 4, 2, 7, 1, -9} // '`' - , - {409, 7, 7, 8, 0, -6} // 'a' - , - {416, 6, 9, 8, 1, -8} // 'b' - , - {423, 7, 7, 8, 0, -6} // 'c' - , - {430, 7, 9, 8, 0, -8} // 'd' - , - {438, 7, 7, 8, 0, -6} // 'e' - , - {445, 4, 9, 4, 0, -8} // 'f' - , - {450, 7, 10, 8, 0, -6} // 'g' - , - {459, 6, 9, 8, 1, -8} // 'h' - , - {466, 2, 9, 3, 1, -8} // 'i' - , - {469, 3, 11, 4, 0, -8} // 'j' - , - {474, 6, 9, 7, 1, -8} // 'k' - , - {481, 2, 9, 4, 1, -8} // 'l' - , - {484, 10, 7, 12, 1, -6} // 'm' - , - {493, 6, 7, 8, 1, -6} // 'n' - , - {499, 7, 7, 8, 0, -6} // 'o' - , - {506, 6, 9, 8, 1, -6} // 'p' - , - {513, 7, 9, 8, 0, -6} // 'q' - , - {521, 4, 7, 4, 1, -6} // 'r' - , - {524, 5, 7, 6, 0, -6} // 's' - , - {529, 4, 9, 4, 0, -8} // 't' - , - {534, 6, 7, 8, 1, -6} // 'u' - , - {540, 7, 7, 7, 0, -6} // 'v' - , - {547, 10, 7, 10, 0, -6} // 'w' - , - {556, 8, 7, 8, 0, -6} // 'x' - , - {563, 7, 9, 7, 0, -6} // 'y' - , - {571, 5, 7, 5, 0, -6} // 'z' - , - {576, 4, 12, 7, 1, -8} // '{' - , - {582, 2, 10, 7, 2, -8} // '|' - , - {585, 4, 12, 6, 1, -8} // '}' - , - {591, 6, 2, 7, 1, -3} // '~' -}; - diff --git a/resource/font_tomthumb.cpp b/resource/font_tomthumb.cpp deleted file mode 100644 index b2398cf77..000000000 --- a/resource/font_tomthumb.cpp +++ /dev/null @@ -1,421 +0,0 @@ -#include -#include "../gfxfont.h" - -unsigned char TomThumbBitmaps[] = { - 0x00, /* 0x20 space */ - 0x80, 0x80, 0x80, 0x00, 0x80, /* 0x21 exclam */ - 0xA0, 0xA0, /* 0x22 quotedbl */ - 0xA0, 0xE0, 0xA0, 0xE0, 0xA0, /* 0x23 numbersign */ - 0x60, 0xC0, 0x60, 0xC0, 0x40, /* 0x24 dollar */ - 0x80, 0x20, 0x40, 0x80, 0x20, /* 0x25 percent */ - 0xC0, 0xC0, 0xE0, 0xA0, 0x60, /* 0x26 ampersand */ - 0x80, 0x80, /* 0x27 quotesingle */ - 0x40, 0x80, 0x80, 0x80, 0x40, /* 0x28 parenleft */ - 0x80, 0x40, 0x40, 0x40, 0x80, /* 0x29 parenright */ - 0xA0, 0x40, 0xA0, /* 0x2A asterisk */ - 0x40, 0xE0, 0x40, /* 0x2B plus */ - 0x40, 0x80, /* 0x2C comma */ - 0xE0, /* 0x2D hyphen */ - 0x80, /* 0x2E period */ - 0x20, 0x20, 0x40, 0x80, 0x80, /* 0x2F slash */ - 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, /* 0x30 zero */ //Edited for aesthetics - 0xC0, 0x40, 0x40, 0x40, 0xE0, /* 0x31 one */ //Edited for aesthetics - 0xE0, 0x20, 0xE0, 0x80, 0xE0, /* 0x32 two */ //Edited for aesthetics - 0xE0, 0x20, 0xE0, 0x20, 0xE0, /* 0x33 three */ //Edited for aesthetics - 0xA0, 0xA0, 0xE0, 0x20, 0x20, /* 0x34 four */ - 0xE0, 0x80, 0xE0, 0x20, 0xE0, /* 0x35 five */ //Edited for aesthetics - 0xE0, 0x80, 0xE0, 0xA0, 0xE0, /* 0x36 six */ //Edited for aesthetics - 0xE0, 0x20, 0x20, 0x20, 0x20, /* 0x37 seven */ //Edited for aesthetics - 0xE0, 0xA0, 0xE0, 0xA0, 0xE0, /* 0x38 eight */ - 0xE0, 0xA0, 0xE0, 0x20, 0xE0, /* 0x39 nine */ //Edited for aesthetics - 0x80, 0x00, 0x80, /* 0x3A colon */ - 0x40, 0x00, 0x40, 0x80, /* 0x3B semicolon */ //edited - 0x00, 0x40, 0x80, 0x40, 0x00, /* 0x3C less */ - 0xE0, 0x00, 0xE0, /* 0x3D equal */ - 0x00, 0x40, 0x20, 0x40, 0x00, /* 0x3E greater */ //edited - 0xE0, 0x20, 0x40, 0x00, 0x40, /* 0x3F question */ - 0x40, 0xA0, 0xE0, 0x80, 0x60, /* 0x40 at */ - 0x40, 0xA0, 0xE0, 0xA0, 0xA0, /* 0x41 A */ - 0xC0, 0xA0, 0xC0, 0xA0, 0xC0, /* 0x42 B */ - 0x60, 0x80, 0x80, 0x80, 0x60, /* 0x43 C */ - 0xC0, 0xA0, 0xA0, 0xA0, 0xC0, /* 0x44 D */ - 0xE0, 0x80, 0xE0, 0x80, 0xE0, /* 0x45 E */ - 0xE0, 0x80, 0xE0, 0x80, 0x80, /* 0x46 F */ - 0x60, 0x80, 0xA0, 0xA0, 0x60, /* 0x47 G */ //Edited for aesthetics - 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, /* 0x48 H */ - 0xE0, 0x40, 0x40, 0x40, 0xE0, /* 0x49 I */ - 0x20, 0x20, 0x20, 0xA0, 0x40, /* 0x4A J */ - 0xA0, 0xA0, 0xC0, 0xA0, 0xA0, /* 0x4B K */ - 0x80, 0x80, 0x80, 0x80, 0xE0, /* 0x4C L */ - 0xA0, 0xE0, 0xE0, 0xA0, 0xA0, /* 0x4D M */ - 0xC0, 0xA0, 0xA0, 0xA0, 0xA0, /* 0x4E N */ //Edited for improved legibility - 0x40, 0xA0, 0xA0, 0xA0, 0x40, /* 0x4F O */ - 0xC0, 0xA0, 0xC0, 0x80, 0x80, /* 0x50 P */ - 0x40, 0xA0, 0xA0, 0xE0, 0x60, /* 0x51 Q */ - 0xE0, 0xA0, 0xE0, 0xC0, 0xA0, /* 0x52 R */ - 0xE0, 0x80, 0xE0, 0x20, 0xE0, /* 0x53 S */ //Edited - 0xE0, 0x40, 0x40, 0x40, 0x40, /* 0x54 T */ - 0xA0, 0xA0, 0xA0, 0xA0, 0x60, /* 0x55 U */ - 0xA0, 0xA0, 0xA0, 0x40, 0x40, /* 0x56 V */ - 0xA0, 0xA0, 0xE0, 0xE0, 0xA0, /* 0x57 W */ - 0xA0, 0xA0, 0x40, 0xA0, 0xA0, /* 0x58 X */ - 0xA0, 0xA0, 0xE0, 0x20, 0xE0, /* 0x59 Y */ - 0xE0, 0x20, 0x40, 0x80, 0xE0, /* 0x5A Z */ - 0xE0, 0x80, 0x80, 0x80, 0xE0, /* 0x5B bracketleft */ - 0x80, 0x40, 0x20, /* 0x5C backslash */ - 0xE0, 0x20, 0x20, 0x20, 0xE0, /* 0x5D bracketright */ - 0x40, 0xA0, /* 0x5E asciicircum */ - 0xE0, /* 0x5F underscore */ - 0x00, 0x00, /* 0x60 space white */ - 0xC0, 0x60, 0xA0, 0xE0, /* 0x61 a */ - 0x80, 0xC0, 0xA0, 0xA0, 0xC0, /* 0x62 b */ - 0x60, 0x80, 0x80, 0x60, /* 0x63 c */ - 0x20, 0x60, 0xA0, 0xA0, 0x60, /* 0x64 d */ - 0x60, 0xA0, 0xC0, 0x60, /* 0x65 e */ - 0x20, 0x40, 0xE0, 0x40, 0x40, /* 0x66 f */ - 0x60, 0xA0, 0xE0, 0x20, 0x40, /* 0x67 g */ - 0x80, 0xC0, 0xA0, 0xA0, 0xA0, /* 0x68 h */ - 0x80, 0x00, 0x80, 0x80, 0x80, /* 0x69 i */ - 0x20, 0x00, 0x20, 0x20, 0xA0, 0x40, /* 0x6A j */ - 0x80, 0xA0, 0xC0, 0xC0, 0xA0, /* 0x6B k */ - 0xC0, 0x40, 0x40, 0x40, 0xE0, /* 0x6C l */ - 0xE0, 0xE0, 0xE0, 0xA0, /* 0x6D m */ - 0xC0, 0xA0, 0xA0, 0xA0, /* 0x6E n */ - 0x40, 0xA0, 0xA0, 0x40, /* 0x6F o */ - 0xC0, 0xA0, 0xA0, 0xC0, 0x80, /* 0x70 p */ - 0x60, 0xA0, 0xA0, 0x60, 0x20, /* 0x71 q */ - 0x60, 0x80, 0x80, 0x80, /* 0x72 r */ - 0x60, 0xC0, 0x60, 0xC0, /* 0x73 s */ - 0x40, 0xE0, 0x40, 0x40, 0x60, /* 0x74 t */ - 0xA0, 0xA0, 0xA0, 0x60, /* 0x75 u */ - 0xA0, 0xA0, 0xE0, 0x40, /* 0x76 v */ - 0xA0, 0xE0, 0xE0, 0xE0, /* 0x77 w */ - 0xA0, 0x40, 0x40, 0xA0, /* 0x78 x */ - 0xA0, 0xA0, 0x60, 0x20, 0x40, /* 0x79 y */ - 0xE0, 0x60, 0xC0, 0xE0, /* 0x7A z */ - 0x60, 0x40, 0x80, 0x40, 0x60, /* 0x7B braceleft */ - 0x80, 0x80, 0x00, 0x80, 0x80, /* 0x7C bar */ - 0xC0, 0x40, 0x20, 0x40, 0xC0, /* 0x7D braceright */ - 0x60, 0xC0, /* 0x7E asciitilde */ -#if (TOMTHUMB_USE_EXTENDED) - 0x80, 0x00, 0x80, 0x80, 0x80, /* 0xA1 exclamdown */ - 0x40, 0xE0, 0x80, 0xE0, 0x40, /* 0xA2 cent */ - 0x60, 0x40, 0xE0, 0x40, 0xE0, /* 0xA3 sterling */ - 0xA0, 0x40, 0xE0, 0x40, 0xA0, /* 0xA4 currency */ - 0xA0, 0xA0, 0x40, 0xE0, 0x40, /* 0xA5 yen */ - 0x80, 0x80, 0x00, 0x80, 0x80, /* 0xA6 brokenbar */ - 0x60, 0x40, 0xA0, 0x40, 0xC0, /* 0xA7 section */ - 0xA0, /* 0xA8 dieresis */ - 0x60, 0x80, 0x60, /* 0xA9 copyright */ - 0x60, 0xA0, 0xE0, 0x00, 0xE0, /* 0xAA ordfeminine */ - 0x40, 0x80, 0x40, /* 0xAB guillemotleft */ - 0xE0, 0x20, /* 0xAC logicalnot */ - 0xC0, /* 0xAD softhyphen */ - 0xC0, 0xC0, 0xA0, /* 0xAE registered */ - 0xE0, /* 0xAF macron */ - 0x40, 0xA0, 0x40, /* 0xB0 degree */ - 0x40, 0xE0, 0x40, 0x00, 0xE0, /* 0xB1 plusminus */ - 0xC0, 0x40, 0x60, /* 0xB2 twosuperior */ - 0xE0, 0x60, 0xE0, /* 0xB3 threesuperior */ - 0x40, 0x80, /* 0xB4 acute */ - 0xA0, 0xA0, 0xA0, 0xC0, 0x80, /* 0xB5 mu */ - 0x60, 0xA0, 0x60, 0x60, 0x60, /* 0xB6 paragraph */ - 0xE0, 0xE0, 0xE0, /* 0xB7 periodcentered */ - 0x40, 0x20, 0xC0, /* 0xB8 cedilla */ - 0x80, 0x80, 0x80, /* 0xB9 onesuperior */ - 0x40, 0xA0, 0x40, 0x00, 0xE0, /* 0xBA ordmasculine */ - 0x80, 0x40, 0x80, /* 0xBB guillemotright */ - 0x80, 0x80, 0x00, 0x60, 0x20, /* 0xBC onequarter */ - 0x80, 0x80, 0x00, 0xC0, 0x60, /* 0xBD onehalf */ - 0xC0, 0xC0, 0x00, 0x60, 0x20, /* 0xBE threequarters */ - 0x40, 0x00, 0x40, 0x80, 0xE0, /* 0xBF questiondown */ - 0x40, 0x20, 0x40, 0xE0, 0xA0, /* 0xC0 Agrave */ - 0x40, 0x80, 0x40, 0xE0, 0xA0, /* 0xC1 Aacute */ - 0xE0, 0x00, 0x40, 0xE0, 0xA0, /* 0xC2 Acircumflex */ - 0x60, 0xC0, 0x40, 0xE0, 0xA0, /* 0xC3 Atilde */ - 0xA0, 0x40, 0xA0, 0xE0, 0xA0, /* 0xC4 Adieresis */ - 0xC0, 0xC0, 0xA0, 0xE0, 0xA0, /* 0xC5 Aring */ - 0x60, 0xC0, 0xE0, 0xC0, 0xE0, /* 0xC6 AE */ - 0x60, 0x80, 0x80, 0x60, 0x20, 0x40, /* 0xC7 Ccedilla */ - 0x40, 0x20, 0xE0, 0xC0, 0xE0, /* 0xC8 Egrave */ - 0x40, 0x80, 0xE0, 0xC0, 0xE0, /* 0xC9 Eacute */ - 0xE0, 0x00, 0xE0, 0xC0, 0xE0, /* 0xCA Ecircumflex */ - 0xA0, 0x00, 0xE0, 0xC0, 0xE0, /* 0xCB Edieresis */ - 0x40, 0x20, 0xE0, 0x40, 0xE0, /* 0xCC Igrave */ - 0x40, 0x80, 0xE0, 0x40, 0xE0, /* 0xCD Iacute */ - 0xE0, 0x00, 0xE0, 0x40, 0xE0, /* 0xCE Icircumflex */ - 0xA0, 0x00, 0xE0, 0x40, 0xE0, /* 0xCF Idieresis */ - 0xC0, 0xA0, 0xE0, 0xA0, 0xC0, /* 0xD0 Eth */ - 0xC0, 0x60, 0xA0, 0xE0, 0xA0, /* 0xD1 Ntilde */ - 0x40, 0x20, 0xE0, 0xA0, 0xE0, /* 0xD2 Ograve */ - 0x40, 0x80, 0xE0, 0xA0, 0xE0, /* 0xD3 Oacute */ - 0xE0, 0x00, 0xE0, 0xA0, 0xE0, /* 0xD4 Ocircumflex */ - 0xC0, 0x60, 0xE0, 0xA0, 0xE0, /* 0xD5 Otilde */ - 0xA0, 0x00, 0xE0, 0xA0, 0xE0, /* 0xD6 Odieresis */ - 0xA0, 0x40, 0xA0, /* 0xD7 multiply */ - 0x60, 0xA0, 0xE0, 0xA0, 0xC0, /* 0xD8 Oslash */ - 0x80, 0x40, 0xA0, 0xA0, 0xE0, /* 0xD9 Ugrave */ - 0x20, 0x40, 0xA0, 0xA0, 0xE0, /* 0xDA Uacute */ - 0xE0, 0x00, 0xA0, 0xA0, 0xE0, /* 0xDB Ucircumflex */ - 0xA0, 0x00, 0xA0, 0xA0, 0xE0, /* 0xDC Udieresis */ - 0x20, 0x40, 0xA0, 0xE0, 0x40, /* 0xDD Yacute */ - 0x80, 0xE0, 0xA0, 0xE0, 0x80, /* 0xDE Thorn */ - 0x60, 0xA0, 0xC0, 0xA0, 0xC0, 0x80, /* 0xDF germandbls */ - 0x40, 0x20, 0x60, 0xA0, 0xE0, /* 0xE0 agrave */ - 0x40, 0x80, 0x60, 0xA0, 0xE0, /* 0xE1 aacute */ - 0xE0, 0x00, 0x60, 0xA0, 0xE0, /* 0xE2 acircumflex */ - 0x60, 0xC0, 0x60, 0xA0, 0xE0, /* 0xE3 atilde */ - 0xA0, 0x00, 0x60, 0xA0, 0xE0, /* 0xE4 adieresis */ - 0x60, 0x60, 0x60, 0xA0, 0xE0, /* 0xE5 aring */ - 0x60, 0xE0, 0xE0, 0xC0, /* 0xE6 ae */ - 0x60, 0x80, 0x60, 0x20, 0x40, /* 0xE7 ccedilla */ - 0x40, 0x20, 0x60, 0xE0, 0x60, /* 0xE8 egrave */ - 0x40, 0x80, 0x60, 0xE0, 0x60, /* 0xE9 eacute */ - 0xE0, 0x00, 0x60, 0xE0, 0x60, /* 0xEA ecircumflex */ - 0xA0, 0x00, 0x60, 0xE0, 0x60, /* 0xEB edieresis */ - 0x80, 0x40, 0x80, 0x80, 0x80, /* 0xEC igrave */ - 0x40, 0x80, 0x40, 0x40, 0x40, /* 0xED iacute */ - 0xE0, 0x00, 0x40, 0x40, 0x40, /* 0xEE icircumflex */ - 0xA0, 0x00, 0x40, 0x40, 0x40, /* 0xEF idieresis */ - 0x60, 0xC0, 0x60, 0xA0, 0x60, /* 0xF0 eth */ - 0xC0, 0x60, 0xC0, 0xA0, 0xA0, /* 0xF1 ntilde */ - 0x40, 0x20, 0x40, 0xA0, 0x40, /* 0xF2 ograve */ - 0x40, 0x80, 0x40, 0xA0, 0x40, /* 0xF3 oacute */ - 0xE0, 0x00, 0x40, 0xA0, 0x40, /* 0xF4 ocircumflex */ - 0xC0, 0x60, 0x40, 0xA0, 0x40, /* 0xF5 otilde */ - 0xA0, 0x00, 0x40, 0xA0, 0x40, /* 0xF6 odieresis */ - 0x40, 0x00, 0xE0, 0x00, 0x40, /* 0xF7 divide */ - 0x60, 0xE0, 0xA0, 0xC0, /* 0xF8 oslash */ - 0x80, 0x40, 0xA0, 0xA0, 0x60, /* 0xF9 ugrave */ - 0x20, 0x40, 0xA0, 0xA0, 0x60, /* 0xFA uacute */ - 0xE0, 0x00, 0xA0, 0xA0, 0x60, /* 0xFB ucircumflex */ - 0xA0, 0x00, 0xA0, 0xA0, 0x60, /* 0xFC udieresis */ - 0x20, 0x40, 0xA0, 0x60, 0x20, 0x40, /* 0xFD yacute */ - 0x80, 0xC0, 0xA0, 0xC0, 0x80, /* 0xFE thorn */ - 0xA0, 0x00, 0xA0, 0x60, 0x20, 0x40, /* 0xFF ydieresis */ - 0x00, /* 0x11D gcircumflex */ - 0x60, 0xC0, 0xE0, 0xC0, 0x60, /* 0x152 OE */ - 0x60, 0xE0, 0xC0, 0xE0, /* 0x153 oe */ - 0xA0, 0x60, 0xC0, 0x60, 0xC0, /* 0x160 Scaron */ - 0xA0, 0x60, 0xC0, 0x60, 0xC0, /* 0x161 scaron */ - 0xA0, 0x00, 0xA0, 0x40, 0x40, /* 0x178 Ydieresis */ - 0xA0, 0xE0, 0x60, 0xC0, 0xE0, /* 0x17D Zcaron */ - 0xA0, 0xE0, 0x60, 0xC0, 0xE0, /* 0x17E zcaron */ - 0x00, /* 0xEA4 uni0EA4 */ - 0x00, /* 0x13A0 uni13A0 */ - 0x80, /* 0x2022 bullet */ - 0xA0, /* 0x2026 ellipsis */ - 0x60, 0xE0, 0xE0, 0xC0, 0x60, /* 0x20AC Euro */ - 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, /* 0xFFFD uniFFFD */ -#endif /* (TOMTHUMB_USE_EXTENDED) */ - }; - -/* {offset, width, height, advance cursor, x offset, y offset} */ -GFXglyph TomThumbGlyphs[] = { - { 0, 8, 1, 2, 0, -5 }, /* 0x20 space */ - { 1, 8, 5, 2, 0, -5 }, /* 0x21 exclam */ - { 6, 8, 2, 4, 0, -5 }, /* 0x22 quotedbl */ - { 8, 8, 5, 4, 0, -5 }, /* 0x23 numbersign */ - { 13, 8, 5, 4, 0, -5 }, /* 0x24 dollar */ - { 18, 8, 5, 4, 0, -5 }, /* 0x25 percent */ - { 23, 8, 5, 4, 0, -5 }, /* 0x26 ampersand */ - { 28, 8, 2, 2, 0, -5 }, /* 0x27 quotesingle */ - { 30, 8, 5, 3, 0, -5 }, /* 0x28 parenleft */ - { 35, 8, 5, 3, 0, -5 }, /* 0x29 parenright */ - { 40, 8, 3, 4, 0, -5 }, /* 0x2A asterisk */ - { 43, 8, 3, 4, 0, -4 }, /* 0x2B plus */ - { 46, 8, 2, 3, 0, -2 }, /* 0x2C comma */ - { 48, 8, 1, 4, 0, -3 }, /* 0x2D hyphen */ - { 49, 8, 1, 2, 0, -1 }, /* 0x2E period */ - { 50, 8, 5, 4, 0, -5 }, /* 0x2F slash */ - { 55, 8, 5, 4, 0, -5 }, /* 0x30 zero */ - { 60, 8, 5, 4, 0, -5 }, /* 0x31 one */ //Spacing improved - { 65, 8, 5, 4, 0, -5 }, /* 0x32 two */ - { 70, 8, 5, 4, 0, -5 }, /* 0x33 three */ - { 75, 8, 5, 4, 0, -5 }, /* 0x34 four */ - { 80, 8, 5, 4, 0, -5 }, /* 0x35 five */ - { 85, 8, 5, 4, 0, -5 }, /* 0x36 six */ - { 90, 8, 5, 4, 0, -5 }, /* 0x37 seven */ - { 95, 8, 5, 4, 0, -5 }, /* 0x38 eight */ - { 100, 8, 5, 4, 0, -5 }, /* 0x39 nine */ - { 105, 8, 3, 2, 0, -4 }, /* 0x3A colon */ - { 108, 8, 4, 3, 0, -4 }, /* 0x3B semicolon */ - { 112, 8, 5, 4, 0, -5 }, /* 0x3C less */ - { 117, 8, 3, 4, 0, -4 }, /* 0x3D equal */ - { 120, 8, 5, 4, 0, -5 }, /* 0x3E greater */ - { 125, 8, 5, 4, 0, -5 }, /* 0x3F question */ - { 130, 8, 5, 4, 0, -5 }, /* 0x40 at */ - { 135, 8, 5, 4, 0, -5 }, /* 0x41 A */ - { 140, 8, 5, 4, 0, -5 }, /* 0x42 B */ - { 145, 8, 5, 4, 0, -5 }, /* 0x43 C */ - { 150, 8, 5, 4, 0, -5 }, /* 0x44 D */ - { 155, 8, 5, 4, 0, -5 }, /* 0x45 E */ - { 160, 8, 5, 4, 0, -5 }, /* 0x46 F */ - { 165, 8, 5, 4, 0, -5 }, /* 0x47 G */ - { 170, 8, 5, 4, 0, -5 }, /* 0x48 H */ - { 175, 8, 5, 4, 0, -5 }, /* 0x49 I */ - { 180, 8, 5, 4, 0, -5 }, /* 0x4A J */ - { 185, 8, 5, 4, 0, -5 }, /* 0x4B K */ - { 190, 8, 5, 4, 0, -5 }, /* 0x4C L */ - { 195, 8, 5, 4, 0, -5 }, /* 0x4D M */ - { 200, 8, 5, 4, 0, -5 }, /* 0x4E N */ - { 205, 8, 5, 4, 0, -5 }, /* 0x4F O */ - { 210, 8, 5, 4, 0, -5 }, /* 0x50 P */ - { 215, 8, 5, 4, 0, -5 }, /* 0x51 Q */ - { 220, 8, 5, 4, 0, -5 }, /* 0x52 R */ - { 225, 8, 5, 4, 0, -5 }, /* 0x53 S */ - { 230, 8, 5, 4, 0, -5 }, /* 0x54 T */ - { 235, 8, 5, 4, 0, -5 }, /* 0x55 U */ - { 240, 8, 5, 4, 0, -5 }, /* 0x56 V */ - { 245, 8, 5, 4, 0, -5 }, /* 0x57 W */ - { 250, 8, 5, 4, 0, -5 }, /* 0x58 X */ - { 255, 8, 5, 4, 0, -5 }, /* 0x59 Y */ - { 260, 8, 5, 4, 0, -5 }, /* 0x5A Z */ - { 265, 8, 5, 4, 0, -5 }, /* 0x5B bracketleft */ - { 270, 8, 3, 4, 0, -4 }, /* 0x5C backslash */ - { 273, 8, 5, 4, 0, -5 }, /* 0x5D bracketright */ - { 278, 8, 2, 4, 0, -5 }, /* 0x5E asciicircum */ - { 280, 8, 1, 4, 0, -1 }, /* 0x5F underscore */ - { 281, 8, 1, 4, 0, -5 }, /* 0x60 space wide */ - { 283, 8, 4, 4, 0, -4 }, /* 0x61 a */ - { 287, 8, 5, 4, 0, -5 }, /* 0x62 b */ - { 292, 8, 4, 4, 0, -4 }, /* 0x63 c */ - { 296, 8, 5, 4, 0, -5 }, /* 0x64 d */ - { 301, 8, 4, 4, 0, -4 }, /* 0x65 e */ - { 305, 8, 5, 4, 0, -5 }, /* 0x66 f */ - { 310, 8, 5, 4, 0, -4 }, /* 0x67 g */ - { 315, 8, 5, 4, 0, -5 }, /* 0x68 h */ - { 320, 8, 5, 2, 0, -5 }, /* 0x69 i */ - { 325, 8, 6, 4, 0, -5 }, /* 0x6A j */ - { 331, 8, 5, 4, 0, -5 }, /* 0x6B k */ - { 336, 8, 5, 4, 0, -5 }, /* 0x6C l */ - { 341, 8, 4, 4, 0, -4 }, /* 0x6D m */ - { 345, 8, 4, 4, 0, -4 }, /* 0x6E n */ - { 349, 8, 4, 4, 0, -4 }, /* 0x6F o */ - { 353, 8, 5, 4, 0, -4 }, /* 0x70 p */ - { 358, 8, 5, 4, 0, -4 }, /* 0x71 q */ - { 363, 8, 4, 4, 0, -4 }, /* 0x72 r */ - { 367, 8, 4, 4, 0, -4 }, /* 0x73 s */ - { 371, 8, 5, 4, 0, -5 }, /* 0x74 t */ - { 376, 8, 4, 4, 0, -4 }, /* 0x75 u */ - { 380, 8, 4, 4, 0, -4 }, /* 0x76 v */ - { 384, 8, 4, 4, 0, -4 }, /* 0x77 w */ - { 388, 8, 4, 4, 0, -4 }, /* 0x78 x */ - { 392, 8, 5, 4, 0, -4 }, /* 0x79 y */ - { 397, 8, 4, 4, 0, -4 }, /* 0x7A z */ - { 401, 8, 5, 4, 0, -5 }, /* 0x7B braceleft */ - { 406, 8, 5, 2, 0, -5 }, /* 0x7C bar */ - { 411, 8, 5, 4, 0, -5 }, /* 0x7D braceright */ - { 416, 8, 2, 4, 0, -5 }, /* 0x7E asciitilde */ -#if (TOMTHUMB_USE_EXTENDED) - { 418, 8, 5, 2, 0, -5 }, /* 0xA1 exclamdown */ - { 423, 8, 5, 4, 0, -5 }, /* 0xA2 cent */ - { 428, 8, 5, 4, 0, -5 }, /* 0xA3 sterling */ - { 433, 8, 5, 4, 0, -5 }, /* 0xA4 currency */ - { 438, 8, 5, 4, 0, -5 }, /* 0xA5 yen */ - { 443, 8, 5, 2, 0, -5 }, /* 0xA6 brokenbar */ - { 448, 8, 5, 4, 0, -5 }, /* 0xA7 section */ - { 453, 8, 1, 4, 0, -5 }, /* 0xA8 dieresis */ - { 454, 8, 3, 4, 0, -5 }, /* 0xA9 copyright */ - { 457, 8, 5, 4, 0, -5 }, /* 0xAA ordfeminine */ - { 462, 8, 3, 3, 0, -5 }, /* 0xAB guillemotleft */ - { 465, 8, 2, 4, 0, -4 }, /* 0xAC logicalnot */ - { 467, 8, 1, 3, 0, -3 }, /* 0xAD softhyphen */ - { 468, 8, 3, 4, 0, -5 }, /* 0xAE registered */ - { 471, 8, 1, 4, 0, -5 }, /* 0xAF macron */ - { 472, 8, 3, 4, 0, -5 }, /* 0xB0 degree */ - { 475, 8, 5, 4, 0, -5 }, /* 0xB1 plusminus */ - { 480, 8, 3, 4, 0, -5 }, /* 0xB2 twosuperior */ - { 483, 8, 3, 4, 0, -5 }, /* 0xB3 threesuperior */ - { 486, 8, 2, 3, 0, -5 }, /* 0xB4 acute */ - { 488, 8, 5, 4, 0, -5 }, /* 0xB5 mu */ - { 493, 8, 5, 4, 0, -5 }, /* 0xB6 paragraph */ - { 498, 8, 3, 4, 0, -4 }, /* 0xB7 periodcentered */ - { 501, 8, 3, 4, 0, -3 }, /* 0xB8 cedilla */ - { 504, 8, 3, 2, 0, -5 }, /* 0xB9 onesuperior */ - { 507, 8, 5, 4, 0, -5 }, /* 0xBA ordmasculine */ - { 512, 8, 3, 3, 0, -5 }, /* 0xBB guillemotright */ - { 515, 8, 5, 4, 0, -5 }, /* 0xBC onequarter */ - { 520, 8, 5, 4, 0, -5 }, /* 0xBD onehalf */ - { 525, 8, 5, 4, 0, -5 }, /* 0xBE threequarters */ - { 530, 8, 5, 4, 0, -5 }, /* 0xBF questiondown */ - { 535, 8, 5, 4, 0, -5 }, /* 0xC0 Agrave */ - { 540, 8, 5, 4, 0, -5 }, /* 0xC1 Aacute */ - { 545, 8, 5, 4, 0, -5 }, /* 0xC2 Acircumflex */ - { 550, 8, 5, 4, 0, -5 }, /* 0xC3 Atilde */ - { 555, 8, 5, 4, 0, -5 }, /* 0xC4 Adieresis */ - { 560, 8, 5, 4, 0, -5 }, /* 0xC5 Aring */ - { 565, 8, 5, 4, 0, -5 }, /* 0xC6 AE */ - { 570, 8, 6, 4, 0, -5 }, /* 0xC7 Ccedilla */ - { 576, 8, 5, 4, 0, -5 }, /* 0xC8 Egrave */ - { 581, 8, 5, 4, 0, -5 }, /* 0xC9 Eacute */ - { 586, 8, 5, 4, 0, -5 }, /* 0xCA Ecircumflex */ - { 591, 8, 5, 4, 0, -5 }, /* 0xCB Edieresis */ - { 596, 8, 5, 4, 0, -5 }, /* 0xCC Igrave */ - { 601, 8, 5, 4, 0, -5 }, /* 0xCD Iacute */ - { 606, 8, 5, 4, 0, -5 }, /* 0xCE Icircumflex */ - { 611, 8, 5, 4, 0, -5 }, /* 0xCF Idieresis */ - { 616, 8, 5, 4, 0, -5 }, /* 0xD0 Eth */ - { 621, 8, 5, 4, 0, -5 }, /* 0xD1 Ntilde */ - { 626, 8, 5, 4, 0, -5 }, /* 0xD2 Ograve */ - { 631, 8, 5, 4, 0, -5 }, /* 0xD3 Oacute */ - { 636, 8, 5, 4, 0, -5 }, /* 0xD4 Ocircumflex */ - { 641, 8, 5, 4, 0, -5 }, /* 0xD5 Otilde */ - { 646, 8, 5, 4, 0, -5 }, /* 0xD6 Odieresis */ - { 651, 8, 3, 4, 0, -4 }, /* 0xD7 multiply */ - { 654, 8, 5, 4, 0, -5 }, /* 0xD8 Oslash */ - { 659, 8, 5, 4, 0, -5 }, /* 0xD9 Ugrave */ - { 664, 8, 5, 4, 0, -5 }, /* 0xDA Uacute */ - { 669, 8, 5, 4, 0, -5 }, /* 0xDB Ucircumflex */ - { 674, 8, 5, 4, 0, -5 }, /* 0xDC Udieresis */ - { 679, 8, 5, 4, 0, -5 }, /* 0xDD Yacute */ - { 684, 8, 5, 4, 0, -5 }, /* 0xDE Thorn */ - { 689, 8, 6, 4, 0, -5 }, /* 0xDF germandbls */ - { 695, 8, 5, 4, 0, -5 }, /* 0xE0 agrave */ - { 700, 8, 5, 4, 0, -5 }, /* 0xE1 aacute */ - { 705, 8, 5, 4, 0, -5 }, /* 0xE2 acircumflex */ - { 710, 8, 5, 4, 0, -5 }, /* 0xE3 atilde */ - { 715, 8, 5, 4, 0, -5 }, /* 0xE4 adieresis */ - { 720, 8, 5, 4, 0, -5 }, /* 0xE5 aring */ - { 725, 8, 4, 4, 0, -4 }, /* 0xE6 ae */ - { 729, 8, 5, 4, 0, -4 }, /* 0xE7 ccedilla */ - { 734, 8, 5, 4, 0, -5 }, /* 0xE8 egrave */ - { 739, 8, 5, 4, 0, -5 }, /* 0xE9 eacute */ - { 744, 8, 5, 4, 0, -5 }, /* 0xEA ecircumflex */ - { 749, 8, 5, 4, 0, -5 }, /* 0xEB edieresis */ - { 754, 8, 5, 3, 0, -5 }, /* 0xEC igrave */ - { 759, 8, 5, 3, 0, -5 }, /* 0xED iacute */ - { 764, 8, 5, 4, 0, -5 }, /* 0xEE icircumflex */ - { 769, 8, 5, 4, 0, -5 }, /* 0xEF idieresis */ - { 774, 8, 5, 4, 0, -5 }, /* 0xF0 eth */ - { 779, 8, 5, 4, 0, -5 }, /* 0xF1 ntilde */ - { 784, 8, 5, 4, 0, -5 }, /* 0xF2 ograve */ - { 789, 8, 5, 4, 0, -5 }, /* 0xF3 oacute */ - { 794, 8, 5, 4, 0, -5 }, /* 0xF4 ocircumflex */ - { 799, 8, 5, 4, 0, -5 }, /* 0xF5 otilde */ - { 804, 8, 5, 4, 0, -5 }, /* 0xF6 odieresis */ - { 809, 8, 5, 4, 0, -5 }, /* 0xF7 divide */ - { 814, 8, 4, 4, 0, -4 }, /* 0xF8 oslash */ - { 818, 8, 5, 4, 0, -5 }, /* 0xF9 ugrave */ - { 823, 8, 5, 4, 0, -5 }, /* 0xFA uacute */ - { 828, 8, 5, 4, 0, -5 }, /* 0xFB ucircumflex */ - { 833, 8, 5, 4, 0, -5 }, /* 0xFC udieresis */ - { 838, 8, 6, 4, 0, -5 }, /* 0xFD yacute */ - { 844, 8, 5, 4, 0, -4 }, /* 0xFE thorn */ - { 849, 8, 6, 4, 0, -5 }, /* 0xFF ydieresis */ - { 855, 8, 1, 2, 0, -1 }, /* 0x11D gcircumflex */ - { 856, 8, 5, 4, 0, -5 }, /* 0x152 OE */ - { 861, 8, 4, 4, 0, -4 }, /* 0x153 oe */ - { 865, 8, 5, 4, 0, -5 }, /* 0x160 Scaron */ - { 870, 8, 5, 4, 0, -5 }, /* 0x161 scaron */ - { 875, 8, 5, 4, 0, -5 }, /* 0x178 Ydieresis */ - { 880, 8, 5, 4, 0, -5 }, /* 0x17D Zcaron */ - { 885, 8, 5, 4, 0, -5 }, /* 0x17E zcaron */ - { 890, 8, 1, 2, 0, -1 }, /* 0xEA4 uni0EA4 */ - { 891, 8, 1, 2, 0, -1 }, /* 0x13A0 uni13A0 */ - { 892, 8, 1, 2, 0, -3 }, /* 0x2022 bullet */ - { 893, 8, 1, 4, 0, -1 }, /* 0x2026 ellipsis */ - { 894, 8, 5, 4, 0, -5 }, /* 0x20AC Euro */ - { 899, 8, 5, 4, 0, -5 }, /* 0xFFFD uniFFFD */ -#endif /* (TOMTHUMB_USE_EXTENDED) */ -}; diff --git a/resource/gen-resource-linux.ps1 b/resource/gen-resource-linux.ps1 index 5263bb479..1f6ab38be 100644 --- a/resource/gen-resource-linux.ps1 +++ b/resource/gen-resource-linux.ps1 @@ -37,7 +37,7 @@ function compile($f) { -D__AVR_ATmega2560__ ` -DAVR ` -std=gnu++1z ` - -Os -fpermissive $f -c -o "$m/$n.o" + -Os --short-enums -fpermissive -fshort-enums $f -c -o "$m/$n.o" ../../tools/avr/bin/avr-objcopy -O binary -j .data "$m/$n.o" "$m/$n.hex" cd ../compress dotnet run "$m/$n.hex" "$m/$n.ez" diff --git a/resource/gen-resource.ps1 b/resource/gen-resource.ps1 index f7b9c126d..e70333dc7 100644 --- a/resource/gen-resource.ps1 +++ b/resource/gen-resource.ps1 @@ -36,7 +36,7 @@ function compile($f) { -D__AVR_ATmega2560__ ` -DAVR ` -std=gnu++1z ` - -Os $f -c -o "$n.o" + -Os --short-enums $f -c -o "$n.o" avr-objcopy -O binary -j .data "$n.o" "$n.hex" ../compress/bin/Release/netcoreapp3.1/compress.exe "$n.hex" "$n.ez" Remove-Item -ErrorAction Ignore patterns.txt diff --git a/resource/icons_boot.cpp b/resource/icons_boot.cpp index 77432cdbf..064cb040e 100644 --- a/resource/icons_boot.cpp +++ b/resource/icons_boot.cpp @@ -13,23 +13,17 @@ unsigned char mcl_logo_bitmap[] = { 0xf3, 0xfe, 0x7c, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0xf3, 0xfe, 0x78, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0xf3, 0xfe, 0x70, 0x00}; -// 'evilknievel', 45x32px +// 'evilknievel', 33x31px unsigned char evilknievel_bitmap[] = { - 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xd5, 0xff, 0x00, - 0x00, 0x6f, 0xe8, 0x2a, 0xff, 0x80, 0x00, 0x77, 0x80, 0x05, 0x7f, 0x80, - 0x00, 0x62, 0x00, 0x02, 0xff, 0x80, 0x00, 0x70, 0x00, 0x05, 0x7f, 0x00, - 0x00, 0x60, 0x00, 0x02, 0xbf, 0x00, 0x00, 0x20, 0x00, 0x01, 0x7f, 0x00, - 0x00, 0x60, 0x00, 0x02, 0xff, 0x00, 0x00, 0x28, 0x00, 0x01, 0x7f, 0x00, - 0x00, 0x3f, 0x87, 0xf2, 0xfe, 0x00, 0x00, 0x7f, 0xd7, 0xfd, 0x7e, 0x00, - 0x00, 0x7f, 0xef, 0xfe, 0xfe, 0x00, 0x00, 0x7f, 0xc7, 0xff, 0xfc, 0x00, - 0x00, 0x7f, 0xc7, 0xfe, 0xec, 0x00, 0x00, 0x3f, 0xc3, 0xfd, 0xd4, 0x00, - 0x00, 0x1e, 0x80, 0xfa, 0xec, 0x00, 0x00, 0x15, 0x00, 0x05, 0x54, 0x00, - 0x00, 0x1a, 0x80, 0x02, 0xa8, 0x00, 0x00, 0x1d, 0xc0, 0x05, 0x78, 0x00, - 0x00, 0x0a, 0xe2, 0x0a, 0xfc, 0x00, 0x00, 0x1d, 0x00, 0x05, 0x5c, 0x00, - 0x00, 0x0b, 0xc0, 0x0a, 0xbe, 0x00, 0x00, 0x3d, 0xc0, 0x15, 0x5f, 0x80, - 0x07, 0xfe, 0xe8, 0x0a, 0xbf, 0xf0, 0x1f, 0xff, 0xd0, 0x17, 0x5f, 0xf8, - 0x3f, 0xff, 0xe8, 0x0f, 0xbf, 0xf8, 0x3f, 0xff, 0x00, 0x1f, 0x7f, 0xf8, - 0x7f, 0xff, 0x80, 0x3e, 0xbf, 0xf8, 0x7f, 0xff, 0xc0, 0x7d, 0x7f, 0xf8, - 0xff, 0xff, 0xfa, 0xfa, 0xff, 0xf8, 0xff, 0xff, 0x7f, 0xf5, 0x7f, 0xf8}; -// oled_display.drawBitmap(128-45, 0, evilknievel_bitmap, 45, 32); + 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0xdf, 0xfc, 0x00, 0x00, 0x01, + 0xc1, 0xee, 0x00, 0x00, 0x01, 0x80, 0xf6, 0x00, 0x00, 0x01, 0x00, 0x7b, 0x00, 0x00, 0x02, 0x00, + 0x1f, 0x80, 0x00, 0x02, 0x00, 0x0f, 0x80, 0x00, 0x06, 0x00, 0x06, 0xc0, 0x00, 0x06, 0x00, 0x07, + 0xe0, 0x00, 0x06, 0x07, 0xe3, 0xe0, 0x00, 0x07, 0xcf, 0x3f, 0xe0, 0x00, 0x0f, 0x7f, 0xdb, 0xe0, + 0x00, 0x0f, 0xaf, 0xf3, 0x20, 0x00, 0x0f, 0xef, 0xf2, 0x20, 0x00, 0x0f, 0xc7, 0xe2, 0xa0, 0x00, + 0x0f, 0xc3, 0x82, 0x60, 0x00, 0x07, 0x80, 0x03, 0xe0, 0x00, 0x06, 0x40, 0x07, 0xe0, 0x00, 0x06, + 0x30, 0x0f, 0xf0, 0x00, 0x06, 0x7e, 0x1f, 0xf0, 0x00, 0x06, 0x83, 0x3f, 0xf8, 0x00, 0x03, 0x33, + 0xff, 0xf8, 0x00, 0x03, 0x01, 0xfc, 0xbc, 0x00, 0x03, 0x83, 0xf9, 0xde, 0x00, 0x01, 0xff, 0xe3, + 0x6c, 0x00, 0x01, 0xff, 0xc6, 0x64, 0x00, 0x07, 0xff, 0x0c, 0x77, 0x00, 0x1d, 0x7e, 0x30, 0x59, + 0x80, 0x7b, 0x20, 0x60, 0x8e, 0x00, 0xf2, 0x60, 0x81, 0x87, 0x80 +}; diff --git a/resource/icons_logo.cpp b/resource/icons_logo.cpp new file mode 100644 index 000000000..6f7132228 --- /dev/null +++ b/resource/icons_logo.cpp @@ -0,0 +1,250 @@ +#include "MCL_impl.h" +#include "MCLGfx.h" + +/* +// 'midi_logo_medium', 18x9px +unsigned char icon_midi_logo_medium [] = { + 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xb2, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00 +}; +// 'mnm_logo_medium', 18x9px +unsigned char icon_mnm_logo_medium [] = { + 0xfc, 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, + 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcf, 0xcf, 0xc0, 0xcf, 0xcf, 0xc0 +}; +// 'perf_logo_small', 18x9px +unsigned char icon_perf_logo_medium [] = { + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x49, 0x80, 0x84, 0x29, 0x40, 0x84, 0x08, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00 +}; +// 'route_logo_medium', 14x10px +unsigned char icon_route_logo_medium [] = { + 0x1e, 0x3c, 0x3c, 0x78, 0x30, 0x60, 0xfd, 0xf8, 0x78, 0xf0, 0x30, 0x60, 0x00, 0x00, 0x30, 0x60, + 0x48, 0x90, 0x30, 0x60 +}; +// 'metronome_logo_medium', 15x12px +unsigned char icon_metronome_logo_medium [] = { + 0x0f, 0x02, 0x0d, 0x04, 0x18, 0x98, 0x1a, 0x98, 0x32, 0x60, 0x32, 0x40, 0x60, 0xa0, 0x61, 0x20, + 0xc2, 0x10, 0xc0, 0x10, 0xff, 0xe0, 0x3f, 0xc0 +}; +// 'analog_logo_medium', 18x9px +unsigned char icon_analog_logo_medium [] = { + 0x0f, 0xfc, 0x00, 0x10, 0x42, 0x00, 0x27, 0x21, 0x00, 0x2f, 0xa1, 0x00, 0x2f, 0xa1, 0x00, 0x2f, + 0xa1, 0x00, 0x27, 0x21, 0x00, 0x10, 0x42, 0x00, 0x0f, 0x9c, 0x00 +}; +// 'md_logo_medium', 18x9px +unsigned char icon_md_logo_medium [] = { + 0x0f, 0x83, 0xc0, 0x1f, 0x83, 0xc0, 0x3f, 0x87, 0x80, 0x7f, 0x87, 0x80, 0xff, 0x8f, 0x00, 0x77, + 0x8f, 0x00, 0x27, 0xbe, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbc, 0x00 +}; +*/ + + +MCLGIF metronome_gif = {45, 8, 17, 15, DIR_FWDBACK, 1}; +MCLGIF perf_gif = {27, 7, 18, 9, DIR_FWDBACK, 1}; +MCLGIF route_gif = {20, 5, 14, 10, DIR_FWDBACK, 1}; + +MCLGIF analog_gif = {27, 7, 18, 9, DIR_FWDBACK, 1}; +MCLGIF monomachine_gif = {27, 10, 18, 9, DIR_FWDBACK, 1}; +MCLGIF machinedrum_gif = {27, 8, 18, 9, DIR_FWD, 1}; +MCLGIF midi_gif = {27, 8, 18, 9, DIR_FWD, 1}; + +unsigned char perf_gif_data [] = { +// 'pixil-frame-0', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x09, 0x80, 0x84, 0x09, 0x40, 0x84, 0x28, 0x40, 0xa4, + 0x48, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-1', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x09, 0x80, 0x84, 0x29, 0x40, 0x84, 0x28, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-2', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x49, 0x80, 0x84, 0x29, 0x40, 0x84, 0x08, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-3', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0xc9, 0x80, 0x84, 0x09, 0x40, 0x84, 0x08, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-4', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x89, 0x80, 0x85, 0x09, 0x40, 0x84, 0x08, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-5', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x09, 0x80, 0x85, 0x09, 0x40, 0x85, 0x08, 0x40, 0xa4, + 0x08, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +// 'pixil-frame-6', 18x9px + 0x01, 0xe0, 0x00, 0x22, 0x11, 0xc0, 0x44, 0x09, 0x80, 0x84, 0x09, 0x40, 0x85, 0x08, 0x40, 0xa4, + 0x88, 0x40, 0x62, 0x10, 0x80, 0xe1, 0xe1, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char route_gif_data [] = { +// 'pixil-frame-0', 14x10px + 0x1e, 0x3c, 0x3c, 0x78, 0x30, 0x60, 0xfd, 0xf8, 0x78, 0xf0, 0x30, 0x60, 0x00, 0x00, 0x30, 0x60, + 0x48, 0x90, 0x30, 0x60, +// 'pixil-frame-1', 14x10px + 0x00, 0x3c, 0x1e, 0x78, 0x3c, 0x60, 0x31, 0xf8, 0xfc, 0xf0, 0x78, 0x60, 0x30, 0x00, 0x30, 0x60, + 0x48, 0x90, 0x30, 0x60, +// 'pixil-frame-2', 14x10px + 0x00, 0x3c, 0x00, 0x78, 0x1e, 0x60, 0x3d, 0xf8, 0x30, 0xf0, 0xfc, 0x60, 0x78, 0x00, 0x30, 0x60, + 0x78, 0x90, 0x30, 0x60, +// 'pixil-frame-3', 14x10px + 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x78, 0x3c, 0x60, 0x31, 0xf8, 0xfc, 0xf0, 0x78, 0x60, 0x30, 0x60, + 0x78, 0x90, 0x30, 0x60, +// 'pixil-frame-4', 14x10px + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3c, 0x3c, 0x78, 0x30, 0x60, 0xfd, 0xf8, 0x78, 0xf0, 0x30, 0x60, + 0x78, 0xf0, 0x30, 0x60, +}; + +unsigned char analog_gif_data [] = { +// 'pixil-frame-0', 18x9px + 0x0f, 0xfc, 0x00, 0x10, 0x42, 0x00, 0x27, 0x21, 0x00, 0x2f, 0xa1, 0x00, 0x2f, 0xa1, 0x00, 0x2f, + 0xa1, 0x00, 0x27, 0x21, 0x00, 0x10, 0x42, 0x00, 0x0f, 0x9c, 0x00, +// 'pixil-frame-1', 18x9px + 0x07, 0xf8, 0x00, 0x08, 0x24, 0x00, 0x13, 0x92, 0x00, 0x17, 0xd2, 0x00, 0x17, 0xd2, 0x00, 0x17, + 0xd2, 0x00, 0x13, 0x92, 0x00, 0x08, 0x24, 0x00, 0x07, 0xd8, 0x00, +// 'pixil-frame-2', 18x9px + 0x01, 0xf0, 0x00, 0x02, 0x08, 0x00, 0x04, 0xe4, 0x00, 0x05, 0xf4, 0x00, 0x05, 0xf4, 0x00, 0x05, + 0xf4, 0x00, 0x04, 0xe4, 0x00, 0x02, 0x08, 0x00, 0x01, 0xf0, 0x00, +// 'pixil-frame-3', 18x9px + 0x00, 0xe0, 0x00, 0x01, 0x10, 0x00, 0x02, 0x48, 0x00, 0x02, 0xe8, 0x00, 0x02, 0xe8, 0x00, 0x02, + 0xe8, 0x00, 0x02, 0x48, 0x00, 0x01, 0x10, 0x00, 0x00, 0xe0, 0x00, +// 'pixil-frame-4', 18x9px + 0x00, 0x40, 0x00, 0x00, 0xa0, 0x00, 0x01, 0x10, 0x00, 0x01, 0x50, 0x00, 0x01, 0x50, 0x00, 0x01, + 0x50, 0x00, 0x01, 0x10, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x40, 0x00, +// 'pixil-frame-5', 18x9px + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, +// 'pixil-frame-6', 18x9px + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char machinedrum_gif_data [] = { +// 'pixil-frame-0', 18x9px + 0x0f, 0x83, 0xc0, 0x1f, 0x83, 0xc0, 0x3f, 0x87, 0x80, 0x7f, 0x87, 0x80, 0xff, 0x8f, 0x00, 0x77, + 0x8f, 0x00, 0x27, 0xbe, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbc, 0x00, +// 'pixil-frame-1', 18x9px + 0x0f, 0x82, 0x00, 0x1f, 0x83, 0x00, 0x3f, 0x87, 0x80, 0x7f, 0x87, 0x80, 0xff, 0x8f, 0x00, 0x77, + 0x8f, 0x00, 0x27, 0xbe, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbc, 0x00, +// 'pixil-frame-2', 18x9px + 0x0f, 0x83, 0xc0, 0x1f, 0x81, 0xc0, 0x3f, 0x80, 0x80, 0x7f, 0x84, 0x00, 0xff, 0x8e, 0x00, 0x77, + 0x8f, 0x00, 0x27, 0xbe, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbc, 0x00, +// 'pixil-frame-3', 18x9px + 0x0e, 0x03, 0xc0, 0x1f, 0x03, 0xc0, 0x3f, 0x87, 0x80, 0x7f, 0x83, 0x80, 0xff, 0x81, 0x00, 0x77, + 0x88, 0x00, 0x27, 0xbc, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbc, 0x00, +// 'pixil-frame-4', 18x9px + 0x08, 0x83, 0xc0, 0x1c, 0x03, 0xc0, 0x3e, 0x07, 0x80, 0x7f, 0x07, 0x80, 0xff, 0x8f, 0x00, 0x77, + 0x87, 0x00, 0x27, 0xa2, 0x00, 0x07, 0xb0, 0x00, 0x07, 0xb8, 0x00, +// 'pixil-frame-5', 18x9px + 0x07, 0x83, 0xc0, 0x03, 0x83, 0xc0, 0x31, 0x87, 0x80, 0x78, 0x87, 0x80, 0xfc, 0x0f, 0x00, 0x76, + 0x0f, 0x00, 0x27, 0x1e, 0x00, 0x07, 0x8e, 0x00, 0x07, 0x84, 0x00, +// 'pixil-frame-6', 18x9px + 0x0f, 0x83, 0xc0, 0x1f, 0x83, 0xc0, 0x1f, 0x87, 0x80, 0x0f, 0x87, 0x80, 0xc7, 0x8f, 0x00, 0x63, + 0x8f, 0x00, 0x31, 0xbe, 0x00, 0x00, 0xbe, 0x00, 0x04, 0x3c, 0x00, +// 'pixil-frame-7', 18x9px + 0x0f, 0x83, 0xc0, 0x1f, 0x83, 0xc0, 0x3f, 0x87, 0x80, 0x7f, 0x87, 0x80, 0x3f, 0x8f, 0x00, 0x17, + 0x8f, 0x00, 0x07, 0xbe, 0x00, 0x07, 0xbe, 0x00, 0x03, 0xbc, 0x00, +}; + + +unsigned char midi_gif_data [] = { +// 'pixil-frame-0', 18x9px + 0x00, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-1', 18x9px + 0x00, 0x00, 0x00, 0x7c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-2', 18x9px + 0x40, 0x00, 0x00, 0xbc, 0xb2, 0x00, 0x6a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-3', 18x9px + 0xa0, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0xaa, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-4', 18x9px + 0x00, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0xaa, 0xaa, 0x00, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x80, 0x00, 0x01, 0x00, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-5', 18x9px + 0x00, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xaa, 0x80, 0x2a, + 0xb3, 0x40, 0x00, 0x00, 0x80, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-6', 18x9px + 0x00, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x00, 0x2a, 0xab, 0x40, 0x2a, + 0xb2, 0x00, 0x00, 0x01, 0x40, 0x3f, 0xfe, 0x00, 0x3f, 0xfe, 0x00, +// 'pixil-frame-7', 18x9px + 0x00, 0x00, 0x00, 0x3c, 0xb2, 0x00, 0x2a, 0x8a, 0x00, 0x2a, 0xaa, 0x80, 0x2a, 0xaa, 0x00, 0x2a, + 0xb2, 0x40, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x80, 0x3f, 0xfe, 0x00, +}; +unsigned char monomachine_gif_data [] = { +// 'pixil-frame-0', 18x9px + 0xfc, 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, + 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcf, 0xcf, 0xc0, 0xcf, 0xcf, 0xc0, +// 'pixil-frame-1', 18x9px + 0xfc, 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 0x0c, + 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0f, 0xcf, 0xc0, 0x0f, 0xcf, 0xc0, +// 'pixil-frame-2', 18x9px + 0x3c, 0xfc, 0x00, 0x3c, 0xfc, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0c, + 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0f, 0xcf, 0xc0, 0x0f, 0xcf, 0xc0, +// 'pixil-frame-3', 18x9px + 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0c, + 0xcc, 0x00, 0x0c, 0xcc, 0x00, 0x0f, 0xcf, 0xc0, 0x0f, 0xcf, 0xc0, +// 'pixil-frame-4', 18x9px + 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x00, + 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x03, 0xcf, 0xc0, 0x03, 0xcf, 0xc0, +// 'pixil-frame-5', 18x9px + 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, +// 'pixil-frame-6', 18x9px + 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, +// 'pixil-frame-7', 18x9px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x0f, 0xc0, +// 'pixil-frame-8', 18x9px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x03, 0xc0, +// 'pixil-frame-9', 18x9px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char metronome_gif_data [] = { +// 'pixil-frame-0', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x80, 0x03, 0x41, 0x00, 0x06, + 0x26, 0x00, 0x06, 0xa6, 0x00, 0x0c, 0x98, 0x00, 0x0c, 0x90, 0x00, 0x18, 0x28, 0x00, 0x18, 0x48, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-1', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0xc2, 0x00, 0x03, 0x4c, 0x00, 0x06, + 0x2c, 0x00, 0x06, 0xb0, 0x00, 0x0c, 0x90, 0x00, 0x0c, 0xb0, 0x00, 0x18, 0x48, 0x00, 0x18, 0x48, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-2', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x03, 0xd8, 0x00, 0x03, 0x58, 0x00, 0x06, + 0x30, 0x00, 0x06, 0xb0, 0x00, 0x0c, 0xb0, 0x00, 0x0c, 0xd0, 0x00, 0x18, 0x48, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-3', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x03, 0xf0, 0x00, 0x03, 0x60, 0x00, 0x06, + 0x20, 0x00, 0x06, 0xe0, 0x00, 0x0c, 0xd0, 0x00, 0x0c, 0xd0, 0x00, 0x18, 0x88, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-4', 17x15px + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x40, 0x00, 0x06, + 0x60, 0x00, 0x06, 0xa0, 0x00, 0x0c, 0x90, 0x00, 0x0c, 0x90, 0x00, 0x18, 0x88, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-5', 17x15px + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x80, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x40, 0x00, 0x07, + 0x20, 0x00, 0x06, 0xa0, 0x00, 0x0c, 0x90, 0x00, 0x0c, 0x90, 0x00, 0x18, 0x88, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-6', 17x15px + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x03, 0x40, 0x00, 0x06, + 0x20, 0x00, 0x07, 0xa0, 0x00, 0x0d, 0x90, 0x00, 0x0c, 0x90, 0x00, 0x18, 0x88, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-7', 17x15px + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x0f, 0x40, 0x00, 0x06, + 0x20, 0x00, 0x06, 0xa0, 0x00, 0x0e, 0x90, 0x00, 0x0d, 0x10, 0x00, 0x19, 0x08, 0x00, 0x18, 0x88, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +}; +/* +// 'pixil-frame-8', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x23, 0xc0, 0x00, 0x1b, 0x40, 0x00, 0x1e, + 0x20, 0x00, 0x06, 0xa0, 0x00, 0x0e, 0x90, 0x00, 0x0e, 0x10, 0x00, 0x19, 0x08, 0x00, 0x19, 0x08, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +// 'pixil-frame-9', 17x15px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xc0, 0x00, 0x43, 0x40, 0x00, 0x36, + 0x20, 0x00, 0x36, 0xa0, 0x00, 0x0e, 0x90, 0x00, 0x0c, 0x10, 0x00, 0x1a, 0x08, 0x00, 0x19, 0x08, + 0x00, 0x30, 0x84, 0x00, 0x30, 0x04, 0x00, 0x3f, 0xf8, 0x00, 0x0f, 0xf0, 0x00, +}; +*/ + diff --git a/resource/icons_page.cpp b/resource/icons_page.cpp index e9857ddff..6979c9961 100644 --- a/resource/icons_page.cpp +++ b/resource/icons_page.cpp @@ -14,16 +14,6 @@ unsigned char icon_lfo[] = { 0xc0, 0x60, 0x63, 0xc0, 0x60, 0x63, 0xc0, 0x7c, 0x63, 0xe0, 0x7c, 0x63, 0x70, 0x60, 0x63, 0x3e, 0x60, 0x3e, 0x0e, 0x60, 0x1c, 0x00, 0x00, 0x00}; -// 'loudness', 24x16px -unsigned char icon_loudness[] = { - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x11, 0xff, 0x88, 0x25, - 0xc3, 0xa4, 0x29, 0x99, 0x94, 0x29, 0xa5, 0x94, 0x29, 0xb5, - 0x94, 0x29, 0x99, 0x94, 0x25, 0xc3, 0xa4, 0x11, 0xff, 0x88, - 0x01, 0xff, 0x80, 0x01, 0xe7, 0x80, 0x01, 0xe7, 0x80, 0x01, - 0xff, 0x80, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 - -}; - // 'wavd', 24x19px unsigned char icon_wavd[] = { 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xaa, 0x70, 0x00, @@ -32,15 +22,12 @@ unsigned char icon_wavd[] = { 0x00, 0x10, 0xaa, 0xee, 0x10, 0xaa, 0xaa, 0x10, 0x44, 0xaa, 0x70, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// 'step', 24x25px +// 'step', 24x21px unsigned char icon_step[] = { - 0x00, 0x00, 0xd7, 0x00, 0x03, 0xdd, 0x00, 0x0c, 0xf5, 0x00, 0x38, - 0x77, 0x00, 0xe0, 0x3c, 0x03, 0x80, 0x7f, 0x0f, 0x01, 0xde, 0x39, - 0x87, 0x38, 0xd6, 0xcc, 0xe1, 0xd9, 0xfb, 0x86, 0x7f, 0xfe, 0x19, - 0xa7, 0x98, 0x67, 0xde, 0x61, 0x9e, 0xe9, 0x86, 0x78, 0x76, 0x19, - 0xe0, 0x3a, 0x67, 0x80, 0x1d, 0x9e, 0x00, 0x0e, 0x78, 0x00, 0x06, - 0xe0, 0x00, 0x02, 0x80, 0x00, 0x00, 0x77, 0x77, 0x00, 0x42, 0x45, - 0x00, 0x72, 0x67, 0x00, 0x12, 0x44, 0x00, 0x72, 0x74}; + 0x00, 0x00, 0xd7, 0x00, 0x03, 0xdd, 0x00, 0x0c, 0xf5, 0x00, 0x38, 0x77, 0x00, 0xe0, 0x3c, 0x03, + 0x80, 0x7f, 0x0f, 0x01, 0xde, 0x39, 0x87, 0x38, 0xd6, 0xcc, 0xe1, 0xd9, 0xfb, 0x86, 0x7f, 0xfe, + 0x19, 0xa7, 0x98, 0x67, 0xde, 0x61, 0x9e, 0xe9, 0x86, 0x78, 0x76, 0x19, 0xe0, 0x3a, 0x67, 0x80, + 0x1d, 0x9e, 0x00, 0x0e, 0x78, 0x00, 0x06, 0xe0, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00}; // 'mixer', 24x16px unsigned char icon_mixer[] = { @@ -69,13 +56,21 @@ unsigned char icon_rhytmecho[] = { 0x1b, 0x6c, 0x7b, 0x1f, 0x6c, 0x7b, 0x1f, 0x6c, 0x63, 0x1b, 0x6c, 0x7b, 0xdb, 0x7c, 0x7b, 0xdb, 0x7c, 0x00, 0x00, 0x00}; -// 'route', 24x16px +// 'route', 24x14px unsigned char icon_route[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf1, 0xf8, 0x07, 0xe3, 0xf0, - 0x06, 0x03, 0x00, 0x06, 0x03, 0x00, 0x1f, 0x8f, 0xc0, 0x0f, 0x07, 0x80, - 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x80, 0x19, 0x8c, 0xc0, - 0x0f, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0xfc, 0x03, 0xf1, 0xf8, 0x03, 0x01, 0x80, 0x03, + 0x01, 0x80, 0x0f, 0xc7, 0xe0, 0x07, 0x83, 0xc0, 0x03, 0x01, 0x80, 0x00, 0x00, 0x00, 0x07, 0x83, + 0xc0, 0x0c, 0xc6, 0x60, 0x07, 0x83, 0xc0, 0x00, 0x00, 0x00}; +// 'sample', 24x25 +unsigned char icon_sample [] = { + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x20, 0x00, 0x30, 0x20, 0x00, 0x38, 0x20, 0x00, 0x3c, 0x20, + 0x00, 0x04, 0x20, 0x03, 0xc4, 0x20, 0x3f, 0xc4, 0x20, 0xfc, 0xc4, 0x20, 0xc0, 0xc4, 0x20, 0xc0, + 0xc4, 0x20, 0xc0, 0xc4, 0x20, 0xc0, 0xc4, 0x20, 0xc0, 0xc4, 0x20, 0xc3, 0xc4, 0x20, 0xc7, 0xc4, + 0x23, 0xc7, 0x84, 0x27, 0x83, 0x04, 0x27, 0x80, 0x04, 0x23, 0x00, 0x04, 0x20, 0x00, 0x04, 0x20, + 0x00, 0x04, 0x20, 0x00, 0x04, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00 +}; +/* // 'sound', 24x19px unsigned char icon_sound[] = { 0x00, 0x03, 0xe0, 0x00, 0x3f, 0xe0, 0x01, 0xff, 0xe0, 0x01, 0xfc, 0xe0, @@ -83,6 +78,7 @@ unsigned char icon_sound[] = { 0x01, 0xc0, 0xe0, 0x01, 0xc0, 0xe0, 0x01, 0xc3, 0xe0, 0x01, 0xc7, 0xe0, 0x01, 0xc7, 0xe0, 0x07, 0xc7, 0xc0, 0x0f, 0xc3, 0x80, 0x0f, 0xc0, 0x00, 0x0f, 0x80, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00}; +*/ // 'ram_2_icon2', 24x25px unsigned char icon_ram2[] = { @@ -115,11 +111,17 @@ unsigned char icon_pianoroll[] = { // 'chroma', 24x25px unsigned char icon_chroma[] = { - 0x00, 0x00, 0x00, 0x75, 0x77, 0x00, 0x45, 0x55, 0x03, 0x47, 0x65, - 0x0f, 0x75, 0x57, 0x39, 0x00, 0x00, 0xe7, 0x00, 0x03, 0x9c, 0x00, - 0x0f, 0xf1, 0x00, 0x3f, 0xc2, 0x00, 0xff, 0x09, 0x03, 0xfc, 0x64, - 0x0f, 0xf0, 0xb2, 0x37, 0xc2, 0x59, 0xd7, 0x09, 0x2d, 0xdc, 0x64, - 0x96, 0x70, 0xb2, 0x59, 0x82, 0x59, 0x67, 0xc9, 0x2d, 0x9e, 0xec, - 0x96, 0x78, 0x76, 0x59, 0xe0, 0x3b, 0x67, 0x80, 0x1d, 0x9e, 0x00, - 0x0e, 0x78, 0x00, 0x06, 0xe0, 0x00, 0x02, 0x80, 0x00}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x39, 0x00, + 0x00, 0xe7, 0x00, 0x03, 0x9c, 0x00, 0x0f, 0xf1, 0x00, 0x3f, 0xc2, 0x00, 0xff, 0x09, 0x03, 0xfc, + 0x64, 0x0f, 0xf0, 0xb2, 0x37, 0xc2, 0x59, 0xd7, 0x09, 0x2d, 0xdc, 0x64, 0x96, 0x70, 0xb2, 0x59, + 0x82, 0x59, 0x67, 0xc9, 0x2d, 0x9e, 0xec, 0x96, 0x78, 0x76, 0x59, 0xe0, 0x3b, 0x67, 0x80, 0x1d, + 0x9e, 0x00, 0x0e, 0x78, 0x00, 0x06, 0xe0, 0x00, 0x02, 0x80, 0x00}; + +// 'perf', 24x18px +unsigned char icon_perf[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x60, 0x00, 0x1c, 0x50, 0x00, 0x63, 0x08, 0x00, 0x63, 0x08, 0x00, 0xff, 0x84, 0x10, 0xff, + 0x84, 0x10, 0xff, 0x80, 0x08, 0x7f, 0x00, 0x08, 0x7f, 0x00, 0x05, 0x1c, 0x00, 0x03, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00}; + diff --git a/resource/menu_layouts.cpp b/resource/menu_layouts.cpp index 995bb4240..a8f332451 100644 --- a/resource/menu_layouts.cpp +++ b/resource/menu_layouts.cpp @@ -11,254 +11,254 @@ ExitPage ***/ -menu_t<4> boot_menu_layout = { +menu_t boot_menu_layout = { "BOOT", { // m r n d p f o - {"OS UPGRADE", 0, 0, 0, 0, 0, 27, 0}, - {"DFU MODE", 0, 0, 0, 0, 0, 26, 0}, - {"USB DISK", 0, 0, 0, 0, 0, 28, 0}, - {"EXIT", 0, 0, 0, 0, 0, 29, 0}, + {"OS UPGRADE", 0, 0, 0, 0, NULL_PAGE, 27, 0}, + {"DFU MODE", 0, 0, 0, 0, NULL_PAGE, 26, 0}, + {"USB DISK", 0, 0, 0, 0, NULL_PAGE, 28, 0}, + {"EXIT", 0, 0, 0, 0, NULL_PAGE, 29, 0}, }, - 0, 0 + 0 }; -menu_t<2> start_menu_layout = { +menu_t start_menu_layout = { "PROJECT", { // m r n d p f o - {"LOAD PROJECT", 0, 0, 0, 0, 1, 0, 0}, - {"NEW PROJECT", 0, 0, 0, 0, 0, 2, 0}, + {"LOAD PROJECT", 0, 0, 0, 0, LOAD_PROJ_PAGE, 0, 0}, + {"NEW PROJECT", 0, 0, 0, 0, NULL_PAGE, 2, 0}, }, - 0, 0 + 0 }; -menu_t<6> system_menu_layout = { +menu_t system_menu_layout = { "CONFIG", { // m r n d p f o - {"LOAD PROJECT", 0, 0, 0, 0, 1, 0, 0}, + {"LOAD PROJECT", 0, 0, 0, 0, LOAD_PROJ_PAGE, 0, 0}, //{"CONV PROJECT", 0, 0, 0, 0, 2, 0, 0}, - {"NEW PROJECT", 0, 0, 0, 0, 0, 2, 0}, - {"MIDI", 0, 0, 0, 0, 3, 0, 0}, - {"MACHINEDRUM", 0, 0, 0, 0, 4, 0, 0}, - {"AUX PAGES", 0, 0, 0, 0, 6, 0, 0}, - {"SYSTEM", 0, 0, 0, 0, 7, 0, 0}, + {"NEW PROJECT", 0, 0, 0, 0, NULL_PAGE, 2, 0}, + {"MIDI", 0, 0, 0, 0, MIDI_CONFIG_PAGE, 0, 0}, + {"MACHINEDRUM", 0, 0, 0, 0, MD_CONFIG_PAGE, 0, 0}, + {"AUX PAGES", 0, 0, 0, 0, AUX_CONFIG_PAGE, 0, 0}, + {"SYSTEM", 0, 0, 0, 0, MCL_CONFIG_PAGE, 0, 0}, }, - 0, 0 + 0 }; -menu_t<1> auxconfig_menu_layout = { +menu_t auxconfig_menu_layout = { "AUX PAGES", { // m r n d p f o - {"RAM Page" ,0, 0, 0, 0, 8, 0, 0}, + {"RAM Page" ,0, 0, 0, 0, RAM_CONFIG_PAGE, 0, 0}, }, - 0, 0, + 0 }; -menu_t<1> rampage1_menu_layout = { +menu_t rampage1_menu_layout = { "RAM PAGE", { // m r n d p f o - {"LINK:", 0, 2, 2, 1, 0, 0, 0}, + {"LINK:", 0, 2, 2, 1, NULL_PAGE, 0, 0}, }, - 0, 0 + 0 }; -menu_t<5> midiconfig_menu_layout = { +menu_t midiconfig_menu_layout = { "MIDI", { - {"PORT CONFIG", 0, 0, 0, 0, 12, 0, 0}, - {"SYNC", 0, 0, 0, 0, 14, 0, 0}, - {"ROUTING", 0, 0, 0, 0, 15, 0, 0}, - {"PROGRAM", 0, 0, 0, 0, 13, 0, 0}, - {"MD MIDI", 0, 0, 0, 0, 16, 0 ,0}, + {"PORT CONFIG", 0, 0, 0, 0, MIDIPORT_MENU_PAGE, 0, 0}, + {"SYNC", 0, 0, 0, 0, MIDICLOCK_MENU_PAGE, 0, 0}, + {"ROUTING", 0, 0, 0, 0, MIDIROUTE_MENU_PAGE, 0, 0}, + {"PROGRAM", 0, 0, 0, 0, MIDIPROGRAM_MENU_PAGE, 0, 0}, + {"MD MIDI", 0, 0, 0, 0, MIDIMACHINEDRUM_MENU_PAGE, 0 ,0}, }, - 0, 0 + 0 }; -menu_t<5> midiport_menu_layout = { +menu_t midiport_menu_layout = { "PORTS", { - {"TURBO 1:", 0, 4, 4, 2, 0, 0, 2}, - {"TURBO 2:", 0, 4, 4, 3, 0, 0, 2}, - {"TURBO USB:", 0, 4, 4, 55, 0 , 0, 2}, - {"DRIVER 2:", 0, 2, 2, 4, 0, 0, 84}, - {"CTRL PORT:", 1, 4, 4, 56, 0, 0, 100}, + {"TURBO 1:", 0, 4, 4, 2, NULL_PAGE, 0, 2}, + {"TURBO 2:", 0, 4, 4, 3, NULL_PAGE, 0, 2}, + {"TURBO USB:", 0, 4, 4, 55, NULL_PAGE , 0, 2}, + {"DRIVER 2:", 0, 2, 2, 4, 0, NULL_PAGE, 84}, + {"CTRL PORT:", 1, 4, 4, 56, NULL_PAGE, 0, 100}, }, - 24, 0 + 24 }; -menu_t<3> midiprogram_menu_layout = { +menu_t midiprogram_menu_layout = { "PROGRAM", { - {"PRG MODE:", 0, 2, 2, 49, 0, 0, 90}, - {"PRG IN:", 0, 18, 2, 47, 0, 0, 88}, - {"PRG OUT:", 0, 17, 2, 48, 0, 0, 88}, + {"PRG MODE:", 0, 2, 2, 49, NULL_PAGE, 0, 90}, + {"PRG IN:", 0, 18, 2, 47, NULL_PAGE, 0, 88}, + {"PRG OUT:", 0, 17, 2, 48, NULL_PAGE, 0, 88}, }, - 24, 0 + 24 }; -menu_t<4> midiclock_menu_layout = { +menu_t midiclock_menu_layout = { "SYNC", { - {"CLOCK RECV:", 0, 3, 3, 5, 0, 0, 7}, - {"TRANS RECV:", 0, 3, 3, 53, 0, 0, 7}, - {"CLOCK SEND:", 0, 4, 4, 6, 0, 0, 100}, - {"TRANS SEND:", 0, 4, 4, 54, 0, 0, 100}, + {"CLOCK RECV:", 0, 3, 3, 5, NULL_PAGE, 0, 7}, + {"TRANS RECV:", 0, 3, 3, 53, NULL_PAGE, 0, 7}, + {"CLOCK SEND:", 0, 4, 4, 6, 0, NULL_PAGE, 100}, + {"TRANS SEND:", 0, 4, 4, 54, NULL_PAGE, 0, 100}, }, - 24, 0 + 24 }; -menu_t<4> midiroute_menu_layout = { +menu_t midiroute_menu_layout = { "ROUTE", { // m r n d p f o - {"MIDI 1 FWD:", 0, 4, 4, 7, 0, 0, 10}, - {"MIDI 2 FWD:", 0, 4, 4, 51, 0, 0, 92}, + {"MIDI 1 FWD:", 0, 4, 4, 7, NULL_PAGE, 0, 10}, + {"MIDI 2 FWD:", 0, 4, 4, 51, NULL_PAGE, 0, 92}, - {"USB FWD:", 0, 4, 4, 52, 0, 0, 96}, + {"USB FWD:", 0, 4, 4, 52, NULL_PAGE, 0, 96}, - {"CC LOOP:", 0, 2, 2, 11, 0, 0, 86}, + {"CC LOOP:", 0, 2, 2, 11, NULL_PAGE, 0, 86}, }, - 24, 0 + 24 }; -menu_t<3> midimachinedrum_menu_layout = { +menu_t midimachinedrum_menu_layout = { "MD MIDI", { // m r n d p f o - {"CHRO CHAN:", 0, 18, 2, 9, 0, 0, 18}, - {"POLY CHAN:", 0, 18, 2, 46, 0, 0, 88}, - {"TRIG CHAN:", 0, 18, 2, 57, 0, 0, 18}, + {"CHRO CHAN:", 0, 17, 2, 9, NULL_PAGE, 0, 18}, + {"POLY CHAN:", 0, 17, 2, 46, NULL_PAGE, 0, 88}, + {"TRIG CHAN:", 0, 17, 2, 57, NULL_PAGE, 0, 18}, }, - 24, 0 + 24 }; - -menu_t<3> mdconfig_menu_layout = { +menu_t mdconfig_menu_layout = { "MD", { // m r n d p f o - {"IMPORT", 0, 0, 0, 0, 11, 0, 0}, - {"NORMALIZE:", 0, 2, 2, 8, 0, 0, 16}, - {"POLY CONFIG", 0, 0, 0, 0, 9, 0, 0}, + {"IMPORT", 0, 0, 0, 0, MD_IMPORT_PAGE, 0, 0}, + {"NORMALIZE:", 0, 2, 2, 8, NULL_PAGE, 0, 16}, }, - 0, 0 + 0 }; -menu_t<4> mdimport_menu_layout = { +menu_t mdimport_menu_layout = { "MD", { // m r n d p f o - {"SRC: ", 0, 128, 128, 43, 0, 0, 128}, - {"DEST: ", 0, 128, 128, 44, 0, 0, 128}, - {"COUNT:", 1, 128, 0, 45, 0, 0, 0}, - {"RUN", 0, 0, 0, 0, 0, 25, 0}, + {"SRC: ", 0, 128, 128, 43, NULL_PAGE, 0, 128}, + {"DEST: ", 0, 128, 128, 44, NULL_PAGE, 0, 128}, + {"COUNT:", 1, 128, 0, 45, NULL_PAGE, 0, 0}, + {"RUN", 0, 0, 0, 0, NULL_PAGE, 25, 0}, }, - 0, 0 + 0 }; -menu_t<1> mclconfig_menu_layout = { +menu_t mclconfig_menu_layout = { "SYSTEM", { // m r n d p f o - {"DISPLAY:", 0, 2, 2, 13, 0, 0, 23}, + {"DISPLAY:", 0, 2, 2, 13, NULL_PAGE, 0, 23}, }, - 1, 0 + 1 }; -menu_t<7> file_menu_layout = { +menu_t file_menu_layout = { "FILE", { // m r n d p f o - {"CANCEL", 0, 0, 0, 0, 0, 0, 0}, - {"NEW DIR.", 0, 0, 0, 0, 0, 0, 0}, - {"DELETE", 0, 0, 0, 0, 0, 0, 0}, - {"RENAME", 0, 0, 0, 0, 0, 0, 0}, - {"OVERWRITE", 0, 0, 0, 0, 0, 0, 0}, - {"RECV ALL", 0, 0, 0, 0, 0, 0, 0}, - {"SEND ALL", 0, 0, 0, 0, 0, 0, 0}, + {"CANCEL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"NEW DIR.", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"DELETE", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"RENAME", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"OVERWRITE", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"RECV ALL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, + {"SEND ALL", 0, 0, 0, 0, NULL_PAGE, 0, 0}, }, - 0, 0 + 0 }; -menu_t<20> seq_menu_layout = { +menu_t seq_menu_layout = { "SEQ", { // m r n d p f o - {"TRACK SEL:", 1, 17, 0, 14, 0, 3, 0}, - {"EDIT:", 0, 4, 4, 15, 0, 4, 48}, - {"EDIT:", 0, 1 + NUM_LOCKS, 1, 16, 0, 0, 54}, - {"CC:", 0, 133, 5, 17, 0, 0, 55}, - {"SLIDE:", 0, 2, 2, 18, 0, 0, 25}, - {"ARPEGGIATOR", 0, 0, 0, 0, 10, 0, 0}, - {"TRANSPOSE:", 0, 12, 0, 19, 0, 0, 0}, - {"VEL:", 0, 128, 0, 20, 0, 0, 0}, - {"COND:", 1, NUM_TRIG_CONDITIONS + 1, NUM_TRIG_CONDITIONS + 1, 21, 0, 0, 60}, - {"SPEED:", 0, 7, 7, 22, 0, 5, 41}, - {"LENGTH:", 1, 129, 0, 23, 0, 6, 0}, - {"CHANNEL:", 1, 17, 0, 24, 0, 7, 0}, - {"COPY: ", 0, 3, 3, 25, 0, 8, 27}, - {"CLEAR:", 0, 3, 3, 26, 0, 9, 27}, - {"CLEAR:", 0, 3, 3, 26, 0, 10, 30}, - {"PASTE:", 0, 3, 3, 27, 0, 11, 27}, - {"SHIFT:", 0, 5, 5, 28, 0, 12, 35}, - {"REVERSE:", 0, 3, 3, 29, 0, 13, 27}, - {"POLYPHONY", 0, 0, 0, 0, 9, 0, 0}, - {"REC QUANT:", 0, 2, 2, 42, 0, 0, 25}, - }, - 14, 0 -}; - -menu_t<4> step_menu_layout = { - "STP", - { - // m r n d p f o - {"CLEAR:", 0, 2, 2, 30, 0, 15, 30}, - {"COPY STEP", 0, 0, 0, 0, 0, 16, 0}, - {"PASTE STEP", 0, 0, 0, 0, 0, 17, 0}, - {"MUTE STEP", 0, 0, 0, 0, 0, 18, 0}, + {"TRACK SEL:", 1, 17, 0, 14, NULL_PAGE, 3, 0}, + {"DEVICE:", 1, 3, 2, 50, NULL_PAGE, 0, 128}, + {"EDIT:", 0, 4, 4, 15, NULL_PAGE, 4, 48}, + {"EDIT:", 0, 1 + NUM_LOCKS, 1, 16, NULL_PAGE, 0, 54}, + {"CC:", 0, 133, 5, 17, NULL_PAGE, 0, 55}, + {"SLIDE:", 0, 2, 2, 18, NULL_PAGE, 0, 25}, + {"ARPEGGIATOR", 0, 0, 0, 0, ARP_PAGE, 0, 0}, + {"KEY:", 0, 12, 12, 19, NULL_PAGE, 0, 104}, + {"VEL:", 0, 128, 0, 20, NULL_PAGE, 0, 0}, + {"COND:", 1, NUM_TRIG_CONDITIONS + 1, NUM_TRIG_CONDITIONS + 1, 21, NULL_PAGE, 0, 60}, + {"SPEED:", 0, 7, 7, 22, NULL_PAGE, 5, 41}, + {"LENGTH:", 1, 65, 0, 23, NULL_PAGE, 6, 0}, + {"LENGTH:", 2, 129, 0, 23, NULL_PAGE, 6, 0}, + {"CHANNEL:", 1, 17, 0, 24, NULL_PAGE, 7, 0}, + {"COPY: ", 0, 3, 3, 25, NULL_PAGE, 8, 27}, + {"CLEAR:", 0, 3, 3, 26, NULL_PAGE, 9, 27}, + {"CLEAR:", 0, 3, 3, 26, NULL_PAGE, 10, 30}, + {"PASTE:", 0, 3, 3, 27, NULL_PAGE, 11, 27}, + {"SHIFT:", 0, 5, 5, 28, NULL_PAGE, 12, 35}, + {"REVERSE:", 0, 3, 3, 29, NULL_PAGE, 13, 27}, + {"POLYPHONY", 0, 0, 0, 0, POLY_PAGE, 0, 0}, + {"QUANT:", 0, 2, 2, 42, NULL_PAGE, 0, 25}, + {"CC REC:", 0, 2, 2, 30, NULL_PAGE, 0, 25}, + {"SOUND", 0, 0, 0, 0, SOUND_BROWSER, 0, 0}, }, - 19, 0 + 14 }; menu_t slot_menu_layout = { "Slot", { // m r n d p f o - {"GRID: ", 0, 2, 2, 31, 0, 0, 52}, - {"MODE:", 1, 4, 3, 32, 0, 0, 20}, + {"GRID: ", 0, 2, 2, 31, NULL_PAGE, 0, 52}, // for non-ext tracks - {"LEN: ", 1, 65, 0, 39, 0, 0, 0}, + {"LEN: ", 1, 65, 0, 39, NULL_PAGE, 0, 0}, // for ext tracks - {"LEN: ", 1, 129, 0, 39, 0, 0, 0}, - {"LOOP: ", 0, 64, 0, 33, 0, 0, 0}, + {"LEN: ", 1, 129, 0, 39, NULL_PAGE, 0, 0}, + {"LOOP: ", 0, 64, 0, 33, NULL_PAGE, 0, 0}, // o=128, generate the table on-demand - {"JUMP: ", 0, 128, 128, 34, 0, 0, 128}, + {"JUMP: ", 0, 128, 128, 34, NULL_PAGE, 0, 128}, #ifndef OLED_DISPLAY - {"APPLY:", 1, 21, 1, 35, 0, 0, 40}, + {"APPLY:", 1, 21, 1, 35, NULL_PAGE, 0, 40}, #endif - {"CLEAR:", 0, 2, 2, 36, 0, 0, 33}, - {"COPY: ", 0, 2, 2, 37, 0, 0, 33}, - {"PASTE:", 0, 2, 2, 38, 0, 0, 33}, - {"INSROW:", 0, 127, 1, 50, 0, 0, 33}, - {"RENAME", 0, 0, 0, 0, 0, 20, 0}, + {"CLEAR:", 0, 2, 2, 36, NULL_PAGE, 0, 33}, + {"COPY: ", 0, 2, 2, 37, NULL_PAGE, 0, 33}, + {"PASTE:", 0, 2, 2, 38, NULL_PAGE, 0, 33}, + {"RENAME", 0, 0, 0, 0, NULL_PAGE, 20, 0}, + }, + 21 +}; + +menu_t wavdesign_menu_layout = { + "", + { + // m r n d p f o + {"EDIT:", 0, 4, 4, 40, NULL_PAGE, 0, 80}, + {"WAV:", 0, 6, 6, 41, NULL_PAGE, 0, 74}, + {"TRANSFER", 0, 0, 0, 0, NULL_PAGE, 22, 0}, }, - 21, 0, + 23 }; -menu_t<3> wavdesign_menu_layout = { +menu_t perf_menu_layout = { "", { // m r n d p f o - {"EDIT:", 0, 4, 4, 40, 0, 0, 80}, - {"WAV:", 0, 6, 6, 41, 0, 0, 74}, - {"TRANSFER", 0, 0, 0, 0, 0, 22, 0}, + + {"CTRL SEL:",0, 4, 4, 59, NULL_PAGE, 0, 117}, + {"RENAME", 0, 0, 0, 0, NULL_PAGE, 30, 0}, + // {"PARAM:", 0, 17, 1, 58, NULL_PAGE, 0, 116}, }, - 23, 0 + 0 }; diff --git a/resource/menu_options.cpp b/resource/menu_options.cpp index c729ba90d..cb7842204 100644 --- a/resource/menu_options.cpp +++ b/resource/menu_options.cpp @@ -15,7 +15,7 @@ menu_option_t MENU_OPTIONS[] = { // 16: MD NORMALIZE {0, "OFF"},{1, "AUTO"}, // 18: MD CTRL CHAN - {0, "INT"},{17, "OMNI"}, + {0, "--"},{17, "OMNI"}, // 20: MD CHAIN/Slot CHAIN {1, "AUT"},{2,"MAN"},{3,"QUE"}, // 23: SYSTEM DISPLAY @@ -62,5 +62,11 @@ menu_option_t MENU_OPTIONS[] = { {0, "OFF"}, {1, "1"}, {2, "2"}, {3, "1 + 2"}, // 100: MIDI CLK SEND {0, "OFF"}, {1, "2"}, {2, "USB"}, {3, "2 + USB"}, + // 104: NOTES + {0, "A"}, {1, "A#"}, {2, "B"}, {3, "C"}, {4, "C#"}, {5, "D"}, {6, "D#"}, {7, "E"}, {8, "F"}, {9, "F#"}, {10, "G"}, {11, "G#"}, + // 116 + {0, "CTRL"}, + // 117 + {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"} }; diff --git a/resource/page_entries.cpp b/resource/page_entries.cpp index 5e5e28bb6..f504d3fdb 100644 --- a/resource/page_entries.cpp +++ b/resource/page_entries.cpp @@ -2,26 +2,23 @@ #include "MCL_impl.h" PageSelectEntry Entries[] = { - {"GRID", &grid_page, 0, 0, 24, 15, nullptr}, - {"MIXER", &mixer_page, 1, 0, 24, 16, nullptr}, - {"ROUTE", &route_page, 2, 0, 24, 16, nullptr}, - {"LFO", &lfo_page, 3, 0, 24, 24, nullptr}, + {"GRID", GRID_PAGE, 0, 0, 24, 15, nullptr}, + {"MIXER", MIXER_PAGE, 1, 0, 24, 16, nullptr}, + {"PERF", PERF_PAGE_0, 2, 0, 24, 18, nullptr}, + {"ROUTE", ROUTE_PAGE, 3, 0, 24, 14, nullptr}, - {"STEP EDIT", &seq_step_page, 4, 1, 24, 25, nullptr}, - {"PIANO ROLL", &seq_extstep_page, 6, 1, 24, 25, nullptr}, - {"CHROMATIC", &seq_ptc_page, 7, 1, 24, 25, nullptr}, + {"STEP EDIT", SEQ_STEP_PAGE, 4, 1, 24, 21, nullptr}, + {"LFO", LFO_PAGE, 5, 1, 24, 24, nullptr}, + {"PIANO ROLL", SEQ_EXTSTEP_PAGE, 6, 1, 24, 25, nullptr}, + {"CHROMATIC", SEQ_PTC_PAGE, 7, 1, 24, 25, nullptr}, #ifdef SOUND_PAGE - {"SOUND MANAGER", &sound_browser, 8, 2, 24, 19, nullptr}, + {"SAMPLE MANAGER", SAMPLE_BROWSER, 8, 2, 24, 25, nullptr}, #endif #ifdef WAV_DESIGNER - {"WAV DESIGNER", &wd.pages[0], 9, 2, 24, 19, nullptr}, + {"WAV DESIGNER", WD_PAGE_0, 9, 2, 24, 19, nullptr}, #endif -#ifdef LOUDNESS_PAGE - {"LOUDNESS", &loudness_page, 10, 2, 24, 16, nullptr}, -#endif - {"DELAY", &fx_page_a, 12, 3, 24, 25, nullptr}, - {"REVERB", &fx_page_b, 13, 3, 24, 25, nullptr}, - {"RAM-1", &ram_page_a, 14, 3, 24, 25, nullptr}, - {"RAM-2", &ram_page_b, 15, 3, 24, 25, nullptr}, + {"DELAY", FX_PAGE_A, 12, 3, 24, 25, nullptr}, + {"REVERB", FX_PAGE_B, 13, 3, 24, 25, nullptr}, + {"RAM-1", RAM_PAGE_A, 14, 3, 24, 25, nullptr}, + {"RAM-2", RAM_PAGE_B, 15, 3, 24, 25, nullptr}, }; - diff --git a/resource/tuning.cpp b/resource/tuning.cpp deleted file mode 100644 index 27d67b79e..000000000 --- a/resource/tuning.cpp +++ /dev/null @@ -1,110 +0,0 @@ -unsigned char efm_rs_tuning[] = { - 1, 3, 6, 9, 11, 14, 17, 19, 22, 25, 27, 30, 33, 35, 38, 41, 43, - 46, 49, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 81, 83, 86, - 89, 91, 94, 97, 99, 102, 105, 107, 110, 113, 115, 118, 121, 123, - 126 -}; -unsigned char efm_hh_tuning[] = { - 1, 5, 9, 14, 18, 22, 27, 31, 35, 39, 44, 48, 52, 56, 61, 65, 69, - 73, 78, 82, 86, 91, 95, 99, 103, 108, 112, 116, 120, 125 -}; -unsigned char efm_cp_tuning[] = { - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 29, 31, 33, - 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 62, 64, 66, - 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 95, 97, 99, 101, - 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127}; - -unsigned char efm_sd_tuning[] = { - 1, 5, 9, 14, 18, 22, 27, 31, 35, 39, 44, 48, 52, 56, 61, 65, 69, 73, 78, 82, -86, 91, 95, 99, 103, 108, 112, 116, 120, 125, -}; - -unsigned char efm_xt_tuning[] = { - 1, 7, 12, 17, 23, 28, 33, 39, 44, 49, 55, 60, 65, 71, 76, 81, 87, 92, 97, 102, - 108, 113, 118, 124, -}; - -unsigned char efm_bd_tuning[] = { - 1, 3, 6, 9, 11, 14, 17, 19, 22, 25, 27, 30, 33, 35, 38, 41, 43, 46, 49, 51, 54, - 57, 59, 62, 65, 67, 70, 73, 75, 78, 81, 83, 86, 89, 91, 94, 97, 99, 102, 105, 107, - 110, 113, 115, 118, 121, 123, 126, -}; -unsigned char trx_cl_tuning[] = { - 5, 11, 17, 23, 29, 36, 42, 48, 54, 60, 66, 72, 78, 84, 91, 97, 103, 109, 115, 121, - 127, -}; -unsigned char trx_sd_tuning[] = { - 3, 13, 24, 35, 45, 56, 67, 77, 88, 98, 109, 120, -}; -unsigned char trx_xc_tuning[] = { - 1, 6, 11, 17, 22, 27, 33, 38, 43, 49, 54, 60, 65, 70, 76, 81, 86, 92, 97, 102, - 108, 113, 118, 124, -}; -unsigned char trx_xt_tuning[] = { - 2, 7, 12, 18, 23, 28, 34, 39, 44, 49, 55, 60, 65, 71, 76, 81, 87, 92, 97, 103, - 108, 113, 118, 124, -}; -unsigned char trx_bd_tuning[] = { - 1, 7, 12, 17, 23, 28, 33, 39, 44, 49, 55, 60, 66, 71, 76, 82, 87, 92, 98, 103, - 108, 114, 119, 124, -}; - -unsigned char trx_s2_tuning[] = { - 3, 7, 11, 15, 20, 24, 30, 35, 41, 47, 54, 60, 68, 76, 84, 92, 101, 111, 121 -}; - -unsigned char rom_tuning[] = { - 0, 2, 5, 7, 9, 12, 14, 16, 19, 21, 23, 26, 28, 31, 34, 37, 40, 43, 46, 49, 52, - 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 102, 105, 107, - 109, (112), 114, 116, 119, 121, 123, 125, -}; - -unsigned char gnd_sn_tuning[] = { - 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, - 22, 23, 24, 26, 27, 28, 30, 31, 32, 34, 35, 36, 38, 39, 40, 42, 43, 44, 46, 47, 48, - 50, 51, 52, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 68, 70, 71, 72, 74, 75, 76, - 78, 79, 80, 82, 83, 84, 86, 87, 88, 90, 91, 92, 94, 95, 96, 98, 99, 100, - 102, 103, 104, 106, 107, 108, 110, 111, 112, 114, 115, 116, 118, 119, 120, - 122, 123, 124, 126, 127 -}; - -unsigned char trx_b2_tuning[] = { - 31, 33, 36, 39, 43, 45, 48, 51, 56, 60, 62, 66, 70, 74, 79, 83, 89, 94, 97, 104, 108, 113, 120, 125 -}; - -unsigned char trx_rs_tuning[] = { - 2, 10, 17, 26, 36, 45, 55, 66, 78, 90, 103, 117 -}; - -unsigned char efm_cb_tuning[] = { - 2, 6, 10, 14, 19, 23, 27, 32, 36, 40, 44, 48, 53, 57, 62, 66, 70, 74, 78, 83, - 87, 91, 96, 100, 104, 108, 113, 117, 121, 126 -}; - -unsigned char efm_cy_tuning[] = { - 1, 6, 10, 14, 18, 22, 27, 31, 36, 40, 44, 49, 52, 57, 61, 65, 70, 74, 78, 82, - 87, 91, 95, 100, 103, 108, 112, 116, 121, 125 -}; - -unsigned char e12_bc_tuning[] = { - 2, 4, 7, 9, 12, 15, 17, 20, 22, 25, 28, 31, 34, 36, 39, 42, 44, 47, 49, 52, 55, 57, 60, 62, 65, - 68, 71, 74, 76, 79, 82, 84, 87, 89, 92, 95, 97, 100, 103, 106, 108, 111, 114, 116, 119, 122, - 124, 127 -}; - -unsigned char e12_cb_tuning[] = { - 1, 4, 6, 9, 12, 14, 17, 19, 22, 25, 27, 30, 33, 36, 39, 41, 44, 46, 49, 52, 54, 57, 59, - 62, 65, 68, 71, 73, 76, 79, 81, 84, 86, 89, 92, 94, 97, 100, 102, 105, 107, 111, 113, 116, - 119, 121, 124, 126 -}; - -unsigned char e12_lt_tuning[] = { - 2, 5, 8, 11, 15, 18, 21, 25, 28, 31, 34, 37, 41, 44, 47, 50, 53, 57, 60, 63, 66, 70, - 73, 76, 79, 82, 85, 89, 92, 95, 98, 101, 105, 108, 111, 114, 118, 121, 124, 127 -}; - -unsigned char tonal_tuning[] = { -0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, -48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, -94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126 -};