forked from mfulz_github/qmk_firmware
		
	Merge pull request #488 from fredizzimo/add_visualizer
Add visualizer library
This commit is contained in:
		
						commit
						5baaf871bb
					
				
							
								
								
									
										29
									
								
								quantum/visualizer/LICENSE.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								quantum/visualizer/LICENSE.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| The files in this project are licensed under the MIT license | ||||
| It uses the following libraries | ||||
| uGFX - with it's own license, see the license.html file in the uGFX subfolder for more information | ||||
| tmk_core - is indirectly used and not included in the repository. It's licensed under the GPLv2 license | ||||
| Chibios - which is used by tmk_core is licensed under GPLv3. | ||||
| 
 | ||||
| Therefore the effective license for any project using the library is GPLv3 | ||||
| 
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										36
									
								
								quantum/visualizer/example_integration/callbacks.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								quantum/visualizer/example_integration/callbacks.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #include "keyboard.h" | ||||
| #include "action_layer.h" | ||||
| #include "visualizer.h" | ||||
| #include "host.h" | ||||
| 
 | ||||
| void post_keyboard_init(void) { | ||||
|     visualizer_init(); | ||||
| } | ||||
| 
 | ||||
| void post_keyboard_task() { | ||||
|     visualizer_set_state(default_layer_state, layer_state, host_keyboard_leds()); | ||||
| } | ||||
							
								
								
									
										325
									
								
								quantum/visualizer/example_integration/gfxconf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								quantum/visualizer/example_integration/gfxconf.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,325 @@ | ||||
| /**
 | ||||
|  * This file has a different license to the rest of the uGFX system. | ||||
|  * You can copy, modify and distribute this file as you see fit. | ||||
|  * You do not need to publish your source modifications to this file. | ||||
|  * The only thing you are not permitted to do is to relicense it | ||||
|  * under a different license. | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Copy this file into your project directory and rename it as gfxconf.h | ||||
|  * Edit your copy to turn on the uGFX features you want to use. | ||||
|  * The values below are the defaults. | ||||
|  * | ||||
|  * Only remove the comments from lines where you want to change the | ||||
|  * default value. This allows definitions to be included from | ||||
|  * driver makefiles when required and provides the best future | ||||
|  * compatibility for your project. | ||||
|  * | ||||
|  * Please use spaces instead of tabs in this file. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _GFXCONF_H | ||||
| #define _GFXCONF_H | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GOS - One of these must be defined, preferably in your Makefile       //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_OS_CHIBIOS                           TRUE | ||||
| //#define GFX_USE_OS_FREERTOS                          FALSE
 | ||||
| //    #define GFX_FREERTOS_USE_TRACE                   FALSE
 | ||||
| //#define GFX_USE_OS_WIN32                             FALSE
 | ||||
| //#define GFX_USE_OS_LINUX                             FALSE
 | ||||
| //#define GFX_USE_OS_OSX                               FALSE
 | ||||
| //#define GFX_USE_OS_ECOS                              FALSE
 | ||||
| //#define GFX_USE_OS_RAWRTOS                           FALSE
 | ||||
| //#define GFX_USE_OS_ARDUINO                           FALSE
 | ||||
| //#define GFX_USE_OS_KEIL                              FALSE
 | ||||
| //#define GFX_USE_OS_CMSIS                             FALSE
 | ||||
| //#define GFX_USE_OS_RAW32                             FALSE
 | ||||
| //    #define INTERRUPTS_OFF()                         optional_code
 | ||||
| //    #define INTERRUPTS_ON()                          optional_code
 | ||||
| // These are not defined by default for some reason
 | ||||
| #define GOS_NEED_X_THREADS	FALSE | ||||
| #define GOS_NEED_X_HEAP		FALSE | ||||
| 
 | ||||
| // Options that (should where relevant) apply to all operating systems
 | ||||
|     #define GFX_NO_INLINE                            FALSE | ||||
| //    #define GFX_COMPILER                             GFX_COMPILER_UNKNOWN
 | ||||
| //    #define GFX_CPU                                  GFX_CPU_UNKNOWN
 | ||||
| //    #define GFX_OS_HEAP_SIZE                         0
 | ||||
| //    #define GFX_OS_NO_INIT                           FALSE
 | ||||
| //    #define GFX_OS_INIT_NO_WARNING                   FALSE
 | ||||
| //    #define GFX_OS_PRE_INIT_FUNCTION                 myHardwareInitRoutine
 | ||||
| //    #define GFX_OS_EXTRA_INIT_FUNCTION               myOSInitRoutine
 | ||||
| //    #define GFX_OS_EXTRA_DEINIT_FUNCTION             myOSDeInitRoutine
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GDISP                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GDISP                                TRUE | ||||
| 
 | ||||
| //#define GDISP_NEED_AUTOFLUSH                         FALSE
 | ||||
| //#define GDISP_NEED_TIMERFLUSH                        FALSE
 | ||||
| //#define GDISP_NEED_VALIDATION                        TRUE
 | ||||
| //#define GDISP_NEED_CLIP                              TRUE
 | ||||
| //#define GDISP_NEED_CIRCLE                            FALSE
 | ||||
| //#define GDISP_NEED_ELLIPSE                           FALSE
 | ||||
| //#define GDISP_NEED_ARC                               FALSE
 | ||||
| //#define GDISP_NEED_ARCSECTORS                        FALSE
 | ||||
| //#define GDISP_NEED_CONVEX_POLYGON                    FALSE
 | ||||
| //#define GDISP_NEED_SCROLL                            FALSE
 | ||||
| //#define GDISP_NEED_PIXELREAD                         FALSE
 | ||||
| //#define GDISP_NEED_CONTROL                           FALSE
 | ||||
| //#define GDISP_NEED_QUERY                             FALSE
 | ||||
| //#define GDISP_NEED_MULTITHREAD                       FALSE
 | ||||
| //#define GDISP_NEED_STREAMING                         FALSE
 | ||||
| #define GDISP_NEED_TEXT                              TRUE | ||||
| //    #define GDISP_NEED_TEXT_WORDWRAP                 FALSE
 | ||||
| //    #define GDISP_NEED_ANTIALIAS                     FALSE
 | ||||
| //    #define GDISP_NEED_UTF8                          FALSE
 | ||||
|     #define GDISP_NEED_TEXT_KERNING                  TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_UI1                   FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_UI2                   FALSE		// The smallest preferred font.
 | ||||
| //    #define GDISP_INCLUDE_FONT_LARGENUMBERS          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS10          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS12          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS16          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS20          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS24          FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS32          FALSE
 | ||||
|     #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12      TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_FIXED_10X20           FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_FIXED_7X14            FALSE
 | ||||
|     #define GDISP_INCLUDE_FONT_FIXED_5X8             TRUE | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS20_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA       FALSE
 | ||||
| //    #define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA   FALSE
 | ||||
| //    #define GDISP_INCLUDE_USER_FONTS                 FALSE
 | ||||
| 
 | ||||
| //#define GDISP_NEED_IMAGE                             FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_NATIVE                  FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_GIF                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_BMP                     FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_1               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_4               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_4_RLE           FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_8               FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_8_RLE           FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_16              FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_24              FALSE
 | ||||
| //        #define GDISP_NEED_IMAGE_BMP_32              FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_JPG                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_PNG                     FALSE
 | ||||
| //    #define GDISP_NEED_IMAGE_ACCOUNTING              FALSE
 | ||||
| 
 | ||||
| //#define GDISP_NEED_PIXMAP                            FALSE
 | ||||
| //    #define GDISP_NEED_PIXMAP_IMAGE                  FALSE
 | ||||
| 
 | ||||
| //#define GDISP_DEFAULT_ORIENTATION                    GDISP_ROTATE_LANDSCAPE    // If not defined the native hardware orientation is used.
 | ||||
| //#define GDISP_LINEBUF_SIZE                           128
 | ||||
| //#define GDISP_STARTUP_COLOR                          Black
 | ||||
| #define GDISP_NEED_STARTUP_LOGO                      FALSE | ||||
| 
 | ||||
| //#define GDISP_TOTAL_DISPLAYS                         1
 | ||||
| 
 | ||||
| //#define GDISP_DRIVER_LIST                            GDISPVMT_Win32, GDISPVMT_Win32
 | ||||
| //    #ifdef GDISP_DRIVER_LIST
 | ||||
| //        // For code and speed optimization define as TRUE or FALSE if all controllers have the same capability
 | ||||
| //        #define GDISP_HARDWARE_STREAM_WRITE          FALSE
 | ||||
| //        #define GDISP_HARDWARE_STREAM_READ           FALSE
 | ||||
| //        #define GDISP_HARDWARE_STREAM_POS            FALSE
 | ||||
| //        #define GDISP_HARDWARE_DRAWPIXEL             FALSE
 | ||||
| //        #define GDISP_HARDWARE_CLEARS                FALSE
 | ||||
| //        #define GDISP_HARDWARE_FILLS                 FALSE
 | ||||
| //        #define GDISP_HARDWARE_BITFILLS              FALSE
 | ||||
| //        #define GDISP_HARDWARE_SCROLL                FALSE
 | ||||
| //        #define GDISP_HARDWARE_PIXELREAD             FALSE
 | ||||
| //        #define GDISP_HARDWARE_CONTROL               FALSE
 | ||||
| //        #define GDISP_HARDWARE_QUERY                 FALSE
 | ||||
| //        #define GDISP_HARDWARE_CLIP                  FALSE
 | ||||
| 
 | ||||
|         #define GDISP_PIXELFORMAT                    GDISP_PIXELFORMAT_RGB888 | ||||
| //    #endif
 | ||||
| 
 | ||||
| // The custom format is not defined for some reason, so define it as error
 | ||||
| // so we don't get compiler warnings
 | ||||
| #define GDISP_PIXELFORMAT_CUSTOM GDISP_PIXELFORMAT_ERROR | ||||
| 
 | ||||
| #define GDISP_USE_GFXNET                             FALSE | ||||
| //    #define GDISP_GFXNET_PORT                        13001
 | ||||
| //    #define GDISP_GFXNET_CUSTOM_LWIP_STARTUP         FALSE
 | ||||
| //    #define GDISP_DONT_WAIT_FOR_NET_DISPLAY          FALSE
 | ||||
| //    #define GDISP_GFXNET_UNSAFE_SOCKETS              FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GWIN                                                                  //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GWIN                                 FALSE | ||||
| 
 | ||||
| //#define GWIN_NEED_WINDOWMANAGER                      FALSE
 | ||||
| //    #define GWIN_REDRAW_IMMEDIATE                    FALSE
 | ||||
| //    #define GWIN_REDRAW_SINGLEOP                     FALSE
 | ||||
| //    #define GWIN_NEED_FLASHING                       FALSE
 | ||||
| //        #define GWIN_FLASHING_PERIOD                 250
 | ||||
| 
 | ||||
| //#define GWIN_NEED_CONSOLE                            FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_HISTORY                 FALSE
 | ||||
| //        #define GWIN_CONSOLE_HISTORY_AVERAGING       FALSE
 | ||||
| //        #define GWIN_CONSOLE_HISTORY_ATCREATE        FALSE
 | ||||
| //    #define GWIN_CONSOLE_ESCSEQ                      FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_BASESTREAM              FALSE
 | ||||
| //    #define GWIN_CONSOLE_USE_FLOAT                   FALSE
 | ||||
| //#define GWIN_NEED_GRAPH                              FALSE
 | ||||
| //#define GWIN_NEED_GL3D                               FALSE
 | ||||
| 
 | ||||
| //#define GWIN_NEED_WIDGET                             FALSE
 | ||||
| //#define GWIN_FOCUS_HIGHLIGHT_WIDTH                   1
 | ||||
| //    #define GWIN_NEED_LABEL                          FALSE
 | ||||
| //        #define GWIN_LABEL_ATTRIBUTE                 FALSE
 | ||||
| //    #define GWIN_NEED_BUTTON                         FALSE
 | ||||
| //        #define GWIN_BUTTON_LAZY_RELEASE             FALSE
 | ||||
| //    #define GWIN_NEED_SLIDER                         FALSE
 | ||||
| //        #define GWIN_SLIDER_NOSNAP                   FALSE
 | ||||
| //        #define GWIN_SLIDER_DEAD_BAND                5
 | ||||
| //        #define GWIN_SLIDER_TOGGLE_INC               20
 | ||||
| //    #define GWIN_NEED_CHECKBOX                       FALSE
 | ||||
| //    #define GWIN_NEED_IMAGE                          FALSE
 | ||||
| //        #define GWIN_NEED_IMAGE_ANIMATION            FALSE
 | ||||
| //    #define GWIN_NEED_RADIO                          FALSE
 | ||||
| //    #define GWIN_NEED_LIST                           FALSE
 | ||||
| //        #define GWIN_NEED_LIST_IMAGES                FALSE
 | ||||
| //    #define GWIN_NEED_PROGRESSBAR                    FALSE
 | ||||
| //        #define GWIN_PROGRESSBAR_AUTO                FALSE
 | ||||
| //    #define GWIN_NEED_KEYBOARD                       FALSE
 | ||||
| //        #define GWIN_KEYBOARD_DEFAULT_LAYOUT         VirtualKeyboard_English1
 | ||||
| //        #define GWIN_NEED_KEYBOARD_ENGLISH1          TRUE
 | ||||
| //    #define GWIN_NEED_TEXTEDIT                       FALSE
 | ||||
| //    #define GWIN_FLAT_STYLING                        FALSE
 | ||||
| //    #define GWIN_WIDGET_TAGS                         FALSE
 | ||||
| 
 | ||||
| //#define GWIN_NEED_CONTAINERS                         FALSE
 | ||||
| //    #define GWIN_NEED_CONTAINER                      FALSE
 | ||||
| //    #define GWIN_NEED_FRAME                          FALSE
 | ||||
| //    #define GWIN_NEED_TABSET                         FALSE
 | ||||
| //        #define GWIN_TABSET_TABHEIGHT                18
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GEVENT                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GEVENT                               FALSE | ||||
| 
 | ||||
| //#define GEVENT_ASSERT_NO_RESOURCE                    FALSE
 | ||||
| //#define GEVENT_MAXIMUM_SIZE                          32
 | ||||
| //#define GEVENT_MAX_SOURCE_LISTENERS                  32
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GTIMER                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GTIMER                               FALSE | ||||
| 
 | ||||
| //#define GTIMER_THREAD_PRIORITY                       HIGH_PRIORITY
 | ||||
| //#define GTIMER_THREAD_WORKAREA_SIZE                  2048
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GQUEUE                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GQUEUE                               FALSE | ||||
| 
 | ||||
| //#define GQUEUE_NEED_ASYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_GSYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_FSYNC                            FALSE
 | ||||
| //#define GQUEUE_NEED_BUFFERS                          FALSE
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GINPUT                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GINPUT                               FALSE | ||||
| 
 | ||||
| //#define GINPUT_NEED_MOUSE                            FALSE
 | ||||
| //    #define GINPUT_TOUCH_STARTRAW                    FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOTOUCH                     FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOCALIBRATE                 FALSE
 | ||||
| //    #define GINPUT_TOUCH_NOCALIBRATE_GUI             FALSE
 | ||||
| //    #define GINPUT_MOUSE_POLL_PERIOD                 25
 | ||||
| //    #define GINPUT_MOUSE_CLICK_TIME                  300
 | ||||
| //    #define GINPUT_TOUCH_CXTCLICK_TIME               700
 | ||||
| //    #define GINPUT_TOUCH_USER_CALIBRATION_LOAD       FALSE
 | ||||
| //    #define GINPUT_TOUCH_USER_CALIBRATION_SAVE       FALSE
 | ||||
| //    #define GMOUSE_DRIVER_LIST                       GMOUSEVMT_Win32, GMOUSEVMT_Win32
 | ||||
| //#define GINPUT_NEED_KEYBOARD                         FALSE
 | ||||
| //    #define GINPUT_KEYBOARD_POLL_PERIOD              200
 | ||||
| //    #define GKEYBOARD_DRIVER_LIST                    GKEYBOARDVMT_Win32, GKEYBOARDVMT_Win32
 | ||||
| //    #define GKEYBOARD_LAYOUT_OFF                     FALSE
 | ||||
| //        #define GKEYBOARD_LAYOUT_SCANCODE2_US        FALSE
 | ||||
| //#define GINPUT_NEED_TOGGLE                           FALSE
 | ||||
| //#define GINPUT_NEED_DIAL                             FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GFILE                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GFILE                                FALSE | ||||
| 
 | ||||
| //#define GFILE_NEED_PRINTG                            FALSE
 | ||||
| //#define GFILE_NEED_SCANG                             FALSE
 | ||||
| //#define GFILE_NEED_STRINGS                           FALSE
 | ||||
| //#define GFILE_NEED_FILELISTS                         FALSE
 | ||||
| //#define GFILE_NEED_STDIO                             FALSE
 | ||||
| //#define GFILE_NEED_NOAUTOMOUNT                       FALSE
 | ||||
| //#define GFILE_NEED_NOAUTOSYNC                        FALSE
 | ||||
| 
 | ||||
| //#define GFILE_NEED_MEMFS                             FALSE
 | ||||
| //#define GFILE_NEED_ROMFS                             FALSE
 | ||||
| //#define GFILE_NEED_RAMFS                             FALSE
 | ||||
| //#define GFILE_NEED_FATFS                             FALSE
 | ||||
| //#define GFILE_NEED_NATIVEFS                          FALSE
 | ||||
| //#define GFILE_NEED_CHBIOSFS                          FALSE
 | ||||
| 
 | ||||
| //#define GFILE_ALLOW_FLOATS                           FALSE
 | ||||
| //#define GFILE_ALLOW_DEVICESPECIFIC                   FALSE
 | ||||
| //#define GFILE_MAX_GFILES                             3
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GADC                                                                  //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GADC                                 FALSE | ||||
| 
 | ||||
| //#define GADC_MAX_LOWSPEED_DEVICES                    4
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GAUDIO                                                                //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GAUDIO                               FALSE | ||||
| // There seems to be a bug in the ugfx code, the wrong define is used
 | ||||
| // So define it in order to avoid warnings
 | ||||
| #define GFX_USE_GAUDIN                               GFX_USE_GAUDIO | ||||
| //    #define GAUDIO_NEED_PLAY                         FALSE
 | ||||
| //    #define GAUDIO_NEED_RECORD                       FALSE
 | ||||
| 
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| // GMISC                                                                 //
 | ||||
| ///////////////////////////////////////////////////////////////////////////
 | ||||
| #define GFX_USE_GMISC                                FALSE | ||||
| 
 | ||||
| //#define GMISC_NEED_ARRAYOPS                          FALSE
 | ||||
| //#define GMISC_NEED_FASTTRIG                          FALSE
 | ||||
| //#define GMISC_NEED_FIXEDTRIG                         FALSE
 | ||||
| //#define GMISC_NEED_INVSQRT                           FALSE
 | ||||
| //    #define GMISC_INVSQRT_MIXED_ENDIAN               FALSE
 | ||||
| //    #define GMISC_INVSQRT_REAL_SLOW                  FALSE
 | ||||
| //#define GMISC_NEED_MATRIXFLOAT2D                     FALSE
 | ||||
| //#define GMISC_NEED_MATRIXFIXED2D                     FALSE
 | ||||
| 
 | ||||
| #endif /* _GFXCONF_H */ | ||||
							
								
								
									
										91
									
								
								quantum/visualizer/example_integration/lcd_backlight_hal.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								quantum/visualizer/example_integration/lcd_backlight_hal.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #include "lcd_backlight.h" | ||||
| #include "hal.h" | ||||
| 
 | ||||
| #define RED_PIN 1 | ||||
| #define GREEN_PIN 2 | ||||
| #define BLUE_PIN 3 | ||||
| #define CHANNEL_RED FTM0->CHANNEL[0] | ||||
| #define CHANNEL_GREEN FTM0->CHANNEL[1] | ||||
| #define CHANNEL_BLUE FTM0->CHANNEL[2] | ||||
| 
 | ||||
| #define RGB_PORT PORTC | ||||
| #define RGB_PORT_GPIO GPIOC | ||||
| 
 | ||||
| // Base FTM clock selection (72 MHz system clock)
 | ||||
| // @ 0xFFFF period, 72 MHz / (0xFFFF * 2) = Actual period
 | ||||
| // Higher pre-scalar will use the most power (also look the best)
 | ||||
| // Pre-scalar calculations
 | ||||
| // 0 -      72 MHz -> 549 Hz
 | ||||
| // 1 -      36 MHz -> 275 Hz
 | ||||
| // 2 -      18 MHz -> 137 Hz
 | ||||
| // 3 -       9 MHz ->  69 Hz (Slightly visible flicker)
 | ||||
| // 4 -   4 500 kHz ->  34 Hz (Visible flickering)
 | ||||
| // 5 -   2 250 kHz ->  17 Hz
 | ||||
| // 6 -   1 125 kHz ->   9 Hz
 | ||||
| // 7 - 562 500  Hz ->   4 Hz
 | ||||
| // Using a higher pre-scalar without flicker is possible but FTM0_MOD will need to be reduced
 | ||||
| // Which will reduce the brightness range
 | ||||
| #define PRESCALAR_DEFINE 0 | ||||
| 
 | ||||
| void lcd_backlight_hal_init(void) { | ||||
| 	// Setup Backlight
 | ||||
|     SIM->SCGC6 |= SIM_SCGC6_FTM0; | ||||
|     FTM0->CNT = 0; // Reset counter
 | ||||
| 
 | ||||
| 	// PWM Period
 | ||||
| 	// 16-bit maximum
 | ||||
| 	FTM0->MOD = 0xFFFF; | ||||
| 
 | ||||
| 	// Set FTM to PWM output - Edge Aligned, Low-true pulses
 | ||||
| #define CNSC_MODE FTM_SC_CPWMS | FTM_SC_PS(4) | FTM_SC_CLKS(0) | ||||
| 	CHANNEL_RED.CnSC = CNSC_MODE; | ||||
| 	CHANNEL_GREEN.CnSC = CNSC_MODE; | ||||
| 	CHANNEL_BLUE.CnSC = CNSC_MODE; | ||||
| 
 | ||||
| 	// System clock, /w prescalar setting
 | ||||
| 	FTM0->SC = FTM_SC_CLKS(1) | FTM_SC_PS(PRESCALAR_DEFINE); | ||||
| 
 | ||||
| 	CHANNEL_RED.CnV = 0; | ||||
| 	CHANNEL_GREEN.CnV = 0; | ||||
| 	CHANNEL_BLUE.CnV = 0; | ||||
| 
 | ||||
| 	RGB_PORT_GPIO->PDDR |= (1 << RED_PIN); | ||||
| 	RGB_PORT_GPIO->PDDR |= (1 << GREEN_PIN); | ||||
| 	RGB_PORT_GPIO->PDDR |= (1 << BLUE_PIN); | ||||
| 
 | ||||
| #define RGB_MODE PORTx_PCRn_SRE | PORTx_PCRn_DSE | PORTx_PCRn_MUX(4) | ||||
|     RGB_PORT->PCR[RED_PIN] = RGB_MODE; | ||||
|     RGB_PORT->PCR[GREEN_PIN] = RGB_MODE; | ||||
|     RGB_PORT->PCR[BLUE_PIN] = RGB_MODE; | ||||
| } | ||||
| 
 | ||||
| void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b) { | ||||
| 	CHANNEL_RED.CnV = r; | ||||
| 	CHANNEL_GREEN.CnV = g; | ||||
| 	CHANNEL_BLUE.CnV = b; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										121
									
								
								quantum/visualizer/example_integration/visualizer_user.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								quantum/visualizer/example_integration/visualizer_user.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| // Currently we are assuming that both the backlight and LCD are enabled
 | ||||
| // But it's entirely possible to write a custom visualizer that use only
 | ||||
| // one of them
 | ||||
| #ifndef LCD_BACKLIGHT_ENABLE | ||||
| #error This visualizer needs that LCD backlight is enabled | ||||
| #endif | ||||
| 
 | ||||
| #ifndef LCD_ENABLE | ||||
| #error This visualizer needs that LCD is enabled | ||||
| #endif | ||||
| 
 | ||||
| #include "visualizer.h" | ||||
| 
 | ||||
| static const char* welcome_text[] = {"TMK", "Infinity Ergodox"}; | ||||
| 
 | ||||
| // Just an example how to write custom keyframe functions, we could have moved
 | ||||
| // all this into the init function
 | ||||
| bool display_welcome(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     // Read the uGFX documentation for information how to use the displays
 | ||||
|     // http://wiki.ugfx.org/index.php/Main_Page
 | ||||
|     gdispClear(White); | ||||
|     // You can use static variables for things that can't be found in the animation
 | ||||
|     // or state structs
 | ||||
|     gdispDrawString(0, 3, welcome_text[0], state->font_dejavusansbold12, Black); | ||||
|     gdispDrawString(0, 15, welcome_text[1], state->font_dejavusansbold12, Black); | ||||
|     // Always remember to flush the display
 | ||||
|     gdispFlush(); | ||||
|     // you could set the backlight color as well, but we won't do it here, since
 | ||||
|     // it's part of the following animation
 | ||||
|     // lcd_backlight_color(hue, saturation, intensity);
 | ||||
|     // We don't need constant updates, just drawing the screen once is enough
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // Feel free to modify the animations below, or even add new ones if needed
 | ||||
| 
 | ||||
| // Don't worry, if the startup animation is long, you can use the keyboard like normal
 | ||||
| // during that time
 | ||||
| static keyframe_animation_t startup_animation = { | ||||
|     .num_frames = 4, | ||||
|     .loop = false, | ||||
|     .frame_lengths = {0, MS2ST(1000), MS2ST(5000), 0}, | ||||
|     .frame_functions = {display_welcome, keyframe_animate_backlight_color, keyframe_no_operation, enable_visualization}, | ||||
| }; | ||||
| 
 | ||||
| // The color animation animates the LCD color when you change layers
 | ||||
| static keyframe_animation_t color_animation = { | ||||
|     .num_frames = 2, | ||||
|     .loop = false, | ||||
|     // Note that there's a 200 ms no-operation frame,
 | ||||
|     // this prevents the color from changing when activating the layer
 | ||||
|     // momentarily
 | ||||
|     .frame_lengths = {MS2ST(200), MS2ST(500)}, | ||||
|     .frame_functions = {keyframe_no_operation, keyframe_animate_backlight_color}, | ||||
| }; | ||||
| 
 | ||||
| // The LCD animation alternates between the layer name display and a
 | ||||
| // bitmap that displays all active layers
 | ||||
| static keyframe_animation_t lcd_animation = { | ||||
|     .num_frames = 2, | ||||
|     .loop = true, | ||||
|     .frame_lengths = {MS2ST(2000), MS2ST(2000)}, | ||||
|     .frame_functions = {keyframe_display_layer_text, keyframe_display_layer_bitmap}, | ||||
| }; | ||||
| 
 | ||||
| void initialize_user_visualizer(visualizer_state_t* state) { | ||||
|     // The brightness will be dynamically adjustable in the future
 | ||||
|     // But for now, change it here.
 | ||||
|     lcd_backlight_brightness(0x50); | ||||
|     state->current_lcd_color = LCD_COLOR(0x00, 0x00, 0xFF); | ||||
|     state->target_lcd_color = LCD_COLOR(0x10, 0xFF, 0xFF); | ||||
|     start_keyframe_animation(&startup_animation); | ||||
| } | ||||
| 
 | ||||
| void update_user_visualizer_state(visualizer_state_t* state) { | ||||
|     // Add more tests, change the colors and layer texts here
 | ||||
|     // Usually you want to check the high bits (higher layers first)
 | ||||
|     // because that's the order layers are processed for keypresses
 | ||||
|     // You can for check for example:
 | ||||
|     // state->status.layer
 | ||||
|     // state->status.default_layer
 | ||||
|     // state->status.leds (see led.h for available statuses)
 | ||||
|     if (state->status.layer & 0x2) { | ||||
|         state->target_lcd_color = LCD_COLOR(0xA0, 0xB0, 0xFF); | ||||
|         state->layer_text = "Layer 2"; | ||||
|     } | ||||
|     else { | ||||
|         state->target_lcd_color = LCD_COLOR(0x50, 0xB0, 0xFF); | ||||
|         state->layer_text = "Layer 1"; | ||||
|     } | ||||
|     // You can also stop existing animations, and start your custom ones here
 | ||||
|     // remember that you should normally have only one animation for the LCD
 | ||||
|     // and one for the background. But you can also combine them if you want.
 | ||||
|     start_keyframe_animation(&lcd_animation); | ||||
|     start_keyframe_animation(&color_animation); | ||||
| } | ||||
							
								
								
									
										85
									
								
								quantum/visualizer/lcd_backlight.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								quantum/visualizer/lcd_backlight.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #include "lcd_backlight.h" | ||||
| #include <math.h> | ||||
| 
 | ||||
| static uint8_t current_hue = 0x00; | ||||
| static uint8_t current_saturation = 0x00; | ||||
| static uint8_t current_intensity = 0xFF; | ||||
| static uint8_t current_brightness = 0x7F; | ||||
| 
 | ||||
| void lcd_backlight_init(void) { | ||||
|     lcd_backlight_hal_init(); | ||||
|     lcd_backlight_color(current_hue, current_saturation, current_intensity); | ||||
| } | ||||
| 
 | ||||
| // This code is based on Brian Neltner's blogpost and example code
 | ||||
| // "Why every LED light should be using HSI colorspace".
 | ||||
| // http://blog.saikoled.com/post/43693602826/why-every-led-light-should-be-using-hsi
 | ||||
| static void hsi_to_rgb(float h, float s, float i, uint16_t* r_out, uint16_t* g_out, uint16_t* b_out) { | ||||
|     unsigned int r, g, b; | ||||
|     h = fmodf(h, 360.0f); // cycle h around to 0-360 degrees
 | ||||
|     h = 3.14159f * h / 180.0f; // Convert to radians.
 | ||||
|     s = s > 0.0f ? (s < 1.0f ? s : 1.0f) : 0.0f; // clamp s and i to interval [0,1]
 | ||||
|     i = i > 0.0f ? (i < 1.0f ? i : 1.0f) : 0.0f; | ||||
| 
 | ||||
|     // Math! Thanks in part to Kyle Miller.
 | ||||
|     if(h < 2.09439f) { | ||||
|         r = 65535.0f * i/3.0f *(1.0f + s * cos(h) / cosf(1.047196667f - h)); | ||||
|         g = 65535.0f * i/3.0f *(1.0f + s *(1.0f - cosf(h) / cos(1.047196667f - h))); | ||||
|         b = 65535.0f * i/3.0f *(1.0f - s); | ||||
|     } else if(h < 4.188787) { | ||||
|         h = h - 2.09439; | ||||
|         g = 65535.0f * i/3.0f *(1.0f + s * cosf(h) / cosf(1.047196667f - h)); | ||||
|         b = 65535.0f * i/3.0f *(1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); | ||||
|         r = 65535.0f * i/3.0f *(1.0f - s); | ||||
|     } else { | ||||
|         h = h - 4.188787; | ||||
|         b = 65535.0f*i/3.0f * (1.0f + s * cosf(h) / cosf(1.047196667f - h)); | ||||
|         r = 65535.0f*i/3.0f * (1.0f + s * (1.0f - cosf(h) / cosf(1.047196667f - h))); | ||||
|         g = 65535.0f*i/3.0f * (1.0f - s); | ||||
|     } | ||||
|     *r_out = r > 65535 ? 65535 : r; | ||||
|     *g_out = g > 65535 ? 65535 : g; | ||||
|     *b_out = b > 65535 ? 65535 : b; | ||||
| } | ||||
| 
 | ||||
| void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity) { | ||||
|     uint16_t r, g, b; | ||||
|     float hue_f = 360.0f * (float)hue / 255.0f; | ||||
|     float saturation_f = (float)saturation / 255.0f; | ||||
|     float intensity_f = (float)intensity / 255.0f; | ||||
|     intensity_f *= (float)current_brightness / 255.0f; | ||||
|     hsi_to_rgb(hue_f, saturation_f, intensity_f, &r, &g, &b); | ||||
| 	current_hue = hue; | ||||
| 	current_saturation = saturation; | ||||
| 	current_intensity = intensity; | ||||
| 	lcd_backlight_hal_color(r, g, b); | ||||
| } | ||||
| 
 | ||||
| void lcd_backlight_brightness(uint8_t b) { | ||||
|     current_brightness = b; | ||||
|     lcd_backlight_color(current_hue, current_saturation, current_intensity); | ||||
| } | ||||
							
								
								
									
										42
									
								
								quantum/visualizer/lcd_backlight.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								quantum/visualizer/lcd_backlight.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #ifndef LCD_BACKLIGHT_H_ | ||||
| #define LCD_BACKLIGHT_H_ | ||||
| #include "stdint.h" | ||||
| 
 | ||||
| // Helper macros for storing hue, staturation and intensity as unsigned integers
 | ||||
| #define LCD_COLOR(hue, saturation, intensity) (hue << 16 | saturation << 8 | intensity) | ||||
| #define LCD_HUE(color) ((color >> 16) & 0xFF) | ||||
| #define LCD_SAT(color) ((color >> 8) & 0xFF) | ||||
| #define LCD_INT(color) (color & 0xFF) | ||||
| 
 | ||||
| void lcd_backlight_init(void); | ||||
| void lcd_backlight_color(uint8_t hue, uint8_t saturation, uint8_t intensity); | ||||
| void lcd_backlight_brightness(uint8_t b); | ||||
| 
 | ||||
| void lcd_backlight_hal_init(void); | ||||
| void lcd_backlight_hal_color(uint16_t r, uint16_t g, uint16_t b); | ||||
| 
 | ||||
| #endif /* LCD_BACKLIGHT_H_ */ | ||||
							
								
								
									
										170
									
								
								quantum/visualizer/led_test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								quantum/visualizer/led_test.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,170 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| #include "led_test.h" | ||||
| #include "gfx.h" | ||||
| #include "math.h" | ||||
| 
 | ||||
| #define CROSSFADE_TIME 1000 | ||||
| #define GRADIENT_TIME 3000 | ||||
| 
 | ||||
| keyframe_animation_t led_test_animation = { | ||||
|     .num_frames = 14, | ||||
|     .loop = true, | ||||
|     .frame_lengths = { | ||||
|         gfxMillisecondsToTicks(1000), // fade in
 | ||||
|         gfxMillisecondsToTicks(1000), // no op (leds on)
 | ||||
|         gfxMillisecondsToTicks(1000), // fade out
 | ||||
|         gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
 | ||||
|         gfxMillisecondsToTicks(GRADIENT_TIME), // left to rigt (outside in)
 | ||||
|         gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
 | ||||
|         gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
 | ||||
|         0,           // mirror leds
 | ||||
|         gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
 | ||||
|         gfxMillisecondsToTicks(GRADIENT_TIME), // left_to_right (mirrored, so inside out)
 | ||||
|         gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
 | ||||
|         gfxMillisecondsToTicks(GRADIENT_TIME), // top_to_bottom
 | ||||
|         0,           // normal leds
 | ||||
|         gfxMillisecondsToTicks(CROSSFADE_TIME), // crossfade
 | ||||
| 
 | ||||
|     }, | ||||
|     .frame_functions = { | ||||
|         keyframe_fade_in_all_leds, | ||||
|         keyframe_no_operation, | ||||
|         keyframe_fade_out_all_leds, | ||||
|         keyframe_led_crossfade, | ||||
|         keyframe_led_left_to_right_gradient, | ||||
|         keyframe_led_crossfade, | ||||
|         keyframe_led_top_to_bottom_gradient, | ||||
|         keyframe_mirror_led_orientation, | ||||
|         keyframe_led_crossfade, | ||||
|         keyframe_led_left_to_right_gradient, | ||||
|         keyframe_led_crossfade, | ||||
|         keyframe_led_top_to_bottom_gradient, | ||||
|         keyframe_normal_led_orientation, | ||||
|         keyframe_led_crossfade, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| static uint8_t fade_led_color(keyframe_animation_t* animation, int from, int to) { | ||||
|     int frame_length = animation->frame_lengths[animation->current_frame]; | ||||
|     int current_pos = frame_length - animation->time_left_in_frame; | ||||
|     int delta = to - from; | ||||
|     int luma = (delta * current_pos) / frame_length; | ||||
|     luma += from; | ||||
|     return luma; | ||||
| } | ||||
| 
 | ||||
| static void keyframe_fade_all_leds_from_to(keyframe_animation_t* animation, uint8_t from, uint8_t to) { | ||||
|     uint8_t luma = fade_led_color(animation, from, to); | ||||
|     color_t color = LUMA2COLOR(luma); | ||||
|     gdispGClear(LED_DISPLAY, color); | ||||
| } | ||||
| 
 | ||||
| // TODO: Should be customizable per keyboard
 | ||||
| #define NUM_ROWS 7 | ||||
| #define NUM_COLS 7 | ||||
| 
 | ||||
| static uint8_t crossfade_start_frame[NUM_ROWS][NUM_COLS]; | ||||
| static uint8_t crossfade_end_frame[NUM_ROWS][NUM_COLS]; | ||||
| 
 | ||||
| static uint8_t compute_gradient_color(float t, float index, float num) { | ||||
|     const float two_pi = 2.0f * PI; | ||||
|     float normalized_index = (1.0f - index / (num - 1)) * two_pi; | ||||
|     float x = t * two_pi + normalized_index; | ||||
|     float v = 0.5 * (cosf(x) + 1.0f); | ||||
|     return (uint8_t)(255.0f * v); | ||||
| } | ||||
| 
 | ||||
| bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     keyframe_fade_all_leds_from_to(animation, 0, 255); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     keyframe_fade_all_leds_from_to(animation, 255, 0); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     float frame_length = animation->frame_lengths[animation->current_frame]; | ||||
|     float current_pos = frame_length - animation->time_left_in_frame; | ||||
|     float t = current_pos / frame_length; | ||||
|     for (int i=0; i< NUM_COLS; i++) { | ||||
|         uint8_t color = compute_gradient_color(t, i, NUM_COLS); | ||||
|         gdispGDrawLine(LED_DISPLAY, i, 0, i, NUM_ROWS - 1, LUMA2COLOR(color)); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     float frame_length = animation->frame_lengths[animation->current_frame]; | ||||
|     float current_pos = frame_length - animation->time_left_in_frame; | ||||
|     float t = current_pos / frame_length; | ||||
|     for (int i=0; i< NUM_ROWS; i++) { | ||||
|         uint8_t color = compute_gradient_color(t, i, NUM_ROWS); | ||||
|         gdispGDrawLine(LED_DISPLAY, 0, i, NUM_COLS - 1, i, LUMA2COLOR(color)); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static void copy_current_led_state(uint8_t* dest) { | ||||
|     for (int i=0;i<NUM_ROWS;i++) { | ||||
|         for (int j=0;j<NUM_COLS;j++) { | ||||
|             dest[i*NUM_COLS + j] = gdispGGetPixelColor(LED_DISPLAY, j, i); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     if (animation->first_update_of_frame) { | ||||
|         copy_current_led_state(&crossfade_start_frame[0][0]); | ||||
|         run_next_keyframe(animation, state); | ||||
|         copy_current_led_state(&crossfade_end_frame[0][0]); | ||||
|     } | ||||
|     for (int i=0;i<NUM_ROWS;i++) { | ||||
|         for (int j=0;j<NUM_COLS;j++) { | ||||
|             color_t color  = LUMA2COLOR(fade_led_color(animation, crossfade_start_frame[i][j], crossfade_end_frame[i][j])); | ||||
|             gdispGDrawPixel(LED_DISPLAY, j, i, color); | ||||
|         } | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_mirror_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     (void)animation; | ||||
|     gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_180); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)state; | ||||
|     (void)animation; | ||||
|     gdispGSetOrientation(LED_DISPLAY, GDISP_ROTATE_0); | ||||
|     return false; | ||||
| } | ||||
							
								
								
									
										41
									
								
								quantum/visualizer/led_test.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								quantum/visualizer/led_test.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #ifndef TMK_VISUALIZER_LED_TEST_H_ | ||||
| #define TMK_VISUALIZER_LED_TEST_H_ | ||||
| 
 | ||||
| #include "visualizer.h" | ||||
| 
 | ||||
| bool keyframe_fade_in_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_fade_out_all_leds(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_led_left_to_right_gradient(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_led_top_to_bottom_gradient(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_led_crossfade(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_mirror_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_normal_led_orientation(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| 
 | ||||
| extern keyframe_animation_t led_test_animation; | ||||
| 
 | ||||
| 
 | ||||
| #endif /* TMK_VISUALIZER_LED_TEST_H_ */ | ||||
							
								
								
									
										18
									
								
								quantum/visualizer/readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								quantum/visualizer/readme.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| # A visualization library for the TMK keyboard firmware | ||||
| 
 | ||||
| This library is designed to work together with the [TMK keyboard firmware](https://github.com/tmk/tmk_keyboard). Currently it only works for [Chibios](http://www.chibios.org/) | ||||
|  flavors, but it would be possible to add support for other configurations as well. The LCD display functionality is provided by the [uGFX library](http://www.ugfx.org/).  | ||||
| 
 | ||||
| ## To use this library as a user | ||||
| You can and should modify the visualizer\_user.c file. Check the comments in the file for more information. | ||||
| 
 | ||||
| ## To add this library to custom keyboard projects | ||||
| 
 | ||||
| 1. Add tmk_visualizer as a submodule to your project | ||||
| 1. Set VISUALIZER_DIR in the main keyboard project makefile to point to the submodule | ||||
| 1. Define LCD\_ENABLE and/or LCD\_BACKLIGHT\_ENABLE, to enable support | ||||
| 1. Include the visualizer.mk make file | ||||
| 1. Copy the files in the example\_integration folder to your keyboard project | ||||
| 1. All other files than the callback.c file are included automatically, so you will need to add callback.c to your makefile manually. If you already have a similar file in your project, you can just copy the functions instead of the whole file. | ||||
| 1. Edit the files to match your hardware. You might might want to read the Chibios and UGfx documentation, for more information. | ||||
| 1. If you enable LCD support you might also have to write a custom uGFX display driver, check the uGFX documentation for that. You probably also want to enable SPI support in your Chibios configuration. | ||||
							
								
								
									
										549
									
								
								quantum/visualizer/visualizer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										549
									
								
								quantum/visualizer/visualizer.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,549 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #include "visualizer.h" | ||||
| #include "config.h" | ||||
| #include <string.h> | ||||
| #ifdef PROTOCOL_CHIBIOS | ||||
| #include "ch.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LCD_ENABLE | ||||
| #include "gfx.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
| #include "lcd_backlight.h" | ||||
| #endif | ||||
| 
 | ||||
| //#define DEBUG_VISUALIZER
 | ||||
| 
 | ||||
| #ifdef DEBUG_VISUALIZER | ||||
| #include "debug.h" | ||||
| #else | ||||
| #include "nodebug.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_SERIAL_LINK | ||||
| #include "serial_link/protocol/transport.h" | ||||
| #include "serial_link/system/serial_link.h" | ||||
| #endif | ||||
| 
 | ||||
| // Define this in config.h
 | ||||
| #ifndef VISUALIZER_THREAD_PRIORITY | ||||
| #define "Visualizer thread priority not defined" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| static visualizer_keyboard_status_t current_status = { | ||||
|     .layer = 0xFFFFFFFF, | ||||
|     .default_layer = 0xFFFFFFFF, | ||||
|     .leds = 0xFFFFFFFF, | ||||
|     .suspended = false, | ||||
| }; | ||||
| 
 | ||||
| static bool same_status(visualizer_keyboard_status_t* status1, visualizer_keyboard_status_t* status2) { | ||||
|     return status1->layer == status2->layer && | ||||
|         status1->default_layer == status2->default_layer && | ||||
|         status1->leds == status2->leds && | ||||
|         status1->suspended == status2->suspended; | ||||
| } | ||||
| 
 | ||||
| static bool visualizer_enabled = false; | ||||
| 
 | ||||
| #define MAX_SIMULTANEOUS_ANIMATIONS 4 | ||||
| static keyframe_animation_t* animations[MAX_SIMULTANEOUS_ANIMATIONS] = {}; | ||||
| 
 | ||||
| #ifdef USE_SERIAL_LINK | ||||
| MASTER_TO_ALL_SLAVES_OBJECT(current_status, visualizer_keyboard_status_t); | ||||
| 
 | ||||
| static remote_object_t* remote_objects[] = { | ||||
|     REMOTE_OBJECT(current_status), | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| GDisplay* LCD_DISPLAY = 0; | ||||
| GDisplay* LED_DISPLAY = 0; | ||||
| 
 | ||||
| __attribute__((weak)) | ||||
| GDisplay* get_lcd_display(void) { | ||||
|     return gdispGetDisplay(0); | ||||
| } | ||||
| 
 | ||||
| __attribute__((weak)) | ||||
| GDisplay* get_led_display(void) { | ||||
|     return gdispGetDisplay(1); | ||||
| } | ||||
| 
 | ||||
| void start_keyframe_animation(keyframe_animation_t* animation) { | ||||
|     animation->current_frame = -1; | ||||
|     animation->time_left_in_frame = 0; | ||||
|     animation->need_update = true; | ||||
|     int free_index = -1; | ||||
|     for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|         if (animations[i] == animation) { | ||||
|             return; | ||||
|         } | ||||
|         if (free_index == -1 && animations[i] == NULL) { | ||||
|            free_index=i; | ||||
|         } | ||||
|     } | ||||
|     if (free_index!=-1) { | ||||
|         animations[free_index] = animation; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void stop_keyframe_animation(keyframe_animation_t* animation) { | ||||
|     animation->current_frame = animation->num_frames; | ||||
|     animation->time_left_in_frame = 0; | ||||
|     animation->need_update = true; | ||||
|     animation->first_update_of_frame = false; | ||||
|     animation->last_update_of_frame = false; | ||||
|     for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|         if (animations[i] == animation) { | ||||
|             animations[i] = NULL; | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void stop_all_keyframe_animations(void) { | ||||
|     for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|         if (animations[i]) { | ||||
|             animations[i]->current_frame = animations[i]->num_frames; | ||||
|             animations[i]->time_left_in_frame = 0; | ||||
|             animations[i]->need_update = true; | ||||
|             animations[i]->first_update_of_frame = false; | ||||
|             animations[i]->last_update_of_frame = false; | ||||
|             animations[i] = NULL; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool update_keyframe_animation(keyframe_animation_t* animation, visualizer_state_t* state, systemticks_t delta, systemticks_t* sleep_time) { | ||||
|     // TODO: Clean up this messy code
 | ||||
|     dprintf("Animation frame%d, left %d, delta %d\n", animation->current_frame, | ||||
|             animation->time_left_in_frame, delta); | ||||
|     if (animation->current_frame == animation->num_frames) { | ||||
|         animation->need_update = false; | ||||
|         return false; | ||||
|     } | ||||
|     if (animation->current_frame == -1) { | ||||
|        animation->current_frame = 0; | ||||
|        animation->time_left_in_frame = animation->frame_lengths[0]; | ||||
|        animation->need_update = true; | ||||
|        animation->first_update_of_frame = true; | ||||
|     } else { | ||||
|         animation->time_left_in_frame -= delta; | ||||
|         while (animation->time_left_in_frame <= 0) { | ||||
|             int left = animation->time_left_in_frame; | ||||
|             if (animation->need_update) { | ||||
|                 animation->time_left_in_frame = 0; | ||||
|                 animation->last_update_of_frame = true; | ||||
|                 (*animation->frame_functions[animation->current_frame])(animation, state); | ||||
|                 animation->last_update_of_frame = false; | ||||
|             } | ||||
|             animation->current_frame++; | ||||
|             animation->need_update = true; | ||||
|             animation->first_update_of_frame = true; | ||||
|             if (animation->current_frame == animation->num_frames) { | ||||
|                 if (animation->loop) { | ||||
|                     animation->current_frame = 0; | ||||
|                 } | ||||
|                 else { | ||||
|                     stop_keyframe_animation(animation); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             delta = -left; | ||||
|             animation->time_left_in_frame = animation->frame_lengths[animation->current_frame]; | ||||
|             animation->time_left_in_frame -= delta; | ||||
|         } | ||||
|     } | ||||
|     if (animation->need_update) { | ||||
|         animation->need_update = (*animation->frame_functions[animation->current_frame])(animation, state); | ||||
|         animation->first_update_of_frame = false; | ||||
|     } | ||||
| 
 | ||||
|     systemticks_t wanted_sleep = animation->need_update ? gfxMillisecondsToTicks(10) : (unsigned)animation->time_left_in_frame; | ||||
|     if (wanted_sleep < *sleep_time) { | ||||
|         *sleep_time = wanted_sleep; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     int next_frame = animation->current_frame + 1; | ||||
|     if (next_frame == animation->num_frames) { | ||||
|         next_frame = 0; | ||||
|     } | ||||
|     keyframe_animation_t temp_animation = *animation; | ||||
|     temp_animation.current_frame = next_frame; | ||||
|     temp_animation.time_left_in_frame = animation->frame_lengths[next_frame]; | ||||
|     temp_animation.first_update_of_frame = true; | ||||
|     temp_animation.last_update_of_frame = false; | ||||
|     temp_animation.need_update  = false; | ||||
|     visualizer_state_t temp_state = *state; | ||||
|     (*temp_animation.frame_functions[next_frame])(&temp_animation, &temp_state); | ||||
| } | ||||
| 
 | ||||
| bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     (void)state; | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
| bool keyframe_animate_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     int frame_length = animation->frame_lengths[animation->current_frame]; | ||||
|     int current_pos = frame_length - animation->time_left_in_frame; | ||||
|     uint8_t t_h = LCD_HUE(state->target_lcd_color); | ||||
|     uint8_t t_s = LCD_SAT(state->target_lcd_color); | ||||
|     uint8_t t_i = LCD_INT(state->target_lcd_color); | ||||
|     uint8_t p_h = LCD_HUE(state->prev_lcd_color); | ||||
|     uint8_t p_s = LCD_SAT(state->prev_lcd_color); | ||||
|     uint8_t p_i = LCD_INT(state->prev_lcd_color); | ||||
| 
 | ||||
|     uint8_t d_h1 = t_h - p_h; //Modulo arithmetic since we want to wrap around
 | ||||
|     int d_h2 = t_h - p_h; | ||||
|     // Chose the shortest way around
 | ||||
|     int d_h = abs(d_h2) < d_h1 ? d_h2 : d_h1; | ||||
|     int d_s = t_s - p_s; | ||||
|     int d_i = t_i - p_i; | ||||
| 
 | ||||
|     int hue = (d_h * current_pos) / frame_length; | ||||
|     int sat = (d_s * current_pos) / frame_length; | ||||
|     int intensity = (d_i * current_pos) / frame_length; | ||||
|     //dprintf("%X -> %X = %X\n", p_h, t_h, hue);
 | ||||
|     hue += p_h; | ||||
|     sat += p_s; | ||||
|     intensity += p_i; | ||||
|     state->current_lcd_color = LCD_COLOR(hue, sat, intensity); | ||||
|     lcd_backlight_color( | ||||
|             LCD_HUE(state->current_lcd_color), | ||||
|             LCD_SAT(state->current_lcd_color), | ||||
|             LCD_INT(state->current_lcd_color)); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_set_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     state->prev_lcd_color = state->target_lcd_color; | ||||
|     state->current_lcd_color = state->target_lcd_color; | ||||
|     lcd_backlight_color( | ||||
|             LCD_HUE(state->current_lcd_color), | ||||
|             LCD_SAT(state->current_lcd_color), | ||||
|             LCD_INT(state->current_lcd_color)); | ||||
|     return false; | ||||
| } | ||||
| #endif // LCD_BACKLIGHT_ENABLE
 | ||||
| 
 | ||||
| #ifdef LCD_ENABLE | ||||
| bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     gdispClear(White); | ||||
|     gdispDrawString(0, 10, state->layer_text, state->font_dejavusansbold12, Black); | ||||
|     gdispFlush(); | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| static void format_layer_bitmap_string(uint16_t default_layer, uint16_t layer, char* buffer) { | ||||
|     for (int i=0; i<16;i++) | ||||
|     { | ||||
|         uint32_t mask = (1u << i); | ||||
|         if (default_layer & mask) { | ||||
|             if (layer & mask) { | ||||
|                 *buffer = 'B'; | ||||
|             } else { | ||||
|                 *buffer = 'D'; | ||||
|             } | ||||
|         } else if (layer & mask) { | ||||
|             *buffer = '1'; | ||||
|         } else { | ||||
|             *buffer = '0'; | ||||
|         } | ||||
|         ++buffer; | ||||
| 
 | ||||
|         if (i==3 || i==7 || i==11) { | ||||
|             *buffer = ' '; | ||||
|             ++buffer; | ||||
|         } | ||||
|     } | ||||
|     *buffer = 0; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     const char* layer_help = "1=On D=Default B=Both"; | ||||
|     char layer_buffer[16 + 4]; // 3 spaces and one null terminator
 | ||||
|     gdispClear(White); | ||||
|     gdispDrawString(0, 0, layer_help, state->font_fixed5x8, Black); | ||||
|     format_layer_bitmap_string(state->status.default_layer, state->status.layer, layer_buffer); | ||||
|     gdispDrawString(0, 10, layer_buffer, state->font_fixed5x8, Black); | ||||
|     format_layer_bitmap_string(state->status.default_layer >> 16, state->status.layer >> 16, layer_buffer); | ||||
|     gdispDrawString(0, 20, layer_buffer, state->font_fixed5x8, Black); | ||||
|     gdispFlush(); | ||||
|     return false; | ||||
| } | ||||
| #endif // LCD_ENABLE
 | ||||
| 
 | ||||
| bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     (void)state; | ||||
| #ifdef LCD_ENABLE | ||||
|     gdispSetPowerMode(powerOff); | ||||
| #endif | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
|     lcd_backlight_hal_color(0, 0, 0); | ||||
| #endif | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     (void)state; | ||||
| #ifdef LCD_ENABLE | ||||
|     gdispSetPowerMode(powerOn); | ||||
| #endif | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state) { | ||||
|     (void)animation; | ||||
|     (void)state; | ||||
|     dprint("User visualizer inited\n"); | ||||
|     visualizer_enabled = true; | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // TODO: Optimize the stack size, this is probably way too big
 | ||||
| static DECLARE_THREAD_STACK(visualizerThreadStack, 1024); | ||||
| static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { | ||||
|     (void)arg; | ||||
| 
 | ||||
|     GListener event_listener; | ||||
|     geventListenerInit(&event_listener); | ||||
|     geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); | ||||
| 
 | ||||
|     visualizer_keyboard_status_t initial_status = { | ||||
|         .default_layer = 0xFFFFFFFF, | ||||
|         .layer = 0xFFFFFFFF, | ||||
|         .leds = 0xFFFFFFFF, | ||||
|         .suspended = false, | ||||
|     }; | ||||
| 
 | ||||
|     visualizer_state_t state = { | ||||
|         .status = initial_status, | ||||
|         .current_lcd_color = 0, | ||||
| #ifdef LCD_ENABLE | ||||
|         .font_fixed5x8 = gdispOpenFont("fixed_5x8"), | ||||
|         .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12") | ||||
| #endif | ||||
|     }; | ||||
|     initialize_user_visualizer(&state); | ||||
|     state.prev_lcd_color = state.current_lcd_color; | ||||
| 
 | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
|     lcd_backlight_color( | ||||
|             LCD_HUE(state.current_lcd_color), | ||||
|             LCD_SAT(state.current_lcd_color), | ||||
|             LCD_INT(state.current_lcd_color)); | ||||
| #endif | ||||
| 
 | ||||
|     systemticks_t sleep_time = TIME_INFINITE; | ||||
|     systemticks_t current_time = gfxSystemTicks(); | ||||
| 
 | ||||
|     while(true) { | ||||
|         systemticks_t new_time = gfxSystemTicks(); | ||||
|         systemticks_t delta = new_time - current_time; | ||||
|         current_time = new_time; | ||||
|         bool enabled = visualizer_enabled; | ||||
|         if (!same_status(&state.status, ¤t_status)) { | ||||
|             if (visualizer_enabled) { | ||||
|                 if (current_status.suspended) { | ||||
|                     stop_all_keyframe_animations(); | ||||
|                     visualizer_enabled = false; | ||||
|                     state.status = current_status; | ||||
|                     user_visualizer_suspend(&state); | ||||
|                 } | ||||
|                 else { | ||||
|                     state.status = current_status; | ||||
|                     update_user_visualizer_state(&state); | ||||
|                 } | ||||
|                 state.prev_lcd_color = state.current_lcd_color; | ||||
|             } | ||||
|         } | ||||
|         if (!enabled && state.status.suspended && current_status.suspended == false) { | ||||
|             // Setting the status to the initial status will force an update
 | ||||
|             // when the visualizer is enabled again
 | ||||
|             state.status = initial_status; | ||||
|             state.status.suspended = false; | ||||
|             stop_all_keyframe_animations(); | ||||
|             user_visualizer_resume(&state); | ||||
|             state.prev_lcd_color = state.current_lcd_color; | ||||
|         } | ||||
|         sleep_time = TIME_INFINITE; | ||||
|         for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { | ||||
|             if (animations[i]) { | ||||
|                 update_keyframe_animation(animations[i], &state, delta, &sleep_time); | ||||
|             } | ||||
|         } | ||||
| #ifdef LED_ENABLE | ||||
|         gdispGFlush(LED_DISPLAY); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef EMULATOR | ||||
|         draw_emulator(); | ||||
| #endif | ||||
|         // The animation can enable the visualizer
 | ||||
|         // And we might need to update the state when that happens
 | ||||
|         // so don't sleep
 | ||||
|         if (enabled != visualizer_enabled) { | ||||
|             sleep_time = 0; | ||||
|         } | ||||
| 
 | ||||
|         systemticks_t after_update = gfxSystemTicks(); | ||||
|         unsigned update_delta = after_update - current_time; | ||||
|         if (sleep_time != TIME_INFINITE) { | ||||
|             if (sleep_time > update_delta) { | ||||
|                 sleep_time -= update_delta; | ||||
|             } | ||||
|             else { | ||||
|                 sleep_time = 0; | ||||
|             } | ||||
|         } | ||||
|         dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time); | ||||
| #ifdef PROTOCOL_CHIBIOS | ||||
|         // The gEventWait function really takes milliseconds, even if the documentation says ticks.
 | ||||
|         // Unfortunately there's no generic ugfx conversion from system time to milliseconds,
 | ||||
|         // so let's do it in a platform dependent way.
 | ||||
| 
 | ||||
|         // On windows the system ticks is the same as milliseconds anyway
 | ||||
|         if (sleep_time != TIME_INFINITE) { | ||||
|             sleep_time = ST2MS(sleep_time); | ||||
|         } | ||||
| #endif | ||||
|         geventEventWait(&event_listener, sleep_time); | ||||
|     } | ||||
| #ifdef LCD_ENABLE | ||||
|     gdispCloseFont(state.font_fixed5x8); | ||||
|     gdispCloseFont(state.font_dejavusansbold12); | ||||
| #endif | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void visualizer_init(void) { | ||||
| #ifdef LCD_ENABLE | ||||
|     gfxInit(); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
|     lcd_backlight_init(); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_SERIAL_LINK | ||||
|     add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LCD_ENABLE | ||||
|     LCD_DISPLAY = get_lcd_display(); | ||||
| #endif | ||||
| #ifdef LED_ENABLE | ||||
|     LED_DISPLAY = get_led_display(); | ||||
| #endif | ||||
| 
 | ||||
|     // We are using a low priority thread, the idea is to have it run only
 | ||||
|     // when the main thread is sleeping during the matrix scanning
 | ||||
|     gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), | ||||
|                               VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL); | ||||
| } | ||||
| 
 | ||||
| void update_status(bool changed) { | ||||
|     if (changed) { | ||||
|         GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); | ||||
|         if (listener) { | ||||
|             geventSendEvent(listener); | ||||
|         } | ||||
|     } | ||||
| #ifdef USE_SERIAL_LINK | ||||
|     static systime_t last_update = 0; | ||||
|     systime_t current_update = chVTGetSystemTimeX(); | ||||
|     systime_t delta = current_update - last_update; | ||||
|     if (changed || delta > MS2ST(10)) { | ||||
|         last_update = current_update; | ||||
|         visualizer_keyboard_status_t* r = begin_write_current_status(); | ||||
|         *r = current_status; | ||||
|         end_write_current_status(); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds) { | ||||
|     // Note that there's a small race condition here, the thread could read
 | ||||
|     // a state where one of these are set but not the other. But this should
 | ||||
|     // not really matter as it will be fixed during the next loop step.
 | ||||
|     // Alternatively a mutex could be used instead of the volatile variables
 | ||||
| 
 | ||||
|     bool changed = false; | ||||
| #ifdef USE_SERIAL_LINK | ||||
|     if (is_serial_link_connected ()) { | ||||
|         visualizer_keyboard_status_t* new_status = read_current_status(); | ||||
|         if (new_status) { | ||||
|             if (!same_status(¤t_status, new_status)) { | ||||
|                 changed = true; | ||||
|                 current_status = *new_status; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     else { | ||||
| #else | ||||
|    { | ||||
| #endif | ||||
|         visualizer_keyboard_status_t new_status = { | ||||
|             .layer = state, | ||||
|             .default_layer = default_state, | ||||
|             .leds = leds, | ||||
|             .suspended = current_status.suspended, | ||||
|         }; | ||||
|         if (!same_status(¤t_status, &new_status)) { | ||||
|             changed = true; | ||||
|             current_status = new_status; | ||||
|         } | ||||
|     } | ||||
|     update_status(changed); | ||||
| } | ||||
| 
 | ||||
| void visualizer_suspend(void) { | ||||
|     current_status.suspended = true; | ||||
|     update_status(true); | ||||
| } | ||||
| 
 | ||||
| void visualizer_resume(void) { | ||||
|     current_status.suspended = false; | ||||
|     update_status(true); | ||||
| } | ||||
							
								
								
									
										149
									
								
								quantum/visualizer/visualizer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								quantum/visualizer/visualizer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | ||||
| /*
 | ||||
| The MIT License (MIT) | ||||
| 
 | ||||
| Copyright (c) 2016 Fred Sundvik | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| */ | ||||
| 
 | ||||
| #ifndef VISUALIZER_H | ||||
| #define VISUALIZER_H | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #ifdef LCD_ENABLE | ||||
| #include "gfx.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef LCD_BACKLIGHT_ENABLE | ||||
| #include "lcd_backlight.h" | ||||
| #endif | ||||
| 
 | ||||
| // This need to be called once at the start
 | ||||
| void visualizer_init(void); | ||||
| // This should be called at every matrix scan
 | ||||
| void visualizer_update(uint32_t default_state, uint32_t state, uint32_t leds); | ||||
| // This should be called when the keyboard goes to suspend state
 | ||||
| void visualizer_suspend(void); | ||||
| // This should be called when the keyboard wakes up from suspend state
 | ||||
| void visualizer_resume(void); | ||||
| 
 | ||||
| // These functions are week, so they can be overridden by the keyboard
 | ||||
| // if needed
 | ||||
| GDisplay* get_lcd_display(void); | ||||
| GDisplay* get_led_display(void); | ||||
| 
 | ||||
| // For emulator builds, this function need to be implemented
 | ||||
| #ifdef EMULATOR | ||||
| void draw_emulator(void); | ||||
| #endif | ||||
| 
 | ||||
| // If you need support for more than 16 keyframes per animation, you can change this
 | ||||
| #define MAX_VISUALIZER_KEY_FRAMES 16 | ||||
| 
 | ||||
| struct keyframe_animation_t; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint32_t layer; | ||||
|     uint32_t default_layer; | ||||
|     uint32_t leds; // See led.h for available statuses
 | ||||
|     bool suspended; | ||||
| } visualizer_keyboard_status_t; | ||||
| 
 | ||||
| // The state struct is used by the various keyframe functions
 | ||||
| // It's also used for setting the LCD color and layer text
 | ||||
| // from the user customized code
 | ||||
| typedef struct visualizer_state_t { | ||||
|     // The user code should primarily be modifying these
 | ||||
|     uint32_t target_lcd_color; | ||||
|     const char* layer_text; | ||||
| 
 | ||||
|     // The user visualizer(and animation functions) can read these
 | ||||
|     visualizer_keyboard_status_t status; | ||||
| 
 | ||||
|     // These are used by the animation functions
 | ||||
|     uint32_t current_lcd_color; | ||||
|     uint32_t prev_lcd_color; | ||||
| #ifdef LCD_ENABLE | ||||
|     font_t font_fixed5x8; | ||||
|     font_t font_dejavusansbold12; | ||||
| #endif | ||||
| } visualizer_state_t; | ||||
| 
 | ||||
| // Any custom keyframe function should have this signature
 | ||||
| // return true to get continuous updates, otherwise you will only get one
 | ||||
| // update per frame
 | ||||
| typedef bool (*frame_func)(struct keyframe_animation_t*, visualizer_state_t*); | ||||
| 
 | ||||
| // Represents a keyframe animation, so fields are internal to the system
 | ||||
| // while others are meant to be initialized by the user code
 | ||||
| typedef struct keyframe_animation_t { | ||||
|     // These should be initialized
 | ||||
|     int num_frames; | ||||
|     bool loop; | ||||
|     int frame_lengths[MAX_VISUALIZER_KEY_FRAMES]; | ||||
|     frame_func frame_functions[MAX_VISUALIZER_KEY_FRAMES]; | ||||
| 
 | ||||
|     // Used internally by the system, and can also be read by
 | ||||
|     // keyframe update functions
 | ||||
|     int current_frame; | ||||
|     int time_left_in_frame; | ||||
|     bool first_update_of_frame; | ||||
|     bool last_update_of_frame; | ||||
|     bool need_update; | ||||
| 
 | ||||
| } keyframe_animation_t; | ||||
| 
 | ||||
| extern GDisplay* LCD_DISPLAY; | ||||
| extern GDisplay* LED_DISPLAY; | ||||
| 
 | ||||
| void start_keyframe_animation(keyframe_animation_t* animation); | ||||
| void stop_keyframe_animation(keyframe_animation_t* animation); | ||||
| // This runs the next keyframe, but does not update the animation state
 | ||||
| // Useful for crossfades for example
 | ||||
| void run_next_keyframe(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| 
 | ||||
| // Some predefined keyframe functions that can be used by the user code
 | ||||
| // Does nothing, useful for adding delays
 | ||||
| bool keyframe_no_operation(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| // Animates the LCD backlight color between the current color and the target color (of the state)
 | ||||
| bool keyframe_animate_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| // Sets the backlight color to the target color
 | ||||
| bool keyframe_set_backlight_color(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| // Displays the layer text centered vertically on the screen
 | ||||
| bool keyframe_display_layer_text(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| // Displays a bitmap (0/1) of all the currently active layers
 | ||||
| bool keyframe_display_layer_bitmap(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| 
 | ||||
| bool keyframe_disable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| bool keyframe_enable_lcd_and_backlight(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| 
 | ||||
| // Call this once, when the initial animation has finished, alternatively you can call it
 | ||||
| // directly from the initalize_user_visualizer function (the animation can be null)
 | ||||
| bool enable_visualization(keyframe_animation_t* animation, visualizer_state_t* state); | ||||
| 
 | ||||
| // These functions have to be implemented by the user
 | ||||
| void initialize_user_visualizer(visualizer_state_t* state); | ||||
| void update_user_visualizer_state(visualizer_state_t* state); | ||||
| void user_visualizer_suspend(visualizer_state_t* state); | ||||
| void user_visualizer_resume(visualizer_state_t* state); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* VISUALIZER_H */ | ||||
							
								
								
									
										61
									
								
								quantum/visualizer/visualizer.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								quantum/visualizer/visualizer.mk
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| # The MIT License (MIT)
 | ||||
| # 
 | ||||
| # Copyright (c) 2016 Fred Sundvik
 | ||||
| # 
 | ||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy
 | ||||
| # of this software and associated documentation files (the "Software"), to deal
 | ||||
| # in the Software without restriction, including without limitation the rights
 | ||||
| # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | ||||
| # copies of the Software, and to permit persons to whom the Software is
 | ||||
| # furnished to do so, subject to the following conditions:
 | ||||
| # 
 | ||||
| # The above copyright notice and this permission notice shall be included in all
 | ||||
| # copies or substantial portions of the Software.
 | ||||
| # 
 | ||||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | ||||
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | ||||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | ||||
| # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | ||||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | ||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | ||||
| # SOFTWARE.
 | ||||
| 
 | ||||
| GFXLIB = $(VISUALIZER_DIR)/ugfx | ||||
| SRC += $(VISUALIZER_DIR)/visualizer.c | ||||
| UINCDIR += $(GFXINC) $(VISUALIZER_DIR) | ||||
| 
 | ||||
| ifdef LCD_ENABLE | ||||
| UDEFS += -DLCD_ENABLE | ||||
| ULIBS += -lm | ||||
| USE_UGFX = yes | ||||
| endif | ||||
| 
 | ||||
| ifdef LCD_BACKLIGHT_ENABLE | ||||
| SRC += $(VISUALIZER_DIR)/lcd_backlight.c | ||||
| ifndef EMULATOR | ||||
| SRC += lcd_backlight_hal.c | ||||
| endif | ||||
| UDEFS += -DLCD_BACKLIGHT_ENABLE | ||||
| endif | ||||
| 
 | ||||
| ifdef LED_ENABLE | ||||
| SRC += $(VISUALIZER_DIR)/led_test.c | ||||
| UDEFS += -DLED_ENABLE | ||||
| USE_UGFX = yes | ||||
| endif | ||||
| 
 | ||||
| ifdef USE_UGFX | ||||
| include $(GFXLIB)/gfx.mk | ||||
| SRC += $(GFXSRC) | ||||
| UDEFS += $(patsubst %,-D%,$(patsubst -D%,%,$(GFXDEFS))) | ||||
| ULIBS += $(patsubst %,-l%,$(patsubst -l%,%,$(GFXLIBS))) | ||||
| endif | ||||
| 
 | ||||
| ifndef VISUALIZER_USER | ||||
| VISUALIZER_USER = visualizer_user.c | ||||
| endif | ||||
| SRC += $(VISUALIZER_USER) | ||||
| 
 | ||||
| ifdef EMULATOR | ||||
| UINCDIR += $(TMK_DIR)/common | ||||
| endif | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jack Humbert
						Jack Humbert