diff options
Diffstat (limited to 'keyboards/lily58/keymaps/druotoni/draw_helper.c')
| -rw-r--r-- | keyboards/lily58/keymaps/druotoni/draw_helper.c | 768 |
1 files changed, 768 insertions, 0 deletions
diff --git a/keyboards/lily58/keymaps/druotoni/draw_helper.c b/keyboards/lily58/keymaps/druotoni/draw_helper.c new file mode 100644 index 000000000..c6761d725 --- /dev/null +++ b/keyboards/lily58/keymaps/druotoni/draw_helper.c | |||
| @@ -0,0 +1,768 @@ | |||
| 1 | // Copyright 2021 Nicolas Druoton (druotoni) | ||
| 2 | // Copyright 2021 ugfx | ||
| 3 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 4 | |||
| 5 | #include QMK_KEYBOARD_H | ||
| 6 | |||
| 7 | #include "draw_helper.h" | ||
| 8 | #include "fast_random.h" | ||
| 9 | |||
| 10 | void drawline(uint8_t x, uint8_t y, uint8_t width, bool bHorizontal, bool bPositiveDirection, bool color) { | ||
| 11 | if (width <= 0) return; | ||
| 12 | uint8_t yPlus = 0; | ||
| 13 | uint8_t yMois = 0; | ||
| 14 | uint8_t nbtour = 0; | ||
| 15 | |||
| 16 | if (!bPositiveDirection) { | ||
| 17 | if (bHorizontal) { | ||
| 18 | x -= width; | ||
| 19 | } else { | ||
| 20 | y -= width; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | yMois = (width / 2) - 1 + (width % 2); | ||
| 25 | |||
| 26 | yPlus = (width / 2); | ||
| 27 | nbtour = (width / 4) + 1; | ||
| 28 | |||
| 29 | bool bWhite = color; | ||
| 30 | |||
| 31 | if (bHorizontal) { | ||
| 32 | for (uint8_t i = 0; i < nbtour; i++) { | ||
| 33 | oled_write_pixel(x + yPlus + i, y, bWhite); | ||
| 34 | oled_write_pixel(x + yMois - i, y, bWhite); | ||
| 35 | |||
| 36 | oled_write_pixel(x + i, y, bWhite); | ||
| 37 | oled_write_pixel(x + width - 1 - i, y, bWhite); | ||
| 38 | } | ||
| 39 | } else { | ||
| 40 | for (uint8_t i = 0; i < nbtour; i++) { | ||
| 41 | oled_write_pixel(x, y + yPlus + i, bWhite); | ||
| 42 | oled_write_pixel(x, y + yMois - i, bWhite); | ||
| 43 | |||
| 44 | oled_write_pixel(x, y + i, bWhite); | ||
| 45 | |||
| 46 | oled_write_pixel(x, y + width - 1 - i, bWhite); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | void drawline_vb(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, true, color); } | ||
| 52 | |||
| 53 | void drawline_vt(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, false, false, color); } | ||
| 54 | |||
| 55 | void drawline_hr(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, true, color); } | ||
| 56 | |||
| 57 | void drawline_hl(uint8_t x, uint8_t y, uint8_t width, bool color) { drawline(x, y, width, true, false, color); } | ||
| 58 | |||
| 59 | void draw_rectangle(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 60 | drawline_hr(x, y, width, color); | ||
| 61 | drawline_hr(x, y + heigth - 1, width, color); | ||
| 62 | drawline_vb(x, y, heigth, color); | ||
| 63 | drawline_vb(x + width - 1, y, heigth, color); | ||
| 64 | } | ||
| 65 | |||
| 66 | void draw_rectangle_fill(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 67 | for (uint8_t i = 0; i < heigth; i++) { | ||
| 68 | drawline_hr(x, y + i, width, color); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | void drawline_hr_heigth(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, bool color) { | ||
| 73 | for (int i = 0; i < heigth; i++) { | ||
| 74 | drawline_hr(x, y - i, width, color); | ||
| 75 | drawline_hr(x, y + i, width, color); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | void drawline_point_hr(short x, short y, short x1, bool color) { | ||
| 80 | if (y < 0 || y > 127) return; | ||
| 81 | |||
| 82 | if (x1 < x) { | ||
| 83 | short iTemp = x; | ||
| 84 | x = x1; | ||
| 85 | x1 = iTemp; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (x1 > 31) x1 = 31; | ||
| 89 | if (x < 0) x = 0; | ||
| 90 | if (x > 31) x = 31; | ||
| 91 | |||
| 92 | drawline(x, y, x1 - x, true, true, color); | ||
| 93 | } | ||
| 94 | |||
| 95 | void flip_flap_x(short px, short py, uint8_t val, bool color) { | ||
| 96 | oled_write_pixel(px + val, py, color); | ||
| 97 | oled_write_pixel(px - val, py, color); | ||
| 98 | } | ||
| 99 | |||
| 100 | void draw_circle(uint8_t x, uint8_t y, uint8_t radius, bool color) { | ||
| 101 | short a, b, P; | ||
| 102 | |||
| 103 | // Calculate intermediates | ||
| 104 | a = 1; | ||
| 105 | b = radius; | ||
| 106 | P = 4 - radius; | ||
| 107 | |||
| 108 | short py, px; | ||
| 109 | |||
| 110 | // Away we go using Bresenham's circle algorithm | ||
| 111 | // Optimized to prevent double drawing | ||
| 112 | px = x; | ||
| 113 | py = y + b; | ||
| 114 | oled_write_pixel(px, py, color); | ||
| 115 | px = x; | ||
| 116 | py = y - b; | ||
| 117 | oled_write_pixel(px, py, color); | ||
| 118 | |||
| 119 | flip_flap_x(x, y, b, color); | ||
| 120 | |||
| 121 | do { | ||
| 122 | flip_flap_x(x, y + b, a, color); | ||
| 123 | flip_flap_x(x, y - b, a, color); | ||
| 124 | flip_flap_x(x, y + a, b, color); | ||
| 125 | flip_flap_x(x, y - a, b, color); | ||
| 126 | |||
| 127 | if (P < 0) | ||
| 128 | P += 3 + 2 * a++; | ||
| 129 | else | ||
| 130 | P += 5 + 2 * (a++ - b--); | ||
| 131 | } while (a < b); | ||
| 132 | |||
| 133 | flip_flap_x(x, y + b, a, color); | ||
| 134 | flip_flap_x(x, y - b, a, color); | ||
| 135 | } | ||
| 136 | |||
| 137 | void draw_ellipse(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) { | ||
| 138 | int dx, dy; | ||
| 139 | int a2, b2; | ||
| 140 | int err, e2; | ||
| 141 | |||
| 142 | // short py, px; | ||
| 143 | // Calculate intermediates | ||
| 144 | dx = 0; | ||
| 145 | dy = b; | ||
| 146 | a2 = a * a; | ||
| 147 | b2 = b * b; | ||
| 148 | err = b2 - (2 * b - 1) * a2; | ||
| 149 | |||
| 150 | // Away we go using Bresenham's ellipse algorithm | ||
| 151 | do { | ||
| 152 | flip_flap_x(x, y + dy, dx, color); | ||
| 153 | flip_flap_x(x, y - dy, dx, color); | ||
| 154 | |||
| 155 | e2 = 2 * err; | ||
| 156 | if (e2 < (2 * dx + 1) * b2) { | ||
| 157 | dx++; | ||
| 158 | err += (2 * dx + 1) * b2; | ||
| 159 | } | ||
| 160 | if (e2 > -(2 * dy - 1) * a2) { | ||
| 161 | dy--; | ||
| 162 | err -= (2 * dy - 1) * a2; | ||
| 163 | } | ||
| 164 | } while (dy >= 0); | ||
| 165 | } | ||
| 166 | |||
| 167 | void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, bool color) { return; } | ||
| 168 | // void draw_ellipse_fill(uint8_t x, uint8_t y, uint8_t a, uint8_t b, uint8_t color) { | ||
| 169 | // int dx, dy; | ||
| 170 | // int a2, b2; | ||
| 171 | // int err, e2; | ||
| 172 | |||
| 173 | // // Calculate intermediates | ||
| 174 | // dx = 0; | ||
| 175 | // dy = b; | ||
| 176 | // a2 = a * a; | ||
| 177 | // b2 = b * b; | ||
| 178 | // err = b2 - (2 * b - 1) * a2; | ||
| 179 | |||
| 180 | // short py, px, px1; | ||
| 181 | |||
| 182 | // // Away we go using Bresenham's ellipse algorithm | ||
| 183 | // // This is optimized to prevent overdrawing by drawing a line only when a y is about to change value | ||
| 184 | // do { | ||
| 185 | // e2 = 2 * err; | ||
| 186 | // if (e2 < (2 * dx + 1) * b2) { | ||
| 187 | // dx++; | ||
| 188 | // err += (2 * dx + 1) * b2; | ||
| 189 | // } | ||
| 190 | // if (e2 > -(2 * dy - 1) * a2) { | ||
| 191 | // py = y + dy; | ||
| 192 | // px = x - dx; | ||
| 193 | // px1 = x + dx; | ||
| 194 | // drawline_point_hr(px, py, px1, color); | ||
| 195 | // if (y) { | ||
| 196 | // py = y - dy; | ||
| 197 | // px = x - dx; | ||
| 198 | // px1 = x + dx; | ||
| 199 | // drawline_point_hr(px, py, px1, color); | ||
| 200 | // } | ||
| 201 | // dy--; | ||
| 202 | // err -= (2 * dy - 1) * a2; | ||
| 203 | // } | ||
| 204 | // } while (dy >= 0); | ||
| 205 | // } | ||
| 206 | |||
| 207 | bool test_limit(short x, short y) { return !(y < 0 || y > 127 || x < 0 || x > 31); } | ||
| 208 | |||
| 209 | void flip_flap_y_point(short px, short py, short px1, uint8_t val, bool color) { | ||
| 210 | // firmware size optimisation : one fonction for 2 lines of code | ||
| 211 | drawline_point_hr(px, py + val, px1, color); | ||
| 212 | drawline_point_hr(px, py - val, px1, color); | ||
| 213 | } | ||
| 214 | |||
| 215 | void draw_fill_circle(short x, short y, uint8_t radius, bool color) { | ||
| 216 | short a, b, P; | ||
| 217 | |||
| 218 | // Calculate intermediates | ||
| 219 | a = 1; | ||
| 220 | b = radius; | ||
| 221 | P = 4 - radius; | ||
| 222 | |||
| 223 | // Away we go using Bresenham's circle algorithm | ||
| 224 | // This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value | ||
| 225 | short py, px, px1; | ||
| 226 | |||
| 227 | py = y; | ||
| 228 | px = x - b; | ||
| 229 | px1 = x + b; | ||
| 230 | drawline_point_hr(px, py, px1, color); | ||
| 231 | |||
| 232 | py = y + b; | ||
| 233 | px = x; | ||
| 234 | if (test_limit(px, py)) oled_write_pixel(px, py, color); | ||
| 235 | py = y - b; | ||
| 236 | px = x; | ||
| 237 | if (test_limit(px, py)) oled_write_pixel(px, py, color); | ||
| 238 | do { | ||
| 239 | flip_flap_y_point(x - b, y, x + b, a, color); | ||
| 240 | |||
| 241 | if (P < 0) { | ||
| 242 | P += 3 + 2 * a++; | ||
| 243 | } else { | ||
| 244 | flip_flap_y_point(x - a, y, x + a, b, color); | ||
| 245 | |||
| 246 | P += 5 + 2 * (a++ - b--); | ||
| 247 | } | ||
| 248 | } while (a < b); | ||
| 249 | |||
| 250 | flip_flap_y_point(x - b, y, x + b, a, color); | ||
| 251 | } | ||
| 252 | |||
| 253 | bool apres_moitie(int a, int b) { return (a > b / 2); } | ||
| 254 | bool arrive_moitie(int a, int b) { return (a > b / 2); } | ||
| 255 | bool avant_moitie(int a, int b) { return (a <= b / 2 && !apres_moitie(a, b)); } | ||
| 256 | |||
| 257 | void draw_arc_sector(uint8_t x, uint8_t y, uint8_t radius, unsigned char sectors, unsigned char half, bool color) { | ||
| 258 | short a, b, P; | ||
| 259 | short py, px; | ||
| 260 | // Calculate intermediates | ||
| 261 | a = 1; // x in many explanations | ||
| 262 | b = radius; // y in many explanations | ||
| 263 | P = 4 - radius; | ||
| 264 | |||
| 265 | if (half != 2) { | ||
| 266 | // Away we go using Bresenham's circle algorithm | ||
| 267 | // Optimized to prevent double drawing | ||
| 268 | if (sectors & 0x06) { | ||
| 269 | px = x; | ||
| 270 | py = y - b; | ||
| 271 | oled_write_pixel(px, py, color); | ||
| 272 | } // Upper upper | ||
| 273 | if (sectors & 0x60) { | ||
| 274 | px = x; | ||
| 275 | py = y + b; | ||
| 276 | oled_write_pixel(px, py, color); | ||
| 277 | } // Lower lower | ||
| 278 | if (sectors & 0x81) { | ||
| 279 | px = x + b; | ||
| 280 | py = y; | ||
| 281 | oled_write_pixel(px, py, color); | ||
| 282 | } // Right right | ||
| 283 | if (sectors & 0x18) { | ||
| 284 | px = x - b; | ||
| 285 | py = y; | ||
| 286 | oled_write_pixel(px, py, color); | ||
| 287 | } // Left left | ||
| 288 | } | ||
| 289 | |||
| 290 | bool dessiner = false; | ||
| 291 | |||
| 292 | do { | ||
| 293 | if (half == 1 && arrive_moitie(a, b)) break; | ||
| 294 | |||
| 295 | if (half == 2 && avant_moitie(a, b)) { | ||
| 296 | dessiner = false; | ||
| 297 | } else { | ||
| 298 | dessiner = true; | ||
| 299 | } | ||
| 300 | |||
| 301 | if (dessiner) { | ||
| 302 | if (sectors & 0x01) { | ||
| 303 | px = x + b; | ||
| 304 | py = y - a; | ||
| 305 | oled_write_pixel(px, py, color); | ||
| 306 | } // Upper right right | ||
| 307 | if (sectors & 0x02) { | ||
| 308 | px = x + a; | ||
| 309 | py = y - b; | ||
| 310 | oled_write_pixel(px, py, color); | ||
| 311 | } // Upper upper right | ||
| 312 | if (sectors & 0x04) { | ||
| 313 | px = x - a; | ||
| 314 | py = y - b; | ||
| 315 | oled_write_pixel(px, py, color); | ||
| 316 | } // Upper upper left | ||
| 317 | if (sectors & 0x08) { | ||
| 318 | px = x - b; | ||
| 319 | py = y - a; | ||
| 320 | oled_write_pixel(px, py, color); | ||
| 321 | } // Upper left left | ||
| 322 | if (sectors & 0x10) { | ||
| 323 | px = x - b; | ||
| 324 | py = y + a; | ||
| 325 | oled_write_pixel(px, py, color); | ||
| 326 | } // Lower left left | ||
| 327 | if (sectors & 0x20) { | ||
| 328 | px = x - a; | ||
| 329 | py = y + b; | ||
| 330 | oled_write_pixel(px, py, color); | ||
| 331 | } // Lower lower left | ||
| 332 | if (sectors & 0x40) { | ||
| 333 | px = x + a; | ||
| 334 | py = y + b; | ||
| 335 | oled_write_pixel(px, py, color); | ||
| 336 | } // Lower lower right | ||
| 337 | if (sectors & 0x80) { | ||
| 338 | px = x + b; | ||
| 339 | py = y + a; | ||
| 340 | oled_write_pixel(px, py, color); | ||
| 341 | } // Lower right right | ||
| 342 | } | ||
| 343 | |||
| 344 | if (P < 0) | ||
| 345 | P += 3 + 2 * a++; | ||
| 346 | else | ||
| 347 | P += 5 + 2 * (a++ - b--); | ||
| 348 | } while (a < b); | ||
| 349 | |||
| 350 | if (half != 1) { | ||
| 351 | if (sectors & 0xC0) { | ||
| 352 | px = x + a; | ||
| 353 | py = y + b; | ||
| 354 | oled_write_pixel(px, py, color); | ||
| 355 | } // Lower right | ||
| 356 | if (sectors & 0x03) { | ||
| 357 | px = x + a; | ||
| 358 | py = y - b; | ||
| 359 | oled_write_pixel(px, py, color); | ||
| 360 | } // Upper right | ||
| 361 | if (sectors & 0x30) { | ||
| 362 | px = x - a; | ||
| 363 | py = y + b; | ||
| 364 | oled_write_pixel(px, py, color); | ||
| 365 | } // Lower left | ||
| 366 | if (sectors & 0x0C) { | ||
| 367 | px = x - a; | ||
| 368 | py = y - b; | ||
| 369 | oled_write_pixel(px, py, color); | ||
| 370 | } // Upper left | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | void draw_static(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int color, uint8_t density) { | ||
| 375 | unsigned long rx = fastrand_long(); | ||
| 376 | unsigned long ry = fastrand_long(); | ||
| 377 | unsigned long maskx = 1; | ||
| 378 | unsigned long masky = 1; | ||
| 379 | unsigned long mask_base = 1; | ||
| 380 | |||
| 381 | // more 1 in the octet | ||
| 382 | for (int r = 0; r < density; r++) { | ||
| 383 | rx &= fastrand_long(); | ||
| 384 | ry &= fastrand_long(); | ||
| 385 | } | ||
| 386 | |||
| 387 | color = ((rx >> 1) % 2) == 0; | ||
| 388 | |||
| 389 | for (uint8_t i = 0; i < width; i++) { | ||
| 390 | for (uint8_t j = 0; j < heigth; j++) { | ||
| 391 | // new mask based on ij loop | ||
| 392 | maskx = (mask_base << i); | ||
| 393 | masky = (mask_base << j); | ||
| 394 | |||
| 395 | // logic AND with the masks | ||
| 396 | if (((rx & maskx) == maskx) && ((ry & masky) == masky)) { | ||
| 397 | oled_write_pixel(x + i, y + j, color); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | void copy_pixel(int from, int shift, unsigned char mask) { | ||
| 404 | if (shift == 0) return; | ||
| 405 | |||
| 406 | // pixel cluster from | ||
| 407 | char c_from = get_oled_char(from); | ||
| 408 | char extract = c_from & mask; | ||
| 409 | |||
| 410 | // pixel cluster shift | ||
| 411 | char c_from_shift = get_oled_char(from + shift); | ||
| 412 | c_from_shift &= ~(mask); | ||
| 413 | c_from_shift |= extract; | ||
| 414 | oled_write_raw_byte(c_from_shift, from + shift); | ||
| 415 | |||
| 416 | // fill blank with black | ||
| 417 | c_from &= ~(mask); | ||
| 418 | oled_write_raw_byte(c_from, from); | ||
| 419 | } | ||
| 420 | |||
| 421 | void draw_glitch_comb(uint8_t x, uint8_t y, uint8_t width, uint16_t height, uint8_t iSize, bool odd) { | ||
| 422 | // work only on row | ||
| 423 | uint16_t y_start = (y / 8) * 32; | ||
| 424 | uint8_t nb_h = height / 8; | ||
| 425 | |||
| 426 | uint8_t w_max = width; | ||
| 427 | uint16_t index = y_start + x; | ||
| 428 | |||
| 429 | // shift pair even pixel | ||
| 430 | int mask_1 = 85; | ||
| 431 | int mask_2 = 170; | ||
| 432 | |||
| 433 | if (!odd) { | ||
| 434 | // shift odd pixel | ||
| 435 | mask_1 = 170; | ||
| 436 | mask_2 = 85; | ||
| 437 | } | ||
| 438 | |||
| 439 | // wobble | ||
| 440 | uint16_t pos = 0; | ||
| 441 | for (uint16_t j = 0; j < nb_h; j++) { | ||
| 442 | // next line | ||
| 443 | index = (y_start + x) + (j * 32); | ||
| 444 | |||
| 445 | for (uint16_t i = 0; i < w_max; i++) { | ||
| 446 | if (i + iSize < w_max) { | ||
| 447 | pos = index + i; | ||
| 448 | copy_pixel(pos + iSize, iSize * -1, mask_1); | ||
| 449 | } | ||
| 450 | |||
| 451 | if (w_max - 1 - i - iSize >= 0) { | ||
| 452 | pos = (index + w_max - 1) - i; | ||
| 453 | copy_pixel(pos - iSize, iSize, mask_2); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | void draw_random_char(uint8_t column, uint8_t row, char final_char, int value, uint8_t style) { | ||
| 460 | if (value < 0) return; | ||
| 461 | |||
| 462 | char c = final_char; | ||
| 463 | |||
| 464 | if (value < 100) { | ||
| 465 | c = ((fastrand() % 15) + 1); | ||
| 466 | } | ||
| 467 | |||
| 468 | oled_set_cursor(column, row); | ||
| 469 | oled_write_char(c, false); | ||
| 470 | } | ||
| 471 | |||
| 472 | void get_glitch_index_new(uint16_t *glitch_timer, uint8_t *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 473 | if (timer_elapsed(*glitch_timer) > *current_glitch_scope_time) { | ||
| 474 | // end of the last glitch period | ||
| 475 | *glitch_timer = timer_read(); | ||
| 476 | |||
| 477 | // new random glich period | ||
| 478 | *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time); | ||
| 479 | |||
| 480 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 481 | if (!bGenerateGlitch) { | ||
| 482 | // no glitch | ||
| 483 | *glitch_index = 0; | ||
| 484 | return; | ||
| 485 | } | ||
| 486 | |||
| 487 | // get a new glitch index | ||
| 488 | *glitch_index = fastrand() % glitch_frame_number; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | uint8_t get_glitch_frame_index(uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 493 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 494 | if (!bGenerateGlitch) { | ||
| 495 | // no glitch | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | // get a new glitch index | ||
| 500 | return fastrand() % glitch_frame_number; | ||
| 501 | } | ||
| 502 | |||
| 503 | uint8_t get_glitch_duration(uint8_t min_time, uint16_t max_time) { return min_time + fastrand() % (max_time - min_time); } | ||
| 504 | |||
| 505 | void get_glitch_index(uint32_t *glitch_timer, int *current_glitch_scope_time, uint8_t *glitch_index, uint8_t min_time, uint16_t max_time, uint8_t glitch_probobility, uint8_t glitch_frame_number) { | ||
| 506 | if (timer_elapsed32(*glitch_timer) > *current_glitch_scope_time) { | ||
| 507 | // end of the last glitch period | ||
| 508 | *glitch_timer = timer_read32(); | ||
| 509 | |||
| 510 | // new random glich period | ||
| 511 | *current_glitch_scope_time = min_time + fastrand() % (max_time - min_time); | ||
| 512 | |||
| 513 | bool bGenerateGlitch = (fastrand() % 100) < glitch_probobility; | ||
| 514 | if (!bGenerateGlitch) { | ||
| 515 | // no glitch | ||
| 516 | *glitch_index = 0; | ||
| 517 | return; | ||
| 518 | } | ||
| 519 | |||
| 520 | // get a new glitch index | ||
| 521 | *glitch_index = fastrand() % glitch_frame_number; | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | void draw_progress(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int value, uint8_t style, bool color) { | ||
| 526 | if (value > 100) { | ||
| 527 | value = 100; | ||
| 528 | } | ||
| 529 | int lenght = (width * value) / 100; | ||
| 530 | for (uint8_t i = 0; i < lenght; i++) { | ||
| 531 | switch (style) { | ||
| 532 | case 0: | ||
| 533 | drawline_vb(x + i, y, heigth - 1, color); | ||
| 534 | break; | ||
| 535 | |||
| 536 | // case 1: | ||
| 537 | // drawline_vb(x + i, y + 1, heigth - 3, ((i % 3) < 2)); | ||
| 538 | // break; | ||
| 539 | // case 2: | ||
| 540 | // // . . . . . | ||
| 541 | // drawline_vb(x + i, y + 3, 2, ((i % 2) == 0)); | ||
| 542 | // break; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | void oled_write_raw_P_cursor(uint8_t col, uint8_t line, const char *data, uint16_t size) { | ||
| 548 | // raw_P at cursor position | ||
| 549 | oled_set_cursor(col, line); | ||
| 550 | oled_write_raw_P(data, size); | ||
| 551 | } | ||
| 552 | |||
| 553 | void oled_write_cursor(uint8_t col, uint8_t line, const char *data, bool invert) { | ||
| 554 | // write at cursor position | ||
| 555 | oled_set_cursor(col, line); | ||
| 556 | oled_write(data, invert); | ||
| 557 | } | ||
| 558 | |||
| 559 | void draw_label(const char *data, uint8_t len, uint8_t row, int value) { | ||
| 560 | if (value < 0) return; | ||
| 561 | if (row >= 16 || row < 0) return; | ||
| 562 | oled_write_cursor(0, row, data, false); | ||
| 563 | } | ||
| 564 | |||
| 565 | void draw_box(const char *data, uint8_t len, uint8_t row, long value, uint8_t style) { | ||
| 566 | if (value < 0) return; | ||
| 567 | if (row >= 16 || row < 0) return; | ||
| 568 | |||
| 569 | oled_write_cursor(0, row, data, false); | ||
| 570 | |||
| 571 | uint8_t y = row * 8; | ||
| 572 | |||
| 573 | uint8_t x = 6 * len; | ||
| 574 | uint8_t w = 32 - x; | ||
| 575 | |||
| 576 | if (value < 0) value = 0; | ||
| 577 | if (value > 100) value = 100; | ||
| 578 | draw_progress(x, y, w, 7, value, style, 1); | ||
| 579 | } | ||
| 580 | |||
| 581 | char get_oled_char(uint16_t start_index) { | ||
| 582 | oled_buffer_reader_t reader; | ||
| 583 | reader = oled_read_raw(start_index); | ||
| 584 | return *reader.current_element; | ||
| 585 | } | ||
| 586 | |||
| 587 | static int get_index_first_block(uint8_t y) { return ((y / 8) * 32); } | ||
| 588 | |||
| 589 | void move_block(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, int shift) { | ||
| 590 | // clip | ||
| 591 | if (x >= 31) return; | ||
| 592 | if (y >= 127) return; | ||
| 593 | |||
| 594 | int max_screen = 32 - 1; | ||
| 595 | if ((width + x) > max_screen + 1) width = max_screen + 1 - x; | ||
| 596 | |||
| 597 | if (width <= 1) return; | ||
| 598 | |||
| 599 | if ((heigth + y) > 127) heigth = 127 - y; | ||
| 600 | if (heigth <= 1) return; | ||
| 601 | |||
| 602 | // [-32 & +32] | ||
| 603 | if (shift > max_screen) shift = max_screen; | ||
| 604 | if (shift < -1 * max_screen) shift = -1 * max_screen; | ||
| 605 | |||
| 606 | if ((width + x + shift) > max_screen) width = width - shift; | ||
| 607 | |||
| 608 | int pixelTop = 8 - (y % 8); | ||
| 609 | int pixelBottom = (y + heigth) % 8; | ||
| 610 | |||
| 611 | unsigned char cMastTop = ~((unsigned)255 >> (pixelTop)); | ||
| 612 | unsigned char cMastBottom = ~((unsigned)255 << (pixelBottom)); | ||
| 613 | |||
| 614 | int indexFirstBloc = get_index_first_block(y) + x; | ||
| 615 | int indexFirstBlocFull = get_index_first_block(y + pixelTop) + x; | ||
| 616 | int indexFirstBlocEnd = get_index_first_block(y + heigth) + x; | ||
| 617 | |||
| 618 | int nbBlockHeigth = (heigth - pixelTop - pixelBottom) / 8; | ||
| 619 | |||
| 620 | if (nbBlockHeigth < 0) { | ||
| 621 | // just single row | ||
| 622 | nbBlockHeigth = 0; | ||
| 623 | cMastBottom = 0; | ||
| 624 | } | ||
| 625 | |||
| 626 | if (shift < 0) { | ||
| 627 | for (uint16_t i = 0; i < width; i++) { | ||
| 628 | copy_pixel(indexFirstBloc + i, shift, cMastTop); | ||
| 629 | copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom); | ||
| 630 | |||
| 631 | for (uint16_t j = 0; j < nbBlockHeigth; j++) { | ||
| 632 | copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255); | ||
| 633 | } | ||
| 634 | } | ||
| 635 | |||
| 636 | } else { | ||
| 637 | for (int i = width - 1; i >= 0; i--) { | ||
| 638 | copy_pixel(indexFirstBloc + i, shift, cMastTop); | ||
| 639 | copy_pixel(indexFirstBlocEnd + i, shift, cMastBottom); | ||
| 640 | |||
| 641 | for (uint16_t j = 0; j < nbBlockHeigth; j++) { | ||
| 642 | copy_pixel(indexFirstBlocFull + i + (j * 32), shift, 255); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 648 | int interpo_pourcent(int min, int max, int v) { | ||
| 649 | // interpolation | ||
| 650 | float x0 = min; | ||
| 651 | float x1 = max; | ||
| 652 | float y0 = 0; | ||
| 653 | float y1 = 100; | ||
| 654 | float xp = v; | ||
| 655 | float yp = y0 + ((y1 - y0) / (x1 - x0)) * (xp - x0); | ||
| 656 | |||
| 657 | return (int)yp; | ||
| 658 | } | ||
| 659 | |||
| 660 | uint8_t BAYER_PATTERN_4[4][4] = {{15, 135, 45, 165}, {195, 75, 225, 105}, {60, 180, 30, 150}, {240, 120, 210, 90}}; | ||
| 661 | |||
| 662 | void draw_gradient(uint8_t x, uint8_t y, uint8_t width, uint8_t heigth, uint8_t color_start, uint8_t color_end, uint8_t tres) { | ||
| 663 | bool invert = color_start > color_end; | ||
| 664 | |||
| 665 | if (invert) { | ||
| 666 | color_start = 255 - color_start; | ||
| 667 | color_end = 255 - color_end; | ||
| 668 | } | ||
| 669 | |||
| 670 | int step = (100 / tres); | ||
| 671 | int step_minus = (100 / (tres - 1)); | ||
| 672 | int distance = color_end - color_start; | ||
| 673 | |||
| 674 | for (uint8_t i = 0; i < width; i++) { | ||
| 675 | int position = interpo_pourcent(0, width, i); | ||
| 676 | |||
| 677 | float color = position; | ||
| 678 | color = ((int)(color / step)) * step_minus; | ||
| 679 | |||
| 680 | color = color_start + ((distance * color) / 100); | ||
| 681 | |||
| 682 | for (uint8_t j = 0; j < heigth; j++) { | ||
| 683 | uint8_t m = BAYER_PATTERN_4[i % 4][j % 4]; | ||
| 684 | unsigned char color_d = (color > m) ? !invert : invert; | ||
| 685 | |||
| 686 | oled_write_pixel(x + i, y + j, color_d); | ||
| 687 | } | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | void render_tv_animation(uint8_t frame_number, uint8_t x, uint8_t y, uint8_t width, uint8_t heigth) { | ||
| 692 | uint8_t xCenter = x + (width / 2); | ||
| 693 | uint8_t yCenter = y + (heigth / 2); | ||
| 694 | |||
| 695 | switch (frame_number) { | ||
| 696 | case 0: | ||
| 697 | // a fond : allume | ||
| 698 | drawline_hr_heigth(x, yCenter, width, 17, true); | ||
| 699 | break; | ||
| 700 | |||
| 701 | case 1: | ||
| 702 | drawline_hr_heigth(x, yCenter, width, 12, true); | ||
| 703 | draw_ellipse_fill(xCenter, yCenter, 7, 15, true); | ||
| 704 | break; | ||
| 705 | |||
| 706 | case 2: | ||
| 707 | drawline_hr_heigth(x, yCenter, width, 5, true); | ||
| 708 | draw_ellipse_fill(xCenter, yCenter, 5, 8, true); | ||
| 709 | break; | ||
| 710 | |||
| 711 | case 3: | ||
| 712 | drawline_hr_heigth(x, yCenter, width, 3, true); | ||
| 713 | draw_ellipse_fill(xCenter, yCenter, 3, 4, true); | ||
| 714 | break; | ||
| 715 | |||
| 716 | case 4: | ||
| 717 | drawline_hr_heigth(x, yCenter, width, 2, true); | ||
| 718 | draw_fill_circle(xCenter, yCenter, 3, true); | ||
| 719 | break; | ||
| 720 | |||
| 721 | case 5: | ||
| 722 | // central line | ||
| 723 | drawline_hr(x, yCenter, width, true); | ||
| 724 | draw_fill_circle(xCenter, yCenter, 2, true); | ||
| 725 | break; | ||
| 726 | |||
| 727 | case 6: | ||
| 728 | // cross | ||
| 729 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 730 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 731 | |||
| 732 | // central line | ||
| 733 | drawline_hr(x, yCenter, width, true); | ||
| 734 | break; | ||
| 735 | |||
| 736 | case 7: | ||
| 737 | // cross | ||
| 738 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 739 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 740 | // central line | ||
| 741 | drawline_hr(xCenter - 8, yCenter, 18, true); | ||
| 742 | // static | ||
| 743 | oled_write_pixel(xCenter - 11, yCenter, true); | ||
| 744 | oled_write_pixel(xCenter + 12, yCenter, true); | ||
| 745 | break; | ||
| 746 | |||
| 747 | case 8: | ||
| 748 | // cross | ||
| 749 | drawline_hr(xCenter, yCenter + 1, 2, true); | ||
| 750 | drawline_hr(xCenter, yCenter - 1, 2, true); | ||
| 751 | // central line | ||
| 752 | drawline_hr(xCenter - 2, yCenter, 4, true); | ||
| 753 | // static | ||
| 754 | drawline_hr(xCenter - 7, yCenter, 2, true); | ||
| 755 | drawline_hr(xCenter + 6, yCenter, 3, true); | ||
| 756 | |||
| 757 | // oled_write_pixel(xCenter - 11, yCenter, true); | ||
| 758 | oled_write_pixel(xCenter - 9, yCenter, true); | ||
| 759 | oled_write_pixel(xCenter + 12, yCenter, true); | ||
| 760 | oled_write_pixel(xCenter + 14, yCenter, true); | ||
| 761 | break; | ||
| 762 | |||
| 763 | case 9: | ||
| 764 | // central line | ||
| 765 | drawline_hr(xCenter, yCenter, 2, true); | ||
| 766 | break; | ||
| 767 | } | ||
| 768 | } \ No newline at end of file | ||
