├── README.md ├── LICENSE ├── alphanumeric.json └── razer_rgb.py /README.md: -------------------------------------------------------------------------------- 1 | # Razer RGB LED Patterns and Scrolling Text 2 | 3 | Some python code for your Razer RGB LED keyboard. Enjoy! 4 | 5 | Here's the drivers repo that worked for my 2016 Razer Blade: 6 | https://github.com/openrazer/openrazer-drivers 7 | 8 | This is another repo that works for a lot of other machines and peripherals: 9 | https://github.com/terrycain/razer-drivers 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Ross Goodwin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /alphanumeric.json: -------------------------------------------------------------------------------- 1 | { 2 | "A": [ 3 | [0,1],[0,2],[0,3],[0,4],[1,0],[2,0], 4 | [3,1],[1,2],[2,2],[3,2],[3,3],[3,4] 5 | ], 6 | "B": [ 7 | [0,0],[0,1],[0,2],[0,3],[0,4], 8 | [1,0],[1,2],[1,4], 9 | [2,0],[2,2],[2,4], 10 | [3,1],[3,3] 11 | ], 12 | "C": [ 13 | [0,1],[0,2],[0,3], 14 | [1,0],[2,0],[3,0], 15 | [1,4],[2,4],[3,4] 16 | ], 17 | "D": [ 18 | [0,0],[0,1],[0,2],[0,3],[0,4], 19 | [1,0],[2,0],[1,4],[2,4], 20 | [3,1],[3,2],[3,3] 21 | ], 22 | "E": [ 23 | [0,0],[0,1],[0,2],[0,3],[0,4], 24 | [1,0],[2,0],[3,0], 25 | [1,2],[2,2], 26 | [1,4],[2,4],[3,4] 27 | ], 28 | "F": [ 29 | [0,0],[0,1],[0,2],[0,3],[0,4], 30 | [1,0],[2,0],[3,0], 31 | [1,2],[2,2] 32 | ], 33 | "G": [ 34 | [0,1],[0,2],[0,3], 35 | [1,0],[2,0],[3,0], 36 | [1,4],[2,4], 37 | [3,3], 38 | [2,2],[3,2] 39 | ], 40 | "H": [ 41 | [0,0],[0,1],[0,2],[0,3],[0,4], 42 | [3,0],[3,1],[3,2],[3,3],[3,4], 43 | [1,2],[2,2] 44 | ], 45 | "I": [ 46 | [0,0],[1,0],[2,0], 47 | [1,1],[1,2],[1,3], 48 | [0,4],[1,4],[2,4] 49 | ], 50 | "J": [ 51 | [0,0],[1,0],[2,0],[3,0], 52 | [2,1],[2,2],[2,3],[2,4], 53 | [0,3],[0,4],[1,4] 54 | ], 55 | "K": [ 56 | [0,0],[0,1],[0,2],[0,3],[0,4], 57 | [3,0],[2,1],[1,2],[2,3],[3,4] 58 | ], 59 | "L": [ 60 | [0,0],[0,1],[0,2],[0,3],[0,4], 61 | [1,4],[2,4],[3,4] 62 | ], 63 | "M": [ 64 | [0,0],[0,1],[0,2],[0,3],[0,4], 65 | [4,0],[4,1],[4,2],[4,3],[4,4], 66 | [1,1],[2,2],[3,1] 67 | ], 68 | "N": [ 69 | [0,0],[0,1],[0,2],[0,3],[0,4], 70 | [4,0],[4,1],[4,2],[4,3],[4,4], 71 | [1,1],[2,2],[3,3] 72 | ], 73 | "O": [ 74 | [0,1],[0,2],[0,3], 75 | [3,1],[3,2],[3,3], 76 | [1,0],[2,0], 77 | [1,4],[2,4] 78 | ], 79 | "P": [ 80 | [0,0],[0,1],[0,2],[0,3],[0,4], 81 | [1,0],[2,0], 82 | [3,1], 83 | [1,2],[2,2] 84 | ], 85 | "Q": [ 86 | [0,1],[0,2],[0,3], 87 | [3,1],[3,2],[3,3], 88 | [1,0],[2,0], 89 | [1,4],[2,4], 90 | [2,3],[3,4],[4,5] 91 | ], 92 | "R": [ 93 | [0,0],[0,1],[0,2],[0,3],[0,4], 94 | [1,0],[2,0],[3,0], 95 | [3,1], 96 | [1,2],[2,2], 97 | [2,3],[2,4],[3,4] 98 | ], 99 | "S": [ 100 | [1,0],[2,0],[3,0], 101 | [0,4],[1,4],[2,4], 102 | [0,1],[1,2],[2,2],[3,3] 103 | ], 104 | "T": [ 105 | [0,0],[1,0],[2,0],[3,0],[4,0], 106 | [2,1],[2,2],[2,3],[2,4] 107 | ], 108 | "U": [ 109 | [0,0],[0,1],[0,2],[0,3], 110 | [3,0],[3,1],[3,2],[3,3], 111 | [1,4],[2,4] 112 | ], 113 | "V": [ 114 | [0,0],[0,1], 115 | [4,0],[4,1], 116 | [1,2],[1,3], 117 | [3,2],[3,3], 118 | [2,4] 119 | ], 120 | "W": [ 121 | [0,0],[0,1],[0,2],[0,3],[0,4], 122 | [4,0],[4,1],[4,2],[4,3],[4,4], 123 | [1,3],[2,2],[3,3] 124 | ], 125 | "X": [ 126 | [0,0],[1,1],[2,2],[3,3],[4,4], 127 | [0,4],[1,3],[3,1],[4,0] 128 | 129 | ], 130 | "Y": [ 131 | [0,0],[0,1],[4,0],[4,1], 132 | [1,2],[3,2], 133 | [2,3],[2,4] 134 | ], 135 | "Z": [ 136 | [0,0],[1,0],[2,0],[3,0], 137 | [0,4],[1,4],[2,4],[3,4], 138 | [3,1], 139 | [1,2],[2,2], 140 | [0,3] 141 | ], 142 | "0": [ 143 | [0,1],[0,2],[0,3], 144 | [3,1],[3,2],[3,3], 145 | [1,0],[2,0], 146 | [1,4],[2,4] 147 | ], 148 | "1": [ 149 | [2,0],[2,1],[2,2],[2,3],[2,4], 150 | [0,2],[1,1] 151 | ], 152 | "2": [ 153 | [1,0],[2,0], 154 | [0,1],[3,1], 155 | [2,2], 156 | [1,3], 157 | [0,4],[1,4],[2,4],[3,4] 158 | ], 159 | "3": [ 160 | [0,0],[1,0],[2,0], 161 | [3,1], 162 | [1,2],[2,2], 163 | [3,3], 164 | [0,4],[1,4],[2,4] 165 | ], 166 | "4": [ 167 | [0,0],[3,0], 168 | [0,1],[3,1], 169 | [0,2],[1,2],[2,2],[3,2], 170 | [3,3],[3,4] 171 | ], 172 | "5": [ 173 | [0,0],[1,0],[2,0],[3,0], 174 | [0,1], 175 | [0,2],[1,2],[2,2], 176 | [3,3], 177 | [0,4],[1,4],[2,4] 178 | ], 179 | "6": [ 180 | [1,0],[2,0],[3,0], 181 | [0,1], 182 | [1,2],[2,2], 183 | [0,3],[3,3], 184 | [1,4],[2,4] 185 | ], 186 | "7": [ 187 | [0,0],[1,0],[2,0],[3,0], 188 | [0,4],[1,3],[2,2],[3,1] 189 | ], 190 | "8": [ 191 | [1,0],[2,0], 192 | [0,1],[3,1], 193 | [1,2],[2,2], 194 | [0,3],[3,3], 195 | [1,4],[2,4] 196 | ], 197 | "9": [ 198 | [1,0],[2,0], 199 | [0,1],[3,1], 200 | [1,2],[2,2],[3,2], 201 | [3,3], 202 | [1,4],[2,4] 203 | ] 204 | } -------------------------------------------------------------------------------- /razer_rgb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import math 5 | from numpy import interp 6 | from random import choice, sample 7 | from time import sleep 8 | from math import log1p 9 | import json 10 | import string 11 | 12 | ROOT = "/sys/bus/hid/drivers/hid-razer/0003:1532:020F.0001" 13 | ROW_COUNT = 6 14 | COL_COUNT = 16 15 | 16 | def clamp(x): 17 | return max(0, min(x, 255)) 18 | 19 | def write_to_file(filename, value): 20 | with open(os.path.join(ROOT, filename), 'w') as outfile: 21 | outfile.write(value) 22 | 23 | def set_keyboard_rgb(rgb_list): 24 | """ 25 | Set all keys rgb values. Takes list of tups. 26 | """ 27 | hex_str = ''.join( 28 | map( 29 | lambda tup: ''.join(map(chr, tup)), 30 | rgb_list 31 | ) 32 | ) 33 | 34 | write_to_file('set_key_colors', hex_str) 35 | 36 | def solid_color(*rgb): 37 | rgb_list = [rgb]*ROW_COUNT*COL_COUNT 38 | set_keyboard_rgb(rgb_list) 39 | 40 | def two_color_noise(rgb1,rgb2,variety=64,burst=True,secs=10,per_sec=10): 41 | def set_colors(): 42 | rgb_list = sample([rgb1, rgb2]*ROW_COUNT*COL_COUNT*16, ROW_COUNT*COL_COUNT) 43 | for i in range(ROW_COUNT*COL_COUNT): 44 | r,g,b = rgb_list[i] 45 | r += choice(range(-variety/2, variety/2)) 46 | g += choice(range(-variety/2, variety/2)) 47 | b += choice(range(-variety/2, variety/2)) 48 | rgb_list[i] = tuple(map(clamp, [r,g,b])) 49 | set_keyboard_rgb(rgb_list) 50 | 51 | if burst: 52 | for _ in range(secs*per_sec): 53 | set_colors() 54 | sleep(1.0/per_sec) 55 | else: 56 | set_colors() 57 | 58 | def monochrome_noise(red,green,blue,variety=64,burst=True,secs=10,per_sec=10): 59 | def set_colors(): 60 | rgb_list = [(red,green,blue)]*ROW_COUNT*COL_COUNT 61 | for i in range(ROW_COUNT*COL_COUNT): 62 | r,g,b = rgb_list[i] 63 | r += choice(range(-variety/2, variety/2)) 64 | g += choice(range(-variety/2, variety/2)) 65 | b += choice(range(-variety/2, variety/2)) 66 | rgb_list[i] = tuple(map(clamp, [r,g,b])) 67 | # print rgb_list 68 | set_keyboard_rgb(rgb_list) 69 | 70 | if burst: 71 | for _ in range(secs*per_sec): 72 | set_colors() 73 | sleep(1.0/per_sec) 74 | else: 75 | set_colors() 76 | 77 | def random_burst(secs=10, per_sec=10, bright=False, sparseness=0): 78 | for interval in range(secs*per_sec): 79 | if bright: 80 | rng = [0,255] 81 | else: 82 | rng = range(256) 83 | 84 | rgb_list = [ 85 | choice([tuple([choice(rng) for x in range(3)])]+[(0,0,0)]*sparseness) for y in range(ROW_COUNT*COL_COUNT) 86 | ] 87 | 88 | # print rgb_list 89 | 90 | set_keyboard_rgb(rgb_list) 91 | 92 | sleep(1.0/per_sec) 93 | 94 | def perlin_noise(secs=20, per_sec=15, vertical=False): 95 | from noise import pnoise3 96 | t = 0.0 97 | y = 0.0 98 | x = 0.0 99 | random_base = choice(range(512)) 100 | for interval in range(secs*per_sec): 101 | key_vals = [list() for _ in range(ROW_COUNT)] 102 | for i in range(ROW_COUNT): 103 | y += 3.3 104 | for j in range(COL_COUNT): 105 | x += 3.3 106 | r_val = clamp(int(pnoise3(x,y,t, octaves=8, repeatx=1, repeaty=1, repeatz=512, base=random_base) * 256)) 107 | g_val = clamp(int(pnoise3(x,y,t, octaves=8, repeatx=1, repeaty=1, repeatz=512, base=random_base+19) * 256)) 108 | b_val = clamp(int(pnoise3(x,y,t, octaves=8, repeatx=1, repeaty=1, repeatz=512, base=random_base+61) * 256)) 109 | # print r_val, g_val, b_val 110 | key_vals[i].append( (r_val, g_val, b_val) ) 111 | 112 | key_list = list() 113 | for row_list in key_vals: 114 | key_list.extend(row_list) 115 | 116 | set_keyboard_rgb(key_list) 117 | 118 | sleep(1.0/per_sec) 119 | 120 | t += 0.01 121 | 122 | 123 | def r_wipe(count=5, r_color=(255,0,0), bg_color=(0,255,0), twinkle=True, line=False): 124 | 125 | def make_random_color(dominant_ix, variety): 126 | init_rgb = sample(range(variety)*3, 3) 127 | init_rgb[dominant_ix] = choice(range(256-variety,256)) 128 | return tuple(init_rgb) 129 | 130 | if line: 131 | starting_pt = 0 132 | line_variance = 64 133 | else: 134 | starting_pt = -3 135 | line_variance = 1 136 | 137 | for interval in range(count): 138 | for i in range(starting_pt, COL_COUNT): 139 | if twinkle: 140 | dominant_bg_ix = bg_color.index(max(bg_color)) 141 | rgb_list = [ 142 | make_random_color(dominant_bg_ix, 100) for y in range(ROW_COUNT*COL_COUNT) 143 | ] 144 | else: 145 | rgb_list = [bg_color]*ROW_COUNT*COL_COUNT 146 | 147 | # if i >= 0: 148 | rl = [i+x for x in range(0,ROW_COUNT*COL_COUNT,16)] 149 | 150 | if not line: 151 | if -3 <= i <= -1: 152 | to_add = [ rl[0]+3, rl[1]+3, rl[4]+3, rl[5]+3 ] 153 | elif -2 <= i <= -1: 154 | to_add = [ rl[0]+2, rl[0]+3, rl[1]+3, rl[2]+2, rl[3]+2, rl[4]+2, rl[4]+3, rl[5]+3 ] 155 | elif -1 <= i <= 12: 156 | to_add = [ rl[0]+1, rl[0]+2, rl[0]+3, rl[1]+3, rl[2]+1, rl[2]+2, rl[3]+2, rl[4]+2, rl[4]+3, rl[5]+3 ] 157 | elif -1 <= i <= 13: 158 | to_add = [ rl[0]+1, rl[0]+2, rl[2]+1, rl[2]+2, rl[3]+2, rl[4]+2 ] 159 | elif -1 <= i <= 14: 160 | to_add = [ rl[0]+1, rl[2]+1 ] 161 | 162 | if rl < 0: 163 | rl = to_add 164 | else: 165 | rl.extend(to_add) 166 | 167 | dominant_r_ix = r_color.index(max(r_color)) 168 | for ix in rl: 169 | rgb_list[ix] = make_random_color(dominant_r_ix, line_variance) 170 | 171 | set_keyboard_rgb(rgb_list) 172 | 173 | sleep( log1p( 0.3 / ( abs(6-i)+1 ) ) ) 174 | 175 | def scrolling_text(msg, text_color=(255,0,0), bg_color=(0,255,0), twinkle=True, variety=128, speed=10): 176 | with open('alphanumeric.json', 'r') as infile: 177 | alpha = json.load(infile) 178 | 179 | master_coords = list() 180 | starting_x = 6 181 | for c in msg: 182 | if c in set(list(string.ascii_letters+string.digits)): 183 | coords = alpha[c.upper()] 184 | for x,y in coords: 185 | master_coords.append( (x+starting_x, y) ) 186 | 187 | if c.upper() in ['1', 'I']: 188 | starting_x += 4 189 | elif c.upper() in ['M', 'N', 'Q', 'T', 'V', 'W', 'X']: 190 | starting_x += 6 191 | else: 192 | starting_x += 5 193 | elif c == ' ': 194 | starting_x += 3 195 | 196 | x_notch_count = max(master_coords, key=lambda x: x[0])[0]+COL_COUNT+6 197 | 198 | for i in range(x_notch_count): 199 | key_color_map = [ [bg_color for x in range(COL_COUNT)] for y in range(ROW_COUNT) ] 200 | if twinkle: 201 | for y in range(ROW_COUNT): 202 | for x in range(COL_COUNT): 203 | r,g,b = key_color_map[y][x] 204 | r += choice(range(-variety/2, variety/2)) 205 | g += choice(range(-variety/2, variety/2)) 206 | b += choice(range(-variety/2, variety/2)) 207 | key_color_map[y][x] = tuple(map(clamp, [r,g,b])) 208 | # print key_color_map 209 | 210 | on_screen_coords = filter(lambda (x,y): i-COL_COUNT < x <= i, master_coords) 211 | actual_coords = map(lambda (x, y): ((COL_COUNT-1)-i+x, y), on_screen_coords) 212 | 213 | for x,y in actual_coords: 214 | # print x, y 215 | key_color_map[y][x] = text_color 216 | 217 | key_color_list = list() 218 | for l in key_color_map: 219 | key_color_list.extend(l) 220 | 221 | set_keyboard_rgb(key_color_list) 222 | 223 | sleep(1.0/speed) 224 | 225 | # test ROOT 226 | root_confirmed = False 227 | i = 0 228 | while not root_confirmed: 229 | try: 230 | write_to_file('brightness', '0') 231 | except IOError: 232 | ROOT = ROOT[:-1] + str(i) 233 | i += 1 234 | else: 235 | root_confirmed = True 236 | 237 | 238 | 239 | if __name__ == '__main__': 240 | write_to_file('brightness', '255') 241 | scrolling_text('hello world', bg_color=(0,0,0), text_color=(255,255,255), speed=8, variety=32) 242 | perlin_noise() 243 | write_to_file('brightness', '128') 244 | sleep(0.2) 245 | write_to_file('brightness', '64') 246 | sleep(0.2) 247 | write_to_file('brightness', '32') --------------------------------------------------------------------------------