├── 3d_print ├── LISPDECK │ ├── lispdeck_parts60-Housing_Outside.001.stl │ ├── lispdeck_parts60-Housing_Outside.stl │ ├── lispdeck_parts60-Lid.stl │ └── lispdeck_parts60-Lower_door.stl ├── lispbox_26.blend ├── lispbox_26_bake.blend ├── lispbox_26_bake_bevel.blend ├── lispbox_26_bake_bevel_bake.blend ├── lispbox_26_bake_bevel_bake_box.stl └── lispbox_26_bake_bevel_bake_lid.stl ├── Adafruit_RA8875_spi1.cpp ├── Adafruit_RA8875_spi1.h ├── LICENSE ├── LispDeck.jpg ├── LispboxExtensions.ino ├── LispboxLibrary.h ├── LispyLittleHelper.jpg ├── README.md ├── screenshot_editor.jpg └── ulisp-lispbox.ino /3d_print/LISPDECK/lispdeck_parts60-Housing_Outside.001.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/LISPDECK/lispdeck_parts60-Housing_Outside.001.stl -------------------------------------------------------------------------------- /3d_print/LISPDECK/lispdeck_parts60-Housing_Outside.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/LISPDECK/lispdeck_parts60-Housing_Outside.stl -------------------------------------------------------------------------------- /3d_print/LISPDECK/lispdeck_parts60-Lid.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/LISPDECK/lispdeck_parts60-Lid.stl -------------------------------------------------------------------------------- /3d_print/LISPDECK/lispdeck_parts60-Lower_door.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/LISPDECK/lispdeck_parts60-Lower_door.stl -------------------------------------------------------------------------------- /3d_print/lispbox_26.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26.blend -------------------------------------------------------------------------------- /3d_print/lispbox_26_bake.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26_bake.blend -------------------------------------------------------------------------------- /3d_print/lispbox_26_bake_bevel.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26_bake_bevel.blend -------------------------------------------------------------------------------- /3d_print/lispbox_26_bake_bevel_bake.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26_bake_bevel_bake.blend -------------------------------------------------------------------------------- /3d_print/lispbox_26_bake_bevel_bake_box.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26_bake_bevel_bake_box.stl -------------------------------------------------------------------------------- /3d_print/lispbox_26_bake_bevel_bake_lid.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/3d_print/lispbox_26_bake_bevel_bake_lid.stl -------------------------------------------------------------------------------- /Adafruit_RA8875_spi1.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_RA8875.cpp 3 | * 4 | * @mainpage Adafruit RA8875 TFT Driver 5 | * 6 | * @author Limor Friend/Ladyada, K.Townsend/KTOWN for Adafruit Industries 7 | * 8 | * @section intro_sec Introduction 9 | * 10 | * This is the library for the Adafruit RA8875 Driver board for TFT displays 11 | * ---------------> http://www.adafruit.com/products/1590 12 | * The RA8875 is a TFT driver for up to 800x480 dotclock'd displays 13 | * It is tested to work with displays in the Adafruit shop. Other displays 14 | * may need timing adjustments and are not guanteed to work. 15 | * 16 | * Adafruit invests time and resources providing this open 17 | * source code, please support Adafruit and open-source hardware 18 | * by purchasing products from Adafruit! 19 | * 20 | * @section author Author 21 | * 22 | * Written by Limor Fried/Ladyada for Adafruit Industries. 23 | * 24 | * @section license License 25 | * 26 | * BSD license, check license.txt for more information. 27 | * All text above must be included in any redistribution. 28 | * 29 | * @section HISTORY 30 | * 31 | * v1.0 - First release 32 | * 33 | */ 34 | 35 | #include "Adafruit_RA8875_spi1.h" 36 | 37 | /// @cond DISABLE 38 | #if defined(EEPROM_SUPPORTED) 39 | /// @endcond 40 | #include 41 | /// @cond DISABLE 42 | #endif 43 | /// @endcond 44 | 45 | #include 46 | 47 | /// @cond DISABLE 48 | #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) 49 | /// @endcond 50 | uint32_t spi1_speed = 60000000; /*!< 60MHz */ 51 | /// @cond DISABLE 52 | #else 53 | /// @endcond 54 | uint32_t spi1_speed = 4000000; /*!< 4MHz */ 55 | /// @cond DISABLE 56 | #endif 57 | /// @endcond 58 | 59 | // If the SPI library has transaction support, these functions 60 | // establish settings and protect from interference from other 61 | // libraries. Otherwise, they simply do nothing. 62 | #ifdef SPI_HAS_TRANSACTION 63 | static inline void spi1_begin(void) __attribute__((always_inline)); 64 | static inline void spi1_begin(void) { 65 | // max speed! 66 | SPI1.beginTransaction(SPISettings(spi1_speed, MSBFIRST, SPI_MODE0)); 67 | } 68 | static inline void spi1_end(void) __attribute__((always_inline)); 69 | static inline void spi1_end(void) { SPI1.endTransaction(); } 70 | #else 71 | #define spi1_begin() ///< Create dummy Macro Function 72 | #define spi1_end() ///< Create dummy Macro Function 73 | #endif 74 | 75 | /**************************************************************************/ 76 | /*! 77 | Constructor for a new RA8875 instance 78 | 79 | @param CS Location of the SPI chip select pin 80 | @param RST Location of the reset pin 81 | */ 82 | /**************************************************************************/ 83 | Adafruit_RA8875::Adafruit_RA8875(uint8_t CS, uint8_t RST) 84 | : Adafruit_GFX(800, 480) { 85 | _cs = CS; 86 | _rst = RST; 87 | } 88 | 89 | /**************************************************************************/ 90 | /*! 91 | Initialises the LCD driver and any HW required by the display 92 | 93 | @param s The display size, which can be either: 94 | 'RA8875_480x80' (3.8" displays) or 95 | 'RA8875_480x128' (3.9" displays) or 96 | 'RA8875_480x272' (4.3" displays) or 97 | 'RA8875_800x480' (5" and 7" displays) 98 | 99 | @return True if we reached the end 100 | */ 101 | /**************************************************************************/ 102 | boolean Adafruit_RA8875::begin(enum RA8875sizes s) { 103 | _size = s; 104 | 105 | if (_size == RA8875_480x80) { 106 | _width = 480; 107 | _height = 80; 108 | } else if (_size == RA8875_480x128) { 109 | _width = 480; 110 | _height = 128; 111 | } else if (_size == RA8875_480x272) { 112 | _width = 480; 113 | _height = 272; 114 | } else if (_size == RA8875_800x480) { 115 | _width = 800; 116 | _height = 480; 117 | } else { 118 | return false; 119 | } 120 | _rotation = 0; 121 | pinMode(_cs, OUTPUT); 122 | digitalWrite(_cs, HIGH); 123 | pinMode(_rst, OUTPUT); 124 | 125 | digitalWrite(_rst, LOW); 126 | delay(100); 127 | digitalWrite(_rst, HIGH); 128 | delay(100); 129 | 130 | SPI1.setMOSI(26); 131 | SPI1.setSCK(27); 132 | SPI1.setMISO(39); 133 | SPI1.begin(); 134 | 135 | #ifdef SPI_HAS_TRANSACTION 136 | /// @cond DISABLE 137 | #if defined(ARDUINO_ARCH_ARC32) 138 | /// @endcond 139 | spi1_speed = 2000000; 140 | /// @cond DISABLE 141 | #else 142 | /// @endcond 143 | spi1_speed = 125000; 144 | /// @cond DISABLE 145 | #endif 146 | /// @endcond 147 | #else 148 | #ifdef __AVR__ 149 | SPI1.setClockDivider(SPI_CLOCK_DIV128); 150 | SPI1.setDataMode(SPI_MODE0); 151 | #endif 152 | #endif 153 | 154 | uint8_t x = readReg(0); 155 | // Serial.print("x = 0x"); Serial.println(x,HEX); 156 | if (x != 0x75) { 157 | Serial.println(x); 158 | return false; 159 | } 160 | 161 | initialize(); 162 | 163 | #ifdef SPI_HAS_TRANSACTION 164 | /// @cond DISABLE 165 | #if defined(ARDUINO_ARCH_ARC32) 166 | /// @endcond 167 | spi1_speed = 12000000L; 168 | #else 169 | spi1_speed = 4000000L; 170 | #endif 171 | #else 172 | #ifdef __AVR__ 173 | SPI1.setClockDivider(SPI_CLOCK_DIV4); 174 | #endif 175 | #endif 176 | 177 | return true; 178 | } 179 | 180 | /************************* Initialization *********************************/ 181 | 182 | /**************************************************************************/ 183 | /*! 184 | Performs a SW-based reset of the RA8875 185 | */ 186 | /**************************************************************************/ 187 | void Adafruit_RA8875::softReset(void) { 188 | writeCommand(RA8875_PWRR); 189 | writeData(RA8875_PWRR_SOFTRESET); 190 | writeData(RA8875_PWRR_NORMAL); 191 | delay(1); 192 | } 193 | 194 | /**************************************************************************/ 195 | /*! 196 | Initialise the PLL 197 | */ 198 | /**************************************************************************/ 199 | void Adafruit_RA8875::PLLinit(void) { 200 | if (_size == RA8875_480x80 || _size == RA8875_480x128 || 201 | _size == RA8875_480x272) { 202 | writeReg(RA8875_PLLC1, RA8875_PLLC1_PLLDIV1 + 10); 203 | delay(1); 204 | writeReg(RA8875_PLLC2, RA8875_PLLC2_DIV4); 205 | delay(1); 206 | } else /* (_size == RA8875_800x480) */ { 207 | writeReg(RA8875_PLLC1, RA8875_PLLC1_PLLDIV1 + 11); 208 | delay(1); 209 | writeReg(RA8875_PLLC2, RA8875_PLLC2_DIV4); 210 | delay(1); 211 | } 212 | } 213 | 214 | /**************************************************************************/ 215 | /*! 216 | Initialises the driver IC (clock setup, etc.) 217 | */ 218 | /**************************************************************************/ 219 | void Adafruit_RA8875::initialize(void) { 220 | PLLinit(); 221 | writeReg(RA8875_SYSR, RA8875_SYSR_16BPP | RA8875_SYSR_MCU8); 222 | 223 | /* Timing values */ 224 | uint8_t pixclk; 225 | uint8_t hsync_start; 226 | uint8_t hsync_pw; 227 | uint8_t hsync_finetune; 228 | uint8_t hsync_nondisp; 229 | uint8_t vsync_pw; 230 | uint16_t vsync_nondisp; 231 | uint16_t vsync_start; 232 | 233 | /* Set the correct values for the display being used */ 234 | if (_size == RA8875_480x80) { 235 | pixclk = RA8875_PCSR_PDATL | RA8875_PCSR_4CLK; 236 | hsync_nondisp = 10; 237 | hsync_start = 8; 238 | hsync_pw = 48; 239 | hsync_finetune = 0; 240 | vsync_nondisp = 3; 241 | vsync_start = 8; 242 | vsync_pw = 10; 243 | _voffset = 192; // This uses the bottom 80 pixels of a 272 pixel controller 244 | } else if (_size == RA8875_480x128 || _size == RA8875_480x272) { 245 | pixclk = RA8875_PCSR_PDATL | RA8875_PCSR_4CLK; 246 | hsync_nondisp = 10; 247 | hsync_start = 8; 248 | hsync_pw = 48; 249 | hsync_finetune = 0; 250 | vsync_nondisp = 3; 251 | vsync_start = 8; 252 | vsync_pw = 10; 253 | _voffset = 0; 254 | } else // (_size == RA8875_800x480) 255 | { 256 | pixclk = RA8875_PCSR_PDATL | RA8875_PCSR_2CLK; 257 | hsync_nondisp = 26; 258 | hsync_start = 32; 259 | hsync_pw = 96; 260 | hsync_finetune = 0; 261 | vsync_nondisp = 32; 262 | vsync_start = 23; 263 | vsync_pw = 2; 264 | _voffset = 0; 265 | } 266 | 267 | writeReg(RA8875_PCSR, pixclk); 268 | delay(1); 269 | 270 | /* Horizontal settings registers */ 271 | writeReg(RA8875_HDWR, (_width / 8) - 1); // H width: (HDWR + 1) * 8 = 480 272 | writeReg(RA8875_HNDFTR, RA8875_HNDFTR_DE_HIGH + hsync_finetune); 273 | writeReg(RA8875_HNDR, (hsync_nondisp - hsync_finetune - 2) / 274 | 8); // H non-display: HNDR * 8 + HNDFTR + 2 = 10 275 | writeReg(RA8875_HSTR, hsync_start / 8 - 1); // Hsync start: (HSTR + 1)*8 276 | writeReg(RA8875_HPWR, 277 | RA8875_HPWR_LOW + 278 | (hsync_pw / 8 - 1)); // HSync pulse width = (HPWR+1) * 8 279 | 280 | /* Vertical settings registers */ 281 | writeReg(RA8875_VDHR0, (uint16_t)(_height - 1 + _voffset) & 0xFF); 282 | writeReg(RA8875_VDHR1, (uint16_t)(_height - 1 + _voffset) >> 8); 283 | writeReg(RA8875_VNDR0, vsync_nondisp - 1); // V non-display period = VNDR + 1 284 | writeReg(RA8875_VNDR1, vsync_nondisp >> 8); 285 | writeReg(RA8875_VSTR0, vsync_start - 1); // Vsync start position = VSTR + 1 286 | writeReg(RA8875_VSTR1, vsync_start >> 8); 287 | writeReg(RA8875_VPWR, 288 | RA8875_VPWR_LOW + vsync_pw - 1); // Vsync pulse width = VPWR + 1 289 | 290 | /* Set active window X */ 291 | writeReg(RA8875_HSAW0, 0); // horizontal start point 292 | writeReg(RA8875_HSAW1, 0); 293 | writeReg(RA8875_HEAW0, (uint16_t)(_width - 1) & 0xFF); // horizontal end point 294 | writeReg(RA8875_HEAW1, (uint16_t)(_width - 1) >> 8); 295 | 296 | /* Set active window Y */ 297 | writeReg(RA8875_VSAW0, 0 + _voffset); // vertical start point 298 | writeReg(RA8875_VSAW1, 0 + _voffset); 299 | writeReg(RA8875_VEAW0, 300 | (uint16_t)(_height - 1 + _voffset) & 0xFF); // vertical end point 301 | writeReg(RA8875_VEAW1, (uint16_t)(_height - 1 + _voffset) >> 8); 302 | 303 | /* ToDo: Setup touch panel? */ 304 | 305 | /* Clear the entire window */ 306 | writeReg(RA8875_MCLR, RA8875_MCLR_START | RA8875_MCLR_FULL); 307 | delay(500); 308 | } 309 | 310 | /**************************************************************************/ 311 | /*! 312 | Returns the display width in pixels 313 | 314 | @return The 1-based display width in pixels 315 | */ 316 | /**************************************************************************/ 317 | uint16_t Adafruit_RA8875::width(void) { return _width; } 318 | 319 | /**************************************************************************/ 320 | /*! 321 | Returns the display height in pixels 322 | 323 | @return The 1-based display height in pixels 324 | */ 325 | /**************************************************************************/ 326 | uint16_t Adafruit_RA8875::height(void) { return _height; } 327 | 328 | /**************************************************************************/ 329 | /*! 330 | Returns the current rotation (0-3) 331 | 332 | @return The Rotation Setting 333 | */ 334 | /**************************************************************************/ 335 | int8_t Adafruit_RA8875::getRotation(void) { return _rotation; } 336 | 337 | /**************************************************************************/ 338 | /*! 339 | Sets the current rotation (0-3) 340 | 341 | @param rotation The Rotation Setting 342 | */ 343 | /**************************************************************************/ 344 | void Adafruit_RA8875::setRotation(int8_t rotation) { 345 | switch (rotation) { 346 | case 2: 347 | _rotation = rotation; 348 | break; 349 | default: 350 | _rotation = 0; 351 | break; 352 | } 353 | } 354 | 355 | /************************* Text Mode ***********************************/ 356 | 357 | /**************************************************************************/ 358 | /*! 359 | Sets the display in text mode (as opposed to graphics mode) 360 | */ 361 | /**************************************************************************/ 362 | void Adafruit_RA8875::textMode(void) { 363 | /* Set text mode */ 364 | writeCommand(RA8875_MWCR0); 365 | uint8_t temp = readData(); 366 | temp |= RA8875_MWCR0_TXTMODE; // Set bit 7 367 | writeData(temp); 368 | 369 | /* Select the internal (ROM) font */ 370 | writeCommand(0x21); 371 | temp = readData(); 372 | temp &= ~((1 << 7) | (1 << 5)); // Clear bits 7 and 5 373 | writeData(temp); 374 | } 375 | 376 | /**************************************************************************/ 377 | /*! 378 | Sets the display in text mode (as opposed to graphics mode) 379 | 380 | @param x The x position of the cursor (in pixels, 0..1023) 381 | @param y The y position of the cursor (in pixels, 0..511) 382 | */ 383 | /**************************************************************************/ 384 | void Adafruit_RA8875::textSetCursor(uint16_t x, uint16_t y) { 385 | x = applyRotationX(x); 386 | y = applyRotationY(y); 387 | 388 | /* Set cursor location */ 389 | writeCommand(0x2A); 390 | writeData(x & 0xFF); 391 | writeCommand(0x2B); 392 | writeData(x >> 8); 393 | writeCommand(0x2C); 394 | writeData(y & 0xFF); 395 | writeCommand(0x2D); 396 | writeData(y >> 8); 397 | } 398 | 399 | /**************************************************************************/ 400 | /*! 401 | Sets the fore and background color when rendering text 402 | 403 | @param foreColor The RGB565 color to use when rendering the text 404 | @param bgColor The RGB565 colot to use for the background 405 | */ 406 | /**************************************************************************/ 407 | void Adafruit_RA8875::textColor(uint16_t foreColor, uint16_t bgColor) { 408 | /* Set Fore Color */ 409 | writeCommand(0x63); 410 | writeData((foreColor & 0xf800) >> 11); 411 | writeCommand(0x64); 412 | writeData((foreColor & 0x07e0) >> 5); 413 | writeCommand(0x65); 414 | writeData((foreColor & 0x001f)); 415 | 416 | /* Set Background Color */ 417 | writeCommand(0x60); 418 | writeData((bgColor & 0xf800) >> 11); 419 | writeCommand(0x61); 420 | writeData((bgColor & 0x07e0) >> 5); 421 | writeCommand(0x62); 422 | writeData((bgColor & 0x001f)); 423 | 424 | /* Clear transparency flag */ 425 | writeCommand(0x22); 426 | uint8_t temp = readData(); 427 | temp &= ~(1 << 6); // Clear bit 6 428 | writeData(temp); 429 | } 430 | 431 | /**************************************************************************/ 432 | /*! 433 | Sets the fore color when rendering text with a transparent bg 434 | 435 | @param foreColor The RGB565 color to use when rendering the text 436 | */ 437 | /**************************************************************************/ 438 | void Adafruit_RA8875::textTransparent(uint16_t foreColor) { 439 | /* Set Fore Color */ 440 | writeCommand(0x63); 441 | writeData((foreColor & 0xf800) >> 11); 442 | writeCommand(0x64); 443 | writeData((foreColor & 0x07e0) >> 5); 444 | writeCommand(0x65); 445 | writeData((foreColor & 0x001f)); 446 | 447 | /* Set transparency flag */ 448 | writeCommand(0x22); 449 | uint8_t temp = readData(); 450 | temp |= (1 << 6); // Set bit 6 451 | writeData(temp); 452 | } 453 | 454 | /**************************************************************************/ 455 | /*! 456 | Sets the text enlarge settings, using one of the following values: 457 | 458 | 0 = 1x zoom 459 | 1 = 2x zoom 460 | 2 = 3x zoom 461 | 3 = 4x zoom 462 | 463 | @param scale The zoom factor (0..3 for 1-4x zoom) 464 | */ 465 | /**************************************************************************/ 466 | void Adafruit_RA8875::textEnlarge(uint8_t scale) { 467 | if (scale > 3) 468 | scale = 3; // highest setting is 3 469 | 470 | /* Set font size flags */ 471 | writeCommand(0x22); 472 | uint8_t temp = readData(); 473 | temp &= ~(0xF); // Clears bits 0..3 474 | temp |= scale << 2; 475 | temp |= scale; 476 | 477 | writeData(temp); 478 | 479 | _textScale = scale; 480 | } 481 | 482 | /**************************************************************************/ 483 | /*! 484 | Enable Cursor Visibility and Blink 485 | Here we set bits 6 and 5 in 40h 486 | As well as the set the blink rate in 44h 487 | The rate is 0 through max 255 488 | the lower the number the faster it blinks (00h is 1 frame time, 489 | FFh is 256 Frames time. 490 | Blink Time (sec) = BTCR[44h]x(1/Frame_rate) 491 | 492 | @param rate The frame rate to blink 493 | */ 494 | /**************************************************************************/ 495 | 496 | void Adafruit_RA8875::cursorBlink(uint8_t rate) { 497 | 498 | writeCommand(RA8875_MWCR0); 499 | uint8_t temp = readData(); 500 | temp |= RA8875_MWCR0_CURSOR; 501 | writeData(temp); 502 | 503 | writeCommand(RA8875_MWCR0); 504 | temp = readData(); 505 | temp |= RA8875_MWCR0_BLINK; 506 | writeData(temp); 507 | 508 | if (rate > 255) 509 | rate = 255; 510 | writeCommand(RA8875_BTCR); 511 | writeData(rate); 512 | } 513 | 514 | /**************************************************************************/ 515 | /*! 516 | Renders some text on the screen when in text mode 517 | 518 | @param buffer The buffer containing the characters to render 519 | @param len The size of the buffer in bytes 520 | */ 521 | /**************************************************************************/ 522 | void Adafruit_RA8875::textWrite(const char *buffer, uint16_t len) { 523 | if (len == 0) 524 | len = strlen(buffer); 525 | writeCommand(RA8875_MRWC); 526 | for (uint16_t i = 0; i < len; i++) { 527 | writeData(buffer[i]); 528 | /// @cond DISABLE 529 | #if defined(__arm__) 530 | /// @endcond 531 | // This delay is needed with textEnlarge(1) because 532 | // Teensy 3.X is much faster than Arduino Uno 533 | if (_textScale > 0) 534 | delay(1); 535 | /// @cond DISABLE 536 | #else 537 | /// @endcond 538 | // For others, delay starting with textEnlarge(2) 539 | if (_textScale > 1) 540 | delay(1); 541 | /// @cond DISABLE 542 | #endif 543 | /// @endcond 544 | } 545 | } 546 | 547 | /************************* Graphics ***********************************/ 548 | 549 | /**************************************************************************/ 550 | /*! 551 | Sets the display in graphics mode (as opposed to text mode) 552 | */ 553 | /**************************************************************************/ 554 | void Adafruit_RA8875::graphicsMode(void) { 555 | writeCommand(RA8875_MWCR0); 556 | uint8_t temp = readData(); 557 | temp &= ~RA8875_MWCR0_TXTMODE; // bit #7 558 | writeData(temp); 559 | } 560 | 561 | /**************************************************************************/ 562 | /*! 563 | Waits for screen to finish by polling the status! 564 | 565 | @param regname The register name to check 566 | @param waitflag The value to wait for the status register to match 567 | 568 | @return True if the expected status has been reached 569 | */ 570 | /**************************************************************************/ 571 | boolean Adafruit_RA8875::waitPoll(uint8_t regname, uint8_t waitflag) { 572 | /* Wait for the command to finish */ 573 | while (1) { 574 | uint8_t temp = readReg(regname); 575 | if (!(temp & waitflag)) 576 | return true; 577 | } 578 | return false; // MEMEFIX: yeah i know, unreached! - add timeout? 579 | } 580 | 581 | /**************************************************************************/ 582 | /*! 583 | Sets the current X/Y position on the display before drawing 584 | 585 | @param x The 0-based x location 586 | @param y The 0-base y location 587 | */ 588 | /**************************************************************************/ 589 | void Adafruit_RA8875::setXY(uint16_t x, uint16_t y) { 590 | writeReg(RA8875_CURH0, x); 591 | writeReg(RA8875_CURH1, x >> 8); 592 | writeReg(RA8875_CURV0, y); 593 | writeReg(RA8875_CURV1, y >> 8); 594 | } 595 | 596 | /**************************************************************************/ 597 | /*! 598 | HW accelerated function to push a chunk of raw pixel data 599 | 600 | @param num The number of pixels to push 601 | @param p The pixel color to use 602 | */ 603 | /**************************************************************************/ 604 | void Adafruit_RA8875::pushPixels(uint32_t num, uint16_t p) { 605 | digitalWrite(_cs, LOW); 606 | SPI1.transfer(RA8875_DATAWRITE); 607 | while (num--) { 608 | SPI1.transfer(p >> 8); 609 | SPI1.transfer(p); 610 | } 611 | digitalWrite(_cs, HIGH); 612 | } 613 | 614 | /**************************************************************************/ 615 | /*! 616 | Fill the screen with the current color 617 | */ 618 | /**************************************************************************/ 619 | void Adafruit_RA8875::fillRect(void) { 620 | writeCommand(RA8875_DCR); 621 | writeData(RA8875_DCR_LINESQUTRI_STOP | RA8875_DCR_DRAWSQUARE); 622 | writeData(RA8875_DCR_LINESQUTRI_START | RA8875_DCR_FILL | 623 | RA8875_DCR_DRAWSQUARE); 624 | } 625 | 626 | /**************************************************************************/ 627 | /*! 628 | Apply current rotation in the X direction 629 | 630 | @return the X value with current rotation applied 631 | */ 632 | /**************************************************************************/ 633 | int16_t Adafruit_RA8875::applyRotationX(int16_t x) { 634 | switch (_rotation) { 635 | case 2: 636 | x = _width - 1 - x; 637 | break; 638 | } 639 | 640 | return x; 641 | } 642 | 643 | /**************************************************************************/ 644 | /*! 645 | Apply current rotation in the Y direction 646 | 647 | @return the Y value with current rotation applied 648 | */ 649 | /**************************************************************************/ 650 | int16_t Adafruit_RA8875::applyRotationY(int16_t y) { 651 | switch (_rotation) { 652 | case 2: 653 | y = _height - 1 - y; 654 | break; 655 | } 656 | 657 | return y + _voffset; 658 | } 659 | 660 | /**************************************************************************/ 661 | /*! 662 | Draws a single pixel at the specified location 663 | 664 | @param x The 0-based x location 665 | @param y The 0-base y location 666 | @param color The RGB565 color to use when drawing the pixel 667 | */ 668 | /**************************************************************************/ 669 | void Adafruit_RA8875::drawPixel(int16_t x, int16_t y, uint16_t color) { 670 | x = applyRotationX(x); 671 | y = applyRotationY(y); 672 | 673 | writeReg(RA8875_CURH0, x); 674 | writeReg(RA8875_CURH1, x >> 8); 675 | writeReg(RA8875_CURV0, y); 676 | writeReg(RA8875_CURV1, y >> 8); 677 | writeCommand(RA8875_MRWC); 678 | digitalWrite(_cs, LOW); 679 | SPI1.transfer(RA8875_DATAWRITE); 680 | SPI1.transfer(color >> 8); 681 | SPI1.transfer(color); 682 | digitalWrite(_cs, HIGH); 683 | } 684 | 685 | /**************************************************************************/ 686 | /*! 687 | Draws a series of pixels at the specified location without the overhead 688 | 689 | @param p An array of RGB565 color pixels 690 | @param num The number of the pixels to draw 691 | @param x The 0-based x location 692 | @param y The 0-base y location 693 | */ 694 | /**************************************************************************/ 695 | void Adafruit_RA8875::drawPixels(uint16_t *p, uint32_t num, int16_t x, 696 | int16_t y) { 697 | x = applyRotationX(x); 698 | y = applyRotationY(y); 699 | 700 | writeReg(RA8875_CURH0, x); 701 | writeReg(RA8875_CURH1, x >> 8); 702 | writeReg(RA8875_CURV0, y); 703 | writeReg(RA8875_CURV1, y >> 8); 704 | 705 | uint8_t dir = RA8875_MWCR0_LRTD; 706 | if (_rotation == 2) { 707 | dir = RA8875_MWCR0_RLTD; 708 | } 709 | writeReg(RA8875_MWCR0, (readReg(RA8875_MWCR0) & ~RA8875_MWCR0_DIRMASK) | dir); 710 | 711 | writeCommand(RA8875_MRWC); 712 | digitalWrite(_cs, LOW); 713 | SPI1.transfer(RA8875_DATAWRITE); 714 | while (num--) { 715 | SPI1.transfer16(*p++); 716 | } 717 | digitalWrite(_cs, HIGH); 718 | } 719 | 720 | /**************************************************************************/ 721 | /*! 722 | Draws a HW accelerated line on the display 723 | 724 | @param x0 The 0-based starting x location 725 | @param y0 The 0-base starting y location 726 | @param x1 The 0-based ending x location 727 | @param y1 The 0-base ending y location 728 | @param color The RGB565 color to use when drawing the pixel 729 | */ 730 | /**************************************************************************/ 731 | void Adafruit_RA8875::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 732 | uint16_t color) { 733 | x0 = applyRotationX(x0); 734 | y0 = applyRotationY(y0); 735 | x1 = applyRotationX(x1); 736 | y1 = applyRotationY(y1); 737 | 738 | /* Set X */ 739 | writeCommand(0x91); 740 | writeData(x0); 741 | writeCommand(0x92); 742 | writeData(x0 >> 8); 743 | 744 | /* Set Y */ 745 | writeCommand(0x93); 746 | writeData(y0); 747 | writeCommand(0x94); 748 | writeData(y0 >> 8); 749 | 750 | /* Set X1 */ 751 | writeCommand(0x95); 752 | writeData(x1); 753 | writeCommand(0x96); 754 | writeData((x1) >> 8); 755 | 756 | /* Set Y1 */ 757 | writeCommand(0x97); 758 | writeData(y1); 759 | writeCommand(0x98); 760 | writeData((y1) >> 8); 761 | 762 | /* Set Color */ 763 | writeCommand(0x63); 764 | writeData((color & 0xf800) >> 11); 765 | writeCommand(0x64); 766 | writeData((color & 0x07e0) >> 5); 767 | writeCommand(0x65); 768 | writeData((color & 0x001f)); 769 | 770 | /* Draw! */ 771 | writeCommand(RA8875_DCR); 772 | writeData(0x80); 773 | 774 | /* Wait for the command to finish */ 775 | waitPoll(RA8875_DCR, RA8875_DCR_LINESQUTRI_STATUS); 776 | } 777 | 778 | /**************************************************************************/ 779 | /*! 780 | Draw a vertical line 781 | 782 | @param x The X position 783 | @param y The Y position 784 | @param h Height 785 | @param color The color 786 | */ 787 | /**************************************************************************/ 788 | void Adafruit_RA8875::drawFastVLine(int16_t x, int16_t y, int16_t h, 789 | uint16_t color) { 790 | drawLine(x, y, x, y + h, color); 791 | } 792 | 793 | /**************************************************************************/ 794 | /*! 795 | Draw a horizontal line 796 | 797 | @param x The X position 798 | @param y The Y position 799 | @param w Width 800 | @param color The color 801 | */ 802 | /**************************************************************************/ 803 | void Adafruit_RA8875::drawFastHLine(int16_t x, int16_t y, int16_t w, 804 | uint16_t color) { 805 | drawLine(x, y, x + w, y, color); 806 | } 807 | 808 | /**************************************************************************/ 809 | /*! 810 | Draws a HW accelerated rectangle on the display 811 | 812 | @param x The 0-based x location of the top-right corner 813 | @param y The 0-based y location of the top-right corner 814 | @param w The rectangle width 815 | @param h The rectangle height 816 | @param color The RGB565 color to use when drawing the pixel 817 | */ 818 | /**************************************************************************/ 819 | void Adafruit_RA8875::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, 820 | uint16_t color) { 821 | rectHelper(x, y, x + w - 1, y + h - 1, color, false); 822 | } 823 | 824 | /**************************************************************************/ 825 | /*! 826 | Draws a HW accelerated filled rectangle on the display 827 | 828 | @param x The 0-based x location of the top-right corner 829 | @param y The 0-based y location of the top-right corner 830 | @param w The rectangle width 831 | @param h The rectangle height 832 | @param color The RGB565 color to use when drawing the pixel 833 | */ 834 | /**************************************************************************/ 835 | void Adafruit_RA8875::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, 836 | uint16_t color) { 837 | rectHelper(x, y, x + w - 1, y + h - 1, color, true); 838 | } 839 | 840 | /**************************************************************************/ 841 | /*! 842 | Fills the screen with the spefied RGB565 color 843 | 844 | @param color The RGB565 color to use when drawing the pixel 845 | */ 846 | /**************************************************************************/ 847 | void Adafruit_RA8875::fillScreen(uint16_t color) { 848 | rectHelper(0, 0, _width - 1, _height - 1, color, true); 849 | } 850 | 851 | /**************************************************************************/ 852 | /*! 853 | Draws a HW accelerated circle on the display 854 | 855 | @param x The 0-based x location of the center of the circle 856 | @param y The 0-based y location of the center of the circle 857 | @param r The circle's radius 858 | @param color The RGB565 color to use when drawing the pixel 859 | */ 860 | /**************************************************************************/ 861 | void Adafruit_RA8875::drawCircle(int16_t x, int16_t y, int16_t r, 862 | uint16_t color) { 863 | circleHelper(x, y, r, color, false); 864 | } 865 | 866 | /**************************************************************************/ 867 | /*! 868 | Draws a HW accelerated filled circle on the display 869 | 870 | @param x The 0-based x location of the center of the circle 871 | @param y The 0-based y location of the center of the circle 872 | @param r The circle's radius 873 | @param color The RGB565 color to use when drawing the pixel 874 | */ 875 | /**************************************************************************/ 876 | void Adafruit_RA8875::fillCircle(int16_t x, int16_t y, int16_t r, 877 | uint16_t color) { 878 | circleHelper(x, y, r, color, true); 879 | } 880 | 881 | /**************************************************************************/ 882 | /*! 883 | Draws a HW accelerated triangle on the display 884 | 885 | @param x0 The 0-based x location of point 0 on the triangle 886 | @param y0 The 0-based y location of point 0 on the triangle 887 | @param x1 The 0-based x location of point 1 on the triangle 888 | @param y1 The 0-based y location of point 1 on the triangle 889 | @param x2 The 0-based x location of point 2 on the triangle 890 | @param y2 The 0-based y location of point 2 on the triangle 891 | @param color The RGB565 color to use when drawing the pixel 892 | */ 893 | /**************************************************************************/ 894 | void Adafruit_RA8875::drawTriangle(int16_t x0, int16_t y0, int16_t x1, 895 | int16_t y1, int16_t x2, int16_t y2, 896 | uint16_t color) { 897 | triangleHelper(x0, y0, x1, y1, x2, y2, color, false); 898 | } 899 | 900 | /**************************************************************************/ 901 | /*! 902 | Draws a HW accelerated filled triangle on the display 903 | 904 | @param x0 The 0-based x location of point 0 on the triangle 905 | @param y0 The 0-based y location of point 0 on the triangle 906 | @param x1 The 0-based x location of point 1 on the triangle 907 | @param y1 The 0-based y location of point 1 on the triangle 908 | @param x2 The 0-based x location of point 2 on the triangle 909 | @param y2 The 0-based y location of point 2 on the triangle 910 | @param color The RGB565 color to use when drawing the pixel 911 | */ 912 | /**************************************************************************/ 913 | void Adafruit_RA8875::fillTriangle(int16_t x0, int16_t y0, int16_t x1, 914 | int16_t y1, int16_t x2, int16_t y2, 915 | uint16_t color) { 916 | triangleHelper(x0, y0, x1, y1, x2, y2, color, true); 917 | } 918 | 919 | /**************************************************************************/ 920 | /*! 921 | Draws a HW accelerated ellipse on the display 922 | 923 | @param xCenter The 0-based x location of the ellipse's center 924 | @param yCenter The 0-based y location of the ellipse's center 925 | @param longAxis The size in pixels of the ellipse's long axis 926 | @param shortAxis The size in pixels of the ellipse's short axis 927 | @param color The RGB565 color to use when drawing the pixel 928 | */ 929 | /**************************************************************************/ 930 | void Adafruit_RA8875::drawEllipse(int16_t xCenter, int16_t yCenter, 931 | int16_t longAxis, int16_t shortAxis, 932 | uint16_t color) { 933 | ellipseHelper(xCenter, yCenter, longAxis, shortAxis, color, false); 934 | } 935 | 936 | /**************************************************************************/ 937 | /*! 938 | Draws a HW accelerated filled ellipse on the display 939 | 940 | @param xCenter The 0-based x location of the ellipse's center 941 | @param yCenter The 0-based y location of the ellipse's center 942 | @param longAxis The size in pixels of the ellipse's long axis 943 | @param shortAxis The size in pixels of the ellipse's short axis 944 | @param color The RGB565 color to use when drawing the pixel 945 | */ 946 | /**************************************************************************/ 947 | void Adafruit_RA8875::fillEllipse(int16_t xCenter, int16_t yCenter, 948 | int16_t longAxis, int16_t shortAxis, 949 | uint16_t color) { 950 | ellipseHelper(xCenter, yCenter, longAxis, shortAxis, color, true); 951 | } 952 | 953 | /**************************************************************************/ 954 | /*! 955 | Draws a HW accelerated curve on the display 956 | 957 | @param xCenter The 0-based x location of the ellipse's center 958 | @param yCenter The 0-based y location of the ellipse's center 959 | @param longAxis The size in pixels of the ellipse's long axis 960 | @param shortAxis The size in pixels of the ellipse's short axis 961 | @param curvePart The corner to draw, where in clock-wise motion: 962 | 0 = 180-270° 963 | 1 = 270-0° 964 | 2 = 0-90° 965 | 3 = 90-180° 966 | @param color The RGB565 color to use when drawing the pixel 967 | */ 968 | /**************************************************************************/ 969 | void Adafruit_RA8875::drawCurve(int16_t xCenter, int16_t yCenter, 970 | int16_t longAxis, int16_t shortAxis, 971 | uint8_t curvePart, uint16_t color) { 972 | curveHelper(xCenter, yCenter, longAxis, shortAxis, curvePart, color, false); 973 | } 974 | 975 | /**************************************************************************/ 976 | /*! 977 | Draws a HW accelerated filled curve on the display 978 | 979 | @param xCenter The 0-based x location of the ellipse's center 980 | @param yCenter The 0-based y location of the ellipse's center 981 | @param longAxis The size in pixels of the ellipse's long axis 982 | @param shortAxis The size in pixels of the ellipse's short axis 983 | @param curvePart The corner to draw, where in clock-wise motion: 984 | 0 = 180-270° 985 | 1 = 270-0° 986 | 2 = 0-90° 987 | 3 = 90-180° 988 | @param color The RGB565 color to use when drawing the pixel 989 | */ 990 | /**************************************************************************/ 991 | void Adafruit_RA8875::fillCurve(int16_t xCenter, int16_t yCenter, 992 | int16_t longAxis, int16_t shortAxis, 993 | uint8_t curvePart, uint16_t color) { 994 | curveHelper(xCenter, yCenter, longAxis, shortAxis, curvePart, color, true); 995 | } 996 | 997 | /**************************************************************************/ 998 | /*! 999 | Draws a HW accelerated rounded rectangle on the display 1000 | 1001 | @param x The 0-based x location of the rectangle's upper left corner 1002 | @param y The 0-based y location of the rectangle's upper left corner 1003 | @param w The size in pixels of the rectangle's width 1004 | @param h The size in pixels of the rectangle's height 1005 | @param r The radius of the curves in the corners of the rectangle 1006 | @param color The RGB565 color to use when drawing the pixel 1007 | */ 1008 | /**************************************************************************/ 1009 | void Adafruit_RA8875::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, 1010 | int16_t r, uint16_t color) { 1011 | roundRectHelper(x, y, x + w, y + h, r, color, false); 1012 | } 1013 | 1014 | /**************************************************************************/ 1015 | /*! 1016 | Draws a HW accelerated filled rounded rectangle on the display 1017 | 1018 | @param x The 0-based x location of the rectangle's upper left corner 1019 | @param y The 0-based y location of the rectangle's upper left corner 1020 | @param w The size in pixels of the rectangle's width 1021 | @param h The size in pixels of the rectangle's height 1022 | @param r The radius of the curves in the corners of the rectangle 1023 | @param color The RGB565 color to use when drawing the pixel 1024 | */ 1025 | /**************************************************************************/ 1026 | void Adafruit_RA8875::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, 1027 | int16_t r, uint16_t color) { 1028 | roundRectHelper(x, y, x + w, y + h, r, color, true); 1029 | } 1030 | 1031 | /**************************************************************************/ 1032 | /*! 1033 | Helper function for higher level circle drawing code 1034 | */ 1035 | /**************************************************************************/ 1036 | void Adafruit_RA8875::circleHelper(int16_t x, int16_t y, int16_t r, 1037 | uint16_t color, bool filled) { 1038 | x = applyRotationX(x); 1039 | y = applyRotationY(y); 1040 | 1041 | /* Set X */ 1042 | writeCommand(0x99); 1043 | writeData(x); 1044 | writeCommand(0x9a); 1045 | writeData(x >> 8); 1046 | 1047 | /* Set Y */ 1048 | writeCommand(0x9b); 1049 | writeData(y); 1050 | writeCommand(0x9c); 1051 | writeData(y >> 8); 1052 | 1053 | /* Set Radius */ 1054 | writeCommand(0x9d); 1055 | writeData(r); 1056 | 1057 | /* Set Color */ 1058 | writeCommand(0x63); 1059 | writeData((color & 0xf800) >> 11); 1060 | writeCommand(0x64); 1061 | writeData((color & 0x07e0) >> 5); 1062 | writeCommand(0x65); 1063 | writeData((color & 0x001f)); 1064 | 1065 | /* Draw! */ 1066 | writeCommand(RA8875_DCR); 1067 | if (filled) { 1068 | writeData(RA8875_DCR_CIRCLE_START | RA8875_DCR_FILL); 1069 | } else { 1070 | writeData(RA8875_DCR_CIRCLE_START | RA8875_DCR_NOFILL); 1071 | } 1072 | 1073 | /* Wait for the command to finish */ 1074 | waitPoll(RA8875_DCR, RA8875_DCR_CIRCLE_STATUS); 1075 | } 1076 | 1077 | /**************************************************************************/ 1078 | /*! 1079 | Helper function for higher level rectangle drawing code 1080 | */ 1081 | /**************************************************************************/ 1082 | void Adafruit_RA8875::rectHelper(int16_t x, int16_t y, int16_t w, int16_t h, 1083 | uint16_t color, bool filled) { 1084 | x = applyRotationX(x); 1085 | y = applyRotationY(y); 1086 | w = applyRotationX(w); 1087 | h = applyRotationY(h); 1088 | 1089 | /* Set X */ 1090 | writeCommand(0x91); 1091 | writeData(x); 1092 | writeCommand(0x92); 1093 | writeData(x >> 8); 1094 | 1095 | /* Set Y */ 1096 | writeCommand(0x93); 1097 | writeData(y); 1098 | writeCommand(0x94); 1099 | writeData(y >> 8); 1100 | 1101 | /* Set X1 */ 1102 | writeCommand(0x95); 1103 | writeData(w); 1104 | writeCommand(0x96); 1105 | writeData((w) >> 8); 1106 | 1107 | /* Set Y1 */ 1108 | writeCommand(0x97); 1109 | writeData(h); 1110 | writeCommand(0x98); 1111 | writeData((h) >> 8); 1112 | 1113 | /* Set Color */ 1114 | writeCommand(0x63); 1115 | writeData((color & 0xf800) >> 11); 1116 | writeCommand(0x64); 1117 | writeData((color & 0x07e0) >> 5); 1118 | writeCommand(0x65); 1119 | writeData((color & 0x001f)); 1120 | 1121 | /* Draw! */ 1122 | writeCommand(RA8875_DCR); 1123 | if (filled) { 1124 | writeData(0xB0); 1125 | } else { 1126 | writeData(0x90); 1127 | } 1128 | 1129 | /* Wait for the command to finish */ 1130 | waitPoll(RA8875_DCR, RA8875_DCR_LINESQUTRI_STATUS); 1131 | } 1132 | 1133 | /**************************************************************************/ 1134 | /*! 1135 | Helper function for higher level triangle drawing code 1136 | */ 1137 | /**************************************************************************/ 1138 | void Adafruit_RA8875::triangleHelper(int16_t x0, int16_t y0, int16_t x1, 1139 | int16_t y1, int16_t x2, int16_t y2, 1140 | uint16_t color, bool filled) { 1141 | x0 = applyRotationX(x0); 1142 | y0 = applyRotationY(y0); 1143 | x1 = applyRotationX(x1); 1144 | y1 = applyRotationY(y1); 1145 | x2 = applyRotationX(x2); 1146 | y2 = applyRotationY(y2); 1147 | 1148 | /* Set Point 0 */ 1149 | writeCommand(0x91); 1150 | writeData(x0); 1151 | writeCommand(0x92); 1152 | writeData(x0 >> 8); 1153 | writeCommand(0x93); 1154 | writeData(y0); 1155 | writeCommand(0x94); 1156 | writeData(y0 >> 8); 1157 | 1158 | /* Set Point 1 */ 1159 | writeCommand(0x95); 1160 | writeData(x1); 1161 | writeCommand(0x96); 1162 | writeData(x1 >> 8); 1163 | writeCommand(0x97); 1164 | writeData(y1); 1165 | writeCommand(0x98); 1166 | writeData(y1 >> 8); 1167 | 1168 | /* Set Point 2 */ 1169 | writeCommand(0xA9); 1170 | writeData(x2); 1171 | writeCommand(0xAA); 1172 | writeData(x2 >> 8); 1173 | writeCommand(0xAB); 1174 | writeData(y2); 1175 | writeCommand(0xAC); 1176 | writeData(y2 >> 8); 1177 | 1178 | /* Set Color */ 1179 | writeCommand(0x63); 1180 | writeData((color & 0xf800) >> 11); 1181 | writeCommand(0x64); 1182 | writeData((color & 0x07e0) >> 5); 1183 | writeCommand(0x65); 1184 | writeData((color & 0x001f)); 1185 | 1186 | /* Draw! */ 1187 | writeCommand(RA8875_DCR); 1188 | if (filled) { 1189 | writeData(0xA1); 1190 | } else { 1191 | writeData(0x81); 1192 | } 1193 | 1194 | /* Wait for the command to finish */ 1195 | waitPoll(RA8875_DCR, RA8875_DCR_LINESQUTRI_STATUS); 1196 | } 1197 | 1198 | /**************************************************************************/ 1199 | /*! 1200 | Helper function for higher level ellipse drawing code 1201 | */ 1202 | /**************************************************************************/ 1203 | void Adafruit_RA8875::ellipseHelper(int16_t xCenter, int16_t yCenter, 1204 | int16_t longAxis, int16_t shortAxis, 1205 | uint16_t color, bool filled) { 1206 | xCenter = applyRotationX(xCenter); 1207 | yCenter = applyRotationY(yCenter); 1208 | 1209 | /* Set Center Point */ 1210 | writeCommand(0xA5); 1211 | writeData(xCenter); 1212 | writeCommand(0xA6); 1213 | writeData(xCenter >> 8); 1214 | writeCommand(0xA7); 1215 | writeData(yCenter); 1216 | writeCommand(0xA8); 1217 | writeData(yCenter >> 8); 1218 | 1219 | /* Set Long and Short Axis */ 1220 | writeCommand(0xA1); 1221 | writeData(longAxis); 1222 | writeCommand(0xA2); 1223 | writeData(longAxis >> 8); 1224 | writeCommand(0xA3); 1225 | writeData(shortAxis); 1226 | writeCommand(0xA4); 1227 | writeData(shortAxis >> 8); 1228 | 1229 | /* Set Color */ 1230 | writeCommand(0x63); 1231 | writeData((color & 0xf800) >> 11); 1232 | writeCommand(0x64); 1233 | writeData((color & 0x07e0) >> 5); 1234 | writeCommand(0x65); 1235 | writeData((color & 0x001f)); 1236 | 1237 | /* Draw! */ 1238 | writeCommand(0xA0); 1239 | if (filled) { 1240 | writeData(0xC0); 1241 | } else { 1242 | writeData(0x80); 1243 | } 1244 | 1245 | /* Wait for the command to finish */ 1246 | waitPoll(RA8875_ELLIPSE, RA8875_ELLIPSE_STATUS); 1247 | } 1248 | 1249 | /**************************************************************************/ 1250 | /*! 1251 | Helper function for higher level curve drawing code 1252 | */ 1253 | /**************************************************************************/ 1254 | void Adafruit_RA8875::curveHelper(int16_t xCenter, int16_t yCenter, 1255 | int16_t longAxis, int16_t shortAxis, 1256 | uint8_t curvePart, uint16_t color, 1257 | bool filled) { 1258 | xCenter = applyRotationX(xCenter); 1259 | yCenter = applyRotationY(yCenter); 1260 | curvePart = (curvePart + _rotation) % 4; 1261 | 1262 | /* Set Center Point */ 1263 | writeCommand(0xA5); 1264 | writeData(xCenter); 1265 | writeCommand(0xA6); 1266 | writeData(xCenter >> 8); 1267 | writeCommand(0xA7); 1268 | writeData(yCenter); 1269 | writeCommand(0xA8); 1270 | writeData(yCenter >> 8); 1271 | 1272 | /* Set Long and Short Axis */ 1273 | writeCommand(0xA1); 1274 | writeData(longAxis); 1275 | writeCommand(0xA2); 1276 | writeData(longAxis >> 8); 1277 | writeCommand(0xA3); 1278 | writeData(shortAxis); 1279 | writeCommand(0xA4); 1280 | writeData(shortAxis >> 8); 1281 | 1282 | /* Set Color */ 1283 | writeCommand(0x63); 1284 | writeData((color & 0xf800) >> 11); 1285 | writeCommand(0x64); 1286 | writeData((color & 0x07e0) >> 5); 1287 | writeCommand(0x65); 1288 | writeData((color & 0x001f)); 1289 | 1290 | /* Draw! */ 1291 | writeCommand(0xA0); 1292 | if (filled) { 1293 | writeData(0xD0 | (curvePart & 0x03)); 1294 | } else { 1295 | writeData(0x90 | (curvePart & 0x03)); 1296 | } 1297 | 1298 | /* Wait for the command to finish */ 1299 | waitPoll(RA8875_ELLIPSE, RA8875_ELLIPSE_STATUS); 1300 | } 1301 | 1302 | /**************************************************************************/ 1303 | /*! 1304 | Helper function for higher level rounded rectangle drawing code 1305 | */ 1306 | /**************************************************************************/ 1307 | void Adafruit_RA8875::roundRectHelper(int16_t x, int16_t y, int16_t w, 1308 | int16_t h, int16_t r, uint16_t color, 1309 | bool filled) { 1310 | x = applyRotationX(x); 1311 | y = applyRotationY(y); 1312 | w = applyRotationX(w); 1313 | h = applyRotationY(h); 1314 | if (x > w) 1315 | swap(x, w); 1316 | if (y > h) 1317 | swap(y, h); 1318 | 1319 | /* Set X */ 1320 | writeCommand(0x91); 1321 | writeData(x); 1322 | writeCommand(0x92); 1323 | writeData(x >> 8); 1324 | 1325 | /* Set Y */ 1326 | writeCommand(0x93); 1327 | writeData(y); 1328 | writeCommand(0x94); 1329 | writeData(y >> 8); 1330 | 1331 | /* Set X1 */ 1332 | writeCommand(0x95); 1333 | writeData(w); 1334 | writeCommand(0x96); 1335 | writeData((w) >> 8); 1336 | 1337 | /* Set Y1 */ 1338 | writeCommand(0x97); 1339 | writeData(h); 1340 | writeCommand(0x98); 1341 | writeData((h) >> 8); 1342 | 1343 | writeCommand(0xA1); 1344 | writeData(r); 1345 | writeCommand(0xA2); 1346 | writeData((r) >> 8); 1347 | 1348 | writeCommand(0xA3); 1349 | writeData(r); 1350 | writeCommand(0xA4); 1351 | writeData((r) >> 8); 1352 | 1353 | /* Set Color */ 1354 | writeCommand(0x63); 1355 | writeData((color & 0xf800) >> 11); 1356 | writeCommand(0x64); 1357 | writeData((color & 0x07e0) >> 5); 1358 | writeCommand(0x65); 1359 | writeData((color & 0x001f)); 1360 | 1361 | /* Draw! */ 1362 | writeCommand(RA8875_ELLIPSE); 1363 | if (filled) { 1364 | writeData(0xE0); 1365 | } else { 1366 | writeData(0xA0); 1367 | } 1368 | 1369 | /* Wait for the command to finish */ 1370 | waitPoll(RA8875_ELLIPSE, RA8875_DCR_LINESQUTRI_STATUS); 1371 | } 1372 | /**************************************************************************/ 1373 | /*! 1374 | Set the scroll window 1375 | 1376 | @param x X position of the scroll window 1377 | @param y Y position of the scroll window 1378 | @param w Width of the Scroll Window 1379 | @param h Height of the Scroll window 1380 | @param mode Layer to Scroll 1381 | 1382 | */ 1383 | /**************************************************************************/ 1384 | void Adafruit_RA8875::setScrollWindow(int16_t x, int16_t y, int16_t w, 1385 | int16_t h, uint8_t mode) { 1386 | // Horizontal Start point of Scroll Window 1387 | writeCommand(0x38); 1388 | writeData(x); 1389 | writeCommand(0x39); 1390 | writeData(x >> 8); 1391 | 1392 | // Vertical Start Point of Scroll Window 1393 | writeCommand(0x3a); 1394 | writeData(y); 1395 | writeCommand(0x3b); 1396 | writeData(y >> 8); 1397 | 1398 | // Horizontal End Point of Scroll Window 1399 | writeCommand(0x3c); 1400 | writeData(x + w); 1401 | writeCommand(0x3d); 1402 | writeData((x + w) >> 8); 1403 | 1404 | // Vertical End Point of Scroll Window 1405 | writeCommand(0x3e); 1406 | writeData(y + h); 1407 | writeCommand(0x3f); 1408 | writeData((y + h) >> 8); 1409 | 1410 | // Scroll function setting 1411 | writeCommand(0x52); 1412 | writeData(mode); 1413 | } 1414 | 1415 | /**************************************************************************/ 1416 | /*! 1417 | Scroll in the X direction 1418 | 1419 | @param dist The distance to scroll 1420 | 1421 | */ 1422 | /**************************************************************************/ 1423 | void Adafruit_RA8875::scrollX(int16_t dist) { 1424 | writeCommand(0x24); 1425 | writeData(dist); 1426 | writeCommand(0x25); 1427 | writeData(dist >> 8); 1428 | } 1429 | 1430 | /**************************************************************************/ 1431 | /*! 1432 | Scroll in the Y direction 1433 | 1434 | @param dist The distance to scroll 1435 | 1436 | */ 1437 | /**************************************************************************/ 1438 | void Adafruit_RA8875::scrollY(int16_t dist) { 1439 | writeCommand(0x26); 1440 | writeData(dist); 1441 | writeCommand(0x27); 1442 | writeData(dist >> 8); 1443 | } 1444 | 1445 | /************************* Mid Level ***********************************/ 1446 | 1447 | /**************************************************************************/ 1448 | /*! 1449 | Set the Extra General Purpose IO Register 1450 | 1451 | @param on Whether to turn Extra General Purpose IO on or not 1452 | 1453 | */ 1454 | /**************************************************************************/ 1455 | void Adafruit_RA8875::GPIOX(boolean on) { 1456 | if (on) 1457 | writeReg(RA8875_GPIOX, 1); 1458 | else 1459 | writeReg(RA8875_GPIOX, 0); 1460 | } 1461 | 1462 | /**************************************************************************/ 1463 | /*! 1464 | Set the duty cycle of the PWM 1 Clock 1465 | 1466 | @param p The duty Cycle (0-255) 1467 | */ 1468 | /**************************************************************************/ 1469 | void Adafruit_RA8875::PWM1out(uint8_t p) { writeReg(RA8875_P1DCR, p); } 1470 | 1471 | /**************************************************************************/ 1472 | /*! 1473 | Set the duty cycle of the PWM 2 Clock 1474 | 1475 | @param p The duty Cycle (0-255) 1476 | */ 1477 | /**************************************************************************/ 1478 | void Adafruit_RA8875::PWM2out(uint8_t p) { writeReg(RA8875_P2DCR, p); } 1479 | 1480 | /**************************************************************************/ 1481 | /*! 1482 | Configure the PWM 1 Clock 1483 | 1484 | @param on Whether to enable the clock 1485 | @param clock The Clock Divider 1486 | */ 1487 | /**************************************************************************/ 1488 | void Adafruit_RA8875::PWM1config(boolean on, uint8_t clock) { 1489 | if (on) { 1490 | writeReg(RA8875_P1CR, RA8875_P1CR_ENABLE | (clock & 0xF)); 1491 | } else { 1492 | writeReg(RA8875_P1CR, RA8875_P1CR_DISABLE | (clock & 0xF)); 1493 | } 1494 | } 1495 | 1496 | /**************************************************************************/ 1497 | /*! 1498 | Configure the PWM 2 Clock 1499 | 1500 | @param on Whether to enable the clock 1501 | @param clock The Clock Divider 1502 | */ 1503 | /**************************************************************************/ 1504 | void Adafruit_RA8875::PWM2config(boolean on, uint8_t clock) { 1505 | if (on) { 1506 | writeReg(RA8875_P2CR, RA8875_P2CR_ENABLE | (clock & 0xF)); 1507 | } else { 1508 | writeReg(RA8875_P2CR, RA8875_P2CR_DISABLE | (clock & 0xF)); 1509 | } 1510 | } 1511 | 1512 | /**************************************************************************/ 1513 | /*! 1514 | Enables or disables the on-chip touch screen controller 1515 | 1516 | @param on Whether to turn touch sensing on or not 1517 | */ 1518 | /**************************************************************************/ 1519 | void Adafruit_RA8875::touchEnable(boolean on) { 1520 | uint8_t adcClk = (uint8_t)RA8875_TPCR0_ADCCLK_DIV4; 1521 | 1522 | if (_size == RA8875_800x480) // match up touch size with LCD size 1523 | adcClk = (uint8_t)RA8875_TPCR0_ADCCLK_DIV16; 1524 | 1525 | if (on) { 1526 | /* Enable Touch Panel (Reg 0x70) */ 1527 | writeReg(RA8875_TPCR0, RA8875_TPCR0_ENABLE | RA8875_TPCR0_WAIT_4096CLK | 1528 | RA8875_TPCR0_WAKEENABLE | adcClk); // 10mhz max! 1529 | /* Set Auto Mode (Reg 0x71) */ 1530 | writeReg(RA8875_TPCR1, RA8875_TPCR1_AUTO | 1531 | // RA8875_TPCR1_VREFEXT | 1532 | RA8875_TPCR1_DEBOUNCE); 1533 | /* Enable TP INT */ 1534 | writeReg(RA8875_INTC1, readReg(RA8875_INTC1) | RA8875_INTC1_TP); 1535 | } else { 1536 | /* Disable TP INT */ 1537 | writeReg(RA8875_INTC1, readReg(RA8875_INTC1) & ~RA8875_INTC1_TP); 1538 | /* Disable Touch Panel (Reg 0x70) */ 1539 | writeReg(RA8875_TPCR0, RA8875_TPCR0_DISABLE); 1540 | } 1541 | } 1542 | 1543 | /**************************************************************************/ 1544 | /*! 1545 | Checks if a touch event has occured 1546 | 1547 | @return True is a touch event has occured (reading it via 1548 | touchRead() will clear the interrupt in memory) 1549 | */ 1550 | /**************************************************************************/ 1551 | boolean Adafruit_RA8875::touched(void) { 1552 | if (readReg(RA8875_INTC2) & RA8875_INTC2_TP) 1553 | return true; 1554 | return false; 1555 | } 1556 | 1557 | /**************************************************************************/ 1558 | /*! 1559 | Reads the last touch event 1560 | 1561 | @param x Pointer to the uint16_t field to assign the raw X value 1562 | @param y Pointer to the uint16_t field to assign the raw Y value 1563 | 1564 | @return True if successful 1565 | 1566 | @note Calling this function will clear the touch panel interrupt on 1567 | the RA8875, resetting the flag used by the 'touched' function 1568 | */ 1569 | /**************************************************************************/ 1570 | boolean Adafruit_RA8875::touchRead(uint16_t *x, uint16_t *y) { 1571 | uint16_t tx, ty; 1572 | uint8_t temp; 1573 | 1574 | tx = readReg(RA8875_TPXH); 1575 | ty = readReg(RA8875_TPYH); 1576 | temp = readReg(RA8875_TPXYL); 1577 | tx <<= 2; 1578 | ty <<= 2; 1579 | tx |= temp & 0x03; // get the bottom x bits 1580 | ty |= (temp >> 2) & 0x03; // get the bottom y bits 1581 | 1582 | *x = tx; 1583 | *y = ty; 1584 | 1585 | /* Clear TP INT Status */ 1586 | writeReg(RA8875_INTC2, RA8875_INTC2_TP); 1587 | 1588 | return true; 1589 | } 1590 | 1591 | /**************************************************************************/ 1592 | /*! 1593 | Turns the display on or off 1594 | 1595 | @param on Whether to turn the display on or not 1596 | */ 1597 | /**************************************************************************/ 1598 | void Adafruit_RA8875::displayOn(boolean on) { 1599 | if (on) 1600 | writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPON); 1601 | else 1602 | writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPOFF); 1603 | } 1604 | 1605 | /**************************************************************************/ 1606 | /*! 1607 | Puts the display in sleep mode, or disables sleep mode if enabled 1608 | 1609 | @param sleep Whether to sleep or not 1610 | */ 1611 | /**************************************************************************/ 1612 | void Adafruit_RA8875::sleep(boolean sleep) { 1613 | if (sleep) 1614 | writeReg(RA8875_PWRR, RA8875_PWRR_DISPOFF | RA8875_PWRR_SLEEP); 1615 | else 1616 | writeReg(RA8875_PWRR, RA8875_PWRR_DISPOFF); 1617 | } 1618 | 1619 | /************************* Low Level ***********************************/ 1620 | 1621 | /**************************************************************************/ 1622 | /*! 1623 | Write data to the specified register 1624 | 1625 | @param reg Register to write to 1626 | @param val Value to write 1627 | */ 1628 | /**************************************************************************/ 1629 | void Adafruit_RA8875::writeReg(uint8_t reg, uint8_t val) { 1630 | writeCommand(reg); 1631 | writeData(val); 1632 | } 1633 | 1634 | /**************************************************************************/ 1635 | /*! 1636 | Set the register to read from 1637 | 1638 | @param reg Register to read 1639 | 1640 | @return The value 1641 | */ 1642 | /**************************************************************************/ 1643 | uint8_t Adafruit_RA8875::readReg(uint8_t reg) { 1644 | writeCommand(reg); 1645 | return readData(); 1646 | } 1647 | 1648 | /**************************************************************************/ 1649 | /*! 1650 | Write data to the current register 1651 | 1652 | @param d Data to write 1653 | */ 1654 | /**************************************************************************/ 1655 | void Adafruit_RA8875::writeData(uint8_t d) { 1656 | digitalWrite(_cs, LOW); 1657 | spi1_begin(); 1658 | SPI1.transfer(RA8875_DATAWRITE); 1659 | SPI1.transfer(d); 1660 | spi1_end(); 1661 | digitalWrite(_cs, HIGH); 1662 | } 1663 | 1664 | /**************************************************************************/ 1665 | /*! 1666 | Read the data from the current register 1667 | 1668 | @return The Value 1669 | */ 1670 | /**************************************************************************/ 1671 | uint8_t Adafruit_RA8875::readData(void) { 1672 | digitalWrite(_cs, LOW); 1673 | spi1_begin(); 1674 | 1675 | SPI1.transfer(RA8875_DATAREAD); 1676 | uint8_t x = SPI1.transfer(0x0); 1677 | spi1_end(); 1678 | 1679 | digitalWrite(_cs, HIGH); 1680 | return x; 1681 | } 1682 | 1683 | /**************************************************************************/ 1684 | /*! 1685 | Write a command to the current register 1686 | 1687 | @param d The data to write as a command 1688 | */ 1689 | /**************************************************************************/ 1690 | void Adafruit_RA8875::writeCommand(uint8_t d) { 1691 | digitalWrite(_cs, LOW); 1692 | spi1_begin(); 1693 | 1694 | SPI1.transfer(RA8875_CMDWRITE); 1695 | SPI1.transfer(d); 1696 | spi1_end(); 1697 | 1698 | digitalWrite(_cs, HIGH); 1699 | } 1700 | 1701 | /**************************************************************************/ 1702 | /*! 1703 | Read the status from the current register 1704 | 1705 | @return The value 1706 | */ 1707 | /**************************************************************************/ 1708 | uint8_t Adafruit_RA8875::readStatus(void) { 1709 | digitalWrite(_cs, LOW); 1710 | spi1_begin(); 1711 | SPI1.transfer(RA8875_CMDREAD); 1712 | uint8_t x = SPI1.transfer(0x0); 1713 | spi1_end(); 1714 | 1715 | digitalWrite(_cs, HIGH); 1716 | return x; 1717 | } 1718 | 1719 | /// @cond DISABLE 1720 | #if defined(EEPROM_SUPPORTED) 1721 | /// @endcond 1722 | /**************************************************************************/ 1723 | /*! 1724 | Read from the EEPROM location 1725 | 1726 | @param location The location of the EEPROM to read 1727 | 1728 | @return The value 1729 | */ 1730 | /**************************************************************************/ 1731 | 1732 | uint32_t Adafruit_RA8875::eepromReadS32(int location) { 1733 | uint32_t value = ((uint32_t)EEPROM.read(location)) << 24; 1734 | value = value | ((uint32_t)EEPROM.read(location + 1)) << 16; 1735 | value = value | ((uint32_t)EEPROM.read(location + 2)) << 8; 1736 | value = value | ((uint32_t)EEPROM.read(location + 3)); 1737 | return value; 1738 | } 1739 | 1740 | /**************************************************************************/ 1741 | /*! 1742 | Write to the EEPROM location 1743 | 1744 | @param location The location of the EEPROM to write to 1745 | @param value The value to write 1746 | */ 1747 | /**************************************************************************/ 1748 | void Adafruit_RA8875::eepromWriteS32(int location, int32_t value) { 1749 | EEPROM.write(location, (value >> 24) & 0xff); 1750 | EEPROM.write(location + 1, (value >> 16) & 0xff); 1751 | EEPROM.write(location + 2, (value >> 8) & 0xff); 1752 | EEPROM.write(location + 3, (value)&0xff); 1753 | } 1754 | 1755 | /**************************************************************************/ 1756 | /*! 1757 | Read Calibration Data from the EEPROM location 1758 | 1759 | @param location The location of the EEPROM to read from 1760 | @param matrixPtr The pointer to the Matrix Variable 1761 | 1762 | @return success 1763 | */ 1764 | /**************************************************************************/ 1765 | bool Adafruit_RA8875::readCalibration(int location, tsMatrix_t *matrixPtr) { 1766 | if (location + sizeof(tsMatrix_t) > EEPROMSIZE) { 1767 | return false; // readCalibration::Calibration location outside of EEPROM 1768 | // memory bound 1769 | } 1770 | if (EEPROM.read(location + CFG_EEPROM_TOUCHSCREEN_CALIBRATED) == 1) { 1771 | matrixPtr->An = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_AN); 1772 | matrixPtr->Bn = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_BN); 1773 | matrixPtr->Cn = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_CN); 1774 | matrixPtr->Dn = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_DN); 1775 | matrixPtr->En = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_EN); 1776 | matrixPtr->Fn = eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_FN); 1777 | matrixPtr->Divider = 1778 | eepromReadS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_DIVIDER); 1779 | return true; 1780 | } 1781 | return false; 1782 | } 1783 | 1784 | /**************************************************************************/ 1785 | /*! 1786 | Write Calibration Data to the EEPROM location 1787 | 1788 | @param location The location of the EEPROM to write to 1789 | @param matrixPtr The pointer to the Matrix Variable 1790 | */ 1791 | /**************************************************************************/ 1792 | void Adafruit_RA8875::writeCalibration(int location, tsMatrix_t *matrixPtr) { 1793 | if (location + sizeof(tsMatrix_t) < 1794 | EEPROMSIZE) { // Check to see it calibration location outside of EEPROM 1795 | // memory bound 1796 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_AN, matrixPtr->An); 1797 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_BN, matrixPtr->Bn); 1798 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_CN, matrixPtr->Cn); 1799 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_DN, matrixPtr->Dn); 1800 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_EN, matrixPtr->En); 1801 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_FN, matrixPtr->Fn); 1802 | eepromWriteS32(location + CFG_EEPROM_TOUCHSCREEN_CAL_DIVIDER, 1803 | matrixPtr->Divider); 1804 | EEPROM.write(location + CFG_EEPROM_TOUCHSCREEN_CALIBRATED, 1); 1805 | } 1806 | } 1807 | /// @cond DISABLE 1808 | #endif 1809 | /// @endcond 1810 | -------------------------------------------------------------------------------- /Adafruit_RA8875_spi1.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Adafruit_RA8875.h 4 | @author Limor Friend/Ladyada, K.Townsend/KTOWN for Adafruit Industries 5 | 6 | This is the library for the Adafruit RA8875 Driver board for TFT displays 7 | ---------------> http://www.adafruit.com/products/1590 8 | The RA8875 is a TFT driver for up to 800x480 dotclock'd displays 9 | It is tested to work with displays in the Adafruit shop. Other displays 10 | may need timing adjustments and are not guanteed to work. 11 | 12 | Adafruit invests time and resources providing this open 13 | source code, please support Adafruit and open-source hardware 14 | by purchasing products from Adafruit! 15 | 16 | Written by Limor Fried/Ladyada for Adafruit Industries. 17 | BSD license, check license.txt for more information. 18 | All text above must be included in any redistribution. 19 | */ 20 | /**************************************************************************/ 21 | 22 | #if ARDUINO >= 100 23 | #include "Arduino.h" 24 | #include "Print.h" 25 | #else 26 | #include "WProgram.h" 27 | #endif 28 | 29 | #ifdef __AVR 30 | #include 31 | #elif defined(ESP8266) 32 | #include 33 | #endif 34 | 35 | /// @cond DISABLE 36 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || \ 37 | defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(ESP32) || \ 38 | defined(DOXYGEN) 39 | /// @endcond 40 | #define EEPROM_SUPPORTED ///< Board supports EEPROM Storage 41 | /// @cond DISABLE 42 | #endif 43 | /// @endcond 44 | 45 | #include 46 | 47 | #ifndef _ADAFRUIT_RA8875_H 48 | #define _ADAFRUIT_RA8875_H ///< File has been included 49 | 50 | // Touchscreen Calibration and EEPROM Storage Defines 51 | #define CFG_EEPROM_TOUCHSCREEN_CAL_AN 0 ///< EEPROM Storage Location 52 | #define CFG_EEPROM_TOUCHSCREEN_CAL_BN 4 ///< EEPROM Storage Location 53 | #define CFG_EEPROM_TOUCHSCREEN_CAL_CN 8 ///< EEPROM Storage Location 54 | #define CFG_EEPROM_TOUCHSCREEN_CAL_DN 12 ///< EEPROM Storage Location 55 | #define CFG_EEPROM_TOUCHSCREEN_CAL_EN 16 ///< EEPROM Storage Location 56 | #define CFG_EEPROM_TOUCHSCREEN_CAL_FN 20 ///< EEPROM Storage Location 57 | #define CFG_EEPROM_TOUCHSCREEN_CAL_DIVIDER 24 ///< EEPROM Storage Location 58 | #define CFG_EEPROM_TOUCHSCREEN_CALIBRATED 28 ///< EEPROM Storage Location 59 | 60 | /// @cond DISABLE 61 | #if defined(EEPROM_SUPPORTED) 62 | #if defined(__AVR_ATmega328P__) 63 | /// @endcond 64 | #define EEPROMSIZE 1024 ///< 1KB EEPROM 65 | /// @cond DISABLE 66 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 67 | /// @endcond 68 | #define EEPROMSIZE 4096 ///< 4KB EEPROM 69 | /// @cond DISABLE 70 | #else 71 | /// @endcond 72 | #define EEPROMSIZE 512 ///< 512 Byte EEPROM 73 | /// @cond DISABLE 74 | #endif 75 | #endif 76 | /// @endcond 77 | // Sizes! 78 | 79 | /**************************************************************************/ 80 | /*! 81 | @enum RA8875sizes The Supported Screen Sizes 82 | */ 83 | /**************************************************************************/ 84 | enum RA8875sizes { 85 | RA8875_480x80, /*!< 480x80 Pixel Display */ 86 | RA8875_480x128, /*!< 480x128 Pixel Display */ 87 | RA8875_480x272, /*!< 480x272 Pixel Display */ 88 | RA8875_800x480 /*!< 800x480 Pixel Display */ 89 | }; 90 | 91 | /**************************************************************************/ 92 | /*! 93 | @struct Point 94 | Calibration Point 95 | 96 | @var Point::x 97 | x-coordinate 98 | @var Point::y 99 | y-coordinate 100 | */ 101 | /**************************************************************************/ 102 | typedef struct Point { 103 | int32_t x; 104 | int32_t y; 105 | } tsPoint_t; ///< Nameless struct variable! 106 | 107 | /**************************************************************************/ 108 | /*! 109 | @struct tsMatrix_t 110 | Calibration Data Structure 111 | 112 | @var tsMatrix_t::An 113 | A Coefficient with the coarsest granularity 114 | @var tsMatrix_t::Bn 115 | B Coeffiecient 116 | @var tsMatrix_t::Cn 117 | C Coefficient 118 | @var tsMatrix_t::Dn 119 | D Coeffiecient 120 | @var tsMatrix_t::En 121 | E Coefficient 122 | @var tsMatrix_t::Fn 123 | F Coeffiecient with the finest granularity 124 | @var tsMatrix_t::Divider 125 | Divider for Coefficients 126 | */ 127 | /**************************************************************************/ 128 | typedef struct // Matrix 129 | { 130 | int32_t An, Bn, Cn, Dn, En, Fn, Divider; 131 | } tsMatrix_t; 132 | 133 | /**************************************************************************/ 134 | /*! 135 | @brief Class that stores state and functions for interacting with 136 | the RA8875 display controller. 137 | */ 138 | /**************************************************************************/ 139 | class Adafruit_RA8875 : public Adafruit_GFX { 140 | public: 141 | Adafruit_RA8875(uint8_t cs, uint8_t rst); 142 | 143 | boolean begin(enum RA8875sizes s); 144 | void softReset(void); 145 | void displayOn(boolean on); 146 | void sleep(boolean sleep); 147 | 148 | /* Text functions */ 149 | void textMode(void); 150 | void textSetCursor(uint16_t x, uint16_t y); 151 | void textColor(uint16_t foreColor, uint16_t bgColor); 152 | void textTransparent(uint16_t foreColor); 153 | void textEnlarge(uint8_t scale); 154 | void textWrite(const char *buffer, uint16_t len = 0); 155 | void cursorBlink(uint8_t rate); 156 | 157 | /* Graphics functions */ 158 | void graphicsMode(void); 159 | void setXY(uint16_t x, uint16_t y); 160 | void pushPixels(uint32_t num, uint16_t p); 161 | void fillRect(void); 162 | 163 | /* Adafruit_GFX functions */ 164 | void drawPixel(int16_t x, int16_t y, uint16_t color); 165 | void drawPixels(uint16_t *p, uint32_t count, int16_t x, int16_t y); 166 | void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); 167 | void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); 168 | 169 | /* HW accelerated wrapper functions (override Adafruit_GFX prototypes) */ 170 | void fillScreen(uint16_t color); 171 | void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); 172 | void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 173 | void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 174 | void drawCircle(int16_t x, int16_t y, int16_t r, uint16_t color); 175 | void fillCircle(int16_t x, int16_t y, int16_t r, uint16_t color); 176 | void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, 177 | int16_t y2, uint16_t color); 178 | void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, 179 | int16_t y2, uint16_t color); 180 | void drawEllipse(int16_t xCenter, int16_t yCenter, int16_t longAxis, 181 | int16_t shortAxis, uint16_t color); 182 | void fillEllipse(int16_t xCenter, int16_t yCenter, int16_t longAxis, 183 | int16_t shortAxis, uint16_t color); 184 | void drawCurve(int16_t xCenter, int16_t yCenter, int16_t longAxis, 185 | int16_t shortAxis, uint8_t curvePart, uint16_t color); 186 | void fillCurve(int16_t xCenter, int16_t yCenter, int16_t longAxis, 187 | int16_t shortAxis, uint8_t curvePart, uint16_t color); 188 | void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, 189 | uint16_t color); 190 | void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, 191 | uint16_t color); 192 | 193 | /* Scroll */ 194 | void setScrollWindow(int16_t x, int16_t y, int16_t w, int16_t h, 195 | uint8_t mode); 196 | void scrollX(int16_t dist); 197 | void scrollY(int16_t dist); 198 | 199 | /* Backlight */ 200 | void GPIOX(boolean on); 201 | void PWM1config(boolean on, uint8_t clock); 202 | void PWM2config(boolean on, uint8_t clock); 203 | void PWM1out(uint8_t p); 204 | void PWM2out(uint8_t p); 205 | 206 | /* Touch screen */ 207 | void touchEnable(boolean on); 208 | boolean touched(void); 209 | boolean touchRead(uint16_t *x, uint16_t *y); 210 | 211 | /// @cond DISABLE 212 | #if defined(EEPROM_SUPPORTED) 213 | /// @endcond 214 | /* Touch screen calibration persistence*/ 215 | uint32_t eepromReadS32(int location); 216 | void eepromWriteS32(int location, int32_t value); 217 | bool readCalibration(int location, tsMatrix_t *matrixPtr); 218 | void writeCalibration(int location, tsMatrix_t *matrixPtr); 219 | /// @cond DISABLE 220 | #endif 221 | /// @endcond 222 | 223 | /* Low level access */ 224 | void writeReg(uint8_t reg, uint8_t val); 225 | uint8_t readReg(uint8_t reg); 226 | void writeData(uint8_t d); 227 | uint8_t readData(void); 228 | void writeCommand(uint8_t d); 229 | uint8_t readStatus(void); 230 | boolean waitPoll(uint8_t r, uint8_t f); 231 | uint16_t width(void); 232 | uint16_t height(void); 233 | void setRotation(int8_t rotation); 234 | int8_t getRotation(void); 235 | 236 | #ifndef USE_ADAFRUIT_GFX_FONTS 237 | /**************************************************************************/ 238 | /*! 239 | Alias of textWrite to Play nice with Arduino's Print class 240 | 241 | @param b The string to write 242 | 243 | @return The number of bytes written 244 | */ 245 | /**************************************************************************/ 246 | virtual size_t write(uint8_t b) { 247 | textWrite((const char *)&b, 1); 248 | return 1; 249 | } 250 | 251 | /**************************************************************************/ 252 | /*! 253 | Alias of textWrite to Play nice with Arduino's Print class 254 | 255 | @param buffer The buffer to write 256 | @param size The size of the buffer 257 | 258 | @return The number of bytes written 259 | */ 260 | /**************************************************************************/ 261 | virtual size_t write(const uint8_t *buffer, size_t size) { 262 | textWrite((const char *)buffer, size); 263 | return size; 264 | } 265 | #endif 266 | 267 | private: 268 | void PLLinit(void); 269 | void initialize(void); 270 | 271 | /* GFX Helper Functions */ 272 | void circleHelper(int16_t x, int16_t y, int16_t r, uint16_t color, 273 | bool filled); 274 | void rectHelper(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color, 275 | bool filled); 276 | void triangleHelper(int16_t x0, int16_t y0, int16_t x1, int16_t y1, 277 | int16_t x2, int16_t y2, uint16_t color, bool filled); 278 | void ellipseHelper(int16_t xCenter, int16_t yCenter, int16_t longAxis, 279 | int16_t shortAxis, uint16_t color, bool filled); 280 | void curveHelper(int16_t xCenter, int16_t yCenter, int16_t longAxis, 281 | int16_t shortAxis, uint8_t curvePart, uint16_t color, 282 | bool filled); 283 | void roundRectHelper(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, 284 | uint16_t color, bool filled); 285 | 286 | /* Rotation Functions */ 287 | int16_t applyRotationX(int16_t x); 288 | int16_t applyRotationY(int16_t y); 289 | 290 | void swap(int16_t &x, int16_t &y) { 291 | int16_t temp = x; 292 | x = y; 293 | y = temp; 294 | } 295 | 296 | uint8_t _cs, _rst; 297 | uint16_t _width, _height; 298 | uint8_t _textScale; 299 | uint8_t _rotation; 300 | uint8_t _voffset; 301 | enum RA8875sizes _size; 302 | }; 303 | 304 | // Colors (RGB565) 305 | #define RA8875_BLACK 0x0000 ///< Black Color 306 | #define RA8875_BLUE 0x001F ///< Blue Color 307 | #define RA8875_RED 0xF800 ///< Red Color 308 | #define RA8875_GREEN 0x07E0 ///< Green Color 309 | #define RA8875_CYAN 0x07FF ///< Cyan Color 310 | #define RA8875_MAGENTA 0xF81F ///< Magenta Color 311 | #define RA8875_YELLOW 0xFFE0 ///< Yellow Color 312 | #define RA8875_WHITE 0xFFFF ///< White Color 313 | 314 | // Command/Data pins for SPI 315 | #define RA8875_DATAWRITE 0x00 ///< See datasheet 316 | #define RA8875_DATAREAD 0x40 ///< See datasheet 317 | #define RA8875_CMDWRITE 0x80 ///< See datasheet 318 | #define RA8875_CMDREAD 0xC0 ///< See datasheet 319 | 320 | // Registers & bits 321 | #define RA8875_PWRR 0x01 ///< See datasheet 322 | #define RA8875_PWRR_DISPON 0x80 ///< See datasheet 323 | #define RA8875_PWRR_DISPOFF 0x00 ///< See datasheet 324 | #define RA8875_PWRR_SLEEP 0x02 ///< See datasheet 325 | #define RA8875_PWRR_NORMAL 0x00 ///< See datasheet 326 | #define RA8875_PWRR_SOFTRESET 0x01 ///< See datasheet 327 | 328 | #define RA8875_MRWC 0x02 ///< See datasheet 329 | 330 | #define RA8875_GPIOX 0xC7 ///< See datasheet 331 | 332 | #define RA8875_PLLC1 0x88 ///< See datasheet 333 | #define RA8875_PLLC1_PLLDIV2 0x80 ///< See datasheet 334 | #define RA8875_PLLC1_PLLDIV1 0x00 ///< See datasheet 335 | 336 | #define RA8875_PLLC2 0x89 ///< See datasheet 337 | #define RA8875_PLLC2_DIV1 0x00 ///< See datasheet 338 | #define RA8875_PLLC2_DIV2 0x01 ///< See datasheet 339 | #define RA8875_PLLC2_DIV4 0x02 ///< See datasheet 340 | #define RA8875_PLLC2_DIV8 0x03 ///< See datasheet 341 | #define RA8875_PLLC2_DIV16 0x04 ///< See datasheet 342 | #define RA8875_PLLC2_DIV32 0x05 ///< See datasheet 343 | #define RA8875_PLLC2_DIV64 0x06 ///< See datasheet 344 | #define RA8875_PLLC2_DIV128 0x07 ///< See datasheet 345 | 346 | #define RA8875_SYSR 0x10 ///< See datasheet 347 | #define RA8875_SYSR_8BPP 0x00 ///< See datasheet 348 | #define RA8875_SYSR_16BPP 0x0C ///< See datasheet 349 | #define RA8875_SYSR_MCU8 0x00 ///< See datasheet 350 | #define RA8875_SYSR_MCU16 0x03 ///< See datasheet 351 | 352 | #define RA8875_PCSR 0x04 ///< See datasheet 353 | #define RA8875_PCSR_PDATR 0x00 ///< See datasheet 354 | #define RA8875_PCSR_PDATL 0x80 ///< See datasheet 355 | #define RA8875_PCSR_CLK 0x00 ///< See datasheet 356 | #define RA8875_PCSR_2CLK 0x01 ///< See datasheet 357 | #define RA8875_PCSR_4CLK 0x02 ///< See datasheet 358 | #define RA8875_PCSR_8CLK 0x03 ///< See datasheet 359 | 360 | #define RA8875_HDWR 0x14 ///< See datasheet 361 | 362 | #define RA8875_HNDFTR 0x15 ///< See datasheet 363 | #define RA8875_HNDFTR_DE_HIGH 0x00 ///< See datasheet 364 | #define RA8875_HNDFTR_DE_LOW 0x80 ///< See datasheet 365 | 366 | #define RA8875_HNDR 0x16 ///< See datasheet 367 | #define RA8875_HSTR 0x17 ///< See datasheet 368 | #define RA8875_HPWR 0x18 ///< See datasheet 369 | #define RA8875_HPWR_LOW 0x00 ///< See datasheet 370 | #define RA8875_HPWR_HIGH 0x80 ///< See datasheet 371 | 372 | #define RA8875_VDHR0 0x19 ///< See datasheet 373 | #define RA8875_VDHR1 0x1A ///< See datasheet 374 | #define RA8875_VNDR0 0x1B ///< See datasheet 375 | #define RA8875_VNDR1 0x1C ///< See datasheet 376 | #define RA8875_VSTR0 0x1D ///< See datasheet 377 | #define RA8875_VSTR1 0x1E ///< See datasheet 378 | #define RA8875_VPWR 0x1F ///< See datasheet 379 | #define RA8875_VPWR_LOW 0x00 ///< See datasheet 380 | #define RA8875_VPWR_HIGH 0x80 ///< See datasheet 381 | 382 | #define RA8875_HSAW0 0x30 ///< See datasheet 383 | #define RA8875_HSAW1 0x31 ///< See datasheet 384 | #define RA8875_VSAW0 0x32 ///< See datasheet 385 | #define RA8875_VSAW1 0x33 ///< See datasheet 386 | 387 | #define RA8875_HEAW0 0x34 ///< See datasheet 388 | #define RA8875_HEAW1 0x35 ///< See datasheet 389 | #define RA8875_VEAW0 0x36 ///< See datasheet 390 | #define RA8875_VEAW1 0x37 ///< See datasheet 391 | 392 | #define RA8875_MCLR 0x8E ///< See datasheet 393 | #define RA8875_MCLR_START 0x80 ///< See datasheet 394 | #define RA8875_MCLR_STOP 0x00 ///< See datasheet 395 | #define RA8875_MCLR_READSTATUS 0x80 ///< See datasheet 396 | #define RA8875_MCLR_FULL 0x00 ///< See datasheet 397 | #define RA8875_MCLR_ACTIVE 0x40 ///< See datasheet 398 | 399 | #define RA8875_DCR 0x90 ///< See datasheet 400 | #define RA8875_DCR_LINESQUTRI_START 0x80 ///< See datasheet 401 | #define RA8875_DCR_LINESQUTRI_STOP 0x00 ///< See datasheet 402 | #define RA8875_DCR_LINESQUTRI_STATUS 0x80 ///< See datasheet 403 | #define RA8875_DCR_CIRCLE_START 0x40 ///< See datasheet 404 | #define RA8875_DCR_CIRCLE_STATUS 0x40 ///< See datasheet 405 | #define RA8875_DCR_CIRCLE_STOP 0x00 ///< See datasheet 406 | #define RA8875_DCR_FILL 0x20 ///< See datasheet 407 | #define RA8875_DCR_NOFILL 0x00 ///< See datasheet 408 | #define RA8875_DCR_DRAWLINE 0x00 ///< See datasheet 409 | #define RA8875_DCR_DRAWTRIANGLE 0x01 ///< See datasheet 410 | #define RA8875_DCR_DRAWSQUARE 0x10 ///< See datasheet 411 | 412 | #define RA8875_ELLIPSE 0xA0 ///< See datasheet 413 | #define RA8875_ELLIPSE_STATUS 0x80 ///< See datasheet 414 | 415 | #define RA8875_MWCR0 0x40 ///< See datasheet 416 | #define RA8875_MWCR0_GFXMODE 0x00 ///< See datasheet 417 | #define RA8875_MWCR0_TXTMODE 0x80 ///< See datasheet 418 | #define RA8875_MWCR0_CURSOR 0x40 ///< See datasheet 419 | #define RA8875_MWCR0_BLINK 0x20 ///< See datasheet 420 | 421 | #define RA8875_MWCR0_DIRMASK 0x0C ///< Bitmask for Write Direction 422 | #define RA8875_MWCR0_LRTD 0x00 ///< Left->Right then Top->Down 423 | #define RA8875_MWCR0_RLTD 0x04 ///< Right->Left then Top->Down 424 | #define RA8875_MWCR0_TDLR 0x08 ///< Top->Down then Left->Right 425 | #define RA8875_MWCR0_DTLR 0x0C ///< Down->Top then Left->Right 426 | 427 | #define RA8875_BTCR 0x44 ///< See datasheet 428 | #define RA8875_CURH0 0x46 ///< See datasheet 429 | #define RA8875_CURH1 0x47 ///< See datasheet 430 | #define RA8875_CURV0 0x48 ///< See datasheet 431 | #define RA8875_CURV1 0x49 ///< See datasheet 432 | 433 | #define RA8875_P1CR 0x8A ///< See datasheet 434 | #define RA8875_P1CR_ENABLE 0x80 ///< See datasheet 435 | #define RA8875_P1CR_DISABLE 0x00 ///< See datasheet 436 | #define RA8875_P1CR_CLKOUT 0x10 ///< See datasheet 437 | #define RA8875_P1CR_PWMOUT 0x00 ///< See datasheet 438 | 439 | #define RA8875_P1DCR 0x8B ///< See datasheet 440 | 441 | #define RA8875_P2CR 0x8C ///< See datasheet 442 | #define RA8875_P2CR_ENABLE 0x80 ///< See datasheet 443 | #define RA8875_P2CR_DISABLE 0x00 ///< See datasheet 444 | #define RA8875_P2CR_CLKOUT 0x10 ///< See datasheet 445 | #define RA8875_P2CR_PWMOUT 0x00 ///< See datasheet 446 | 447 | #define RA8875_P2DCR 0x8D ///< See datasheet 448 | 449 | #define RA8875_PWM_CLK_DIV1 0x00 ///< See datasheet 450 | #define RA8875_PWM_CLK_DIV2 0x01 ///< See datasheet 451 | #define RA8875_PWM_CLK_DIV4 0x02 ///< See datasheet 452 | #define RA8875_PWM_CLK_DIV8 0x03 ///< See datasheet 453 | #define RA8875_PWM_CLK_DIV16 0x04 ///< See datasheet 454 | #define RA8875_PWM_CLK_DIV32 0x05 ///< See datasheet 455 | #define RA8875_PWM_CLK_DIV64 0x06 ///< See datasheet 456 | #define RA8875_PWM_CLK_DIV128 0x07 ///< See datasheet 457 | #define RA8875_PWM_CLK_DIV256 0x08 ///< See datasheet 458 | #define RA8875_PWM_CLK_DIV512 0x09 ///< See datasheet 459 | #define RA8875_PWM_CLK_DIV1024 0x0A ///< See datasheet 460 | #define RA8875_PWM_CLK_DIV2048 0x0B ///< See datasheet 461 | #define RA8875_PWM_CLK_DIV4096 0x0C ///< See datasheet 462 | #define RA8875_PWM_CLK_DIV8192 0x0D ///< See datasheet 463 | #define RA8875_PWM_CLK_DIV16384 0x0E ///< See datasheet 464 | #define RA8875_PWM_CLK_DIV32768 0x0F ///< See datasheet 465 | 466 | #define RA8875_TPCR0 0x70 ///< See datasheet 467 | #define RA8875_TPCR0_ENABLE 0x80 ///< See datasheet 468 | #define RA8875_TPCR0_DISABLE 0x00 ///< See datasheet 469 | #define RA8875_TPCR0_WAIT_512CLK 0x00 ///< See datasheet 470 | #define RA8875_TPCR0_WAIT_1024CLK 0x10 ///< See datasheet 471 | #define RA8875_TPCR0_WAIT_2048CLK 0x20 ///< See datasheet 472 | #define RA8875_TPCR0_WAIT_4096CLK 0x30 ///< See datasheet 473 | #define RA8875_TPCR0_WAIT_8192CLK 0x40 ///< See datasheet 474 | #define RA8875_TPCR0_WAIT_16384CLK 0x50 ///< See datasheet 475 | #define RA8875_TPCR0_WAIT_32768CLK 0x60 ///< See datasheet 476 | #define RA8875_TPCR0_WAIT_65536CLK 0x70 ///< See datasheet 477 | #define RA8875_TPCR0_WAKEENABLE 0x08 ///< See datasheet 478 | #define RA8875_TPCR0_WAKEDISABLE 0x00 ///< See datasheet 479 | #define RA8875_TPCR0_ADCCLK_DIV1 0x00 ///< See datasheet 480 | #define RA8875_TPCR0_ADCCLK_DIV2 0x01 ///< See datasheet 481 | #define RA8875_TPCR0_ADCCLK_DIV4 0x02 ///< See datasheet 482 | #define RA8875_TPCR0_ADCCLK_DIV8 0x03 ///< See datasheet 483 | #define RA8875_TPCR0_ADCCLK_DIV16 0x04 ///< See datasheet 484 | #define RA8875_TPCR0_ADCCLK_DIV32 0x05 ///< See datasheet 485 | #define RA8875_TPCR0_ADCCLK_DIV64 0x06 ///< See datasheet 486 | #define RA8875_TPCR0_ADCCLK_DIV128 0x07 ///< See datasheet 487 | 488 | #define RA8875_TPCR1 0x71 ///< See datasheet 489 | #define RA8875_TPCR1_AUTO 0x00 ///< See datasheet 490 | #define RA8875_TPCR1_MANUAL 0x40 ///< See datasheet 491 | #define RA8875_TPCR1_VREFINT 0x00 ///< See datasheet 492 | #define RA8875_TPCR1_VREFEXT 0x20 ///< See datasheet 493 | #define RA8875_TPCR1_DEBOUNCE 0x04 ///< See datasheet 494 | #define RA8875_TPCR1_NODEBOUNCE 0x00 ///< See datasheet 495 | #define RA8875_TPCR1_IDLE 0x00 ///< See datasheet 496 | #define RA8875_TPCR1_WAIT 0x01 ///< See datasheet 497 | #define RA8875_TPCR1_LATCHX 0x02 ///< See datasheet 498 | #define RA8875_TPCR1_LATCHY 0x03 ///< See datasheet 499 | 500 | #define RA8875_TPXH 0x72 ///< See datasheet 501 | #define RA8875_TPYH 0x73 ///< See datasheet 502 | #define RA8875_TPXYL 0x74 ///< See datasheet 503 | 504 | #define RA8875_INTC1 0xF0 ///< See datasheet 505 | #define RA8875_INTC1_KEY 0x10 ///< See datasheet 506 | #define RA8875_INTC1_DMA 0x08 ///< See datasheet 507 | #define RA8875_INTC1_TP 0x04 ///< See datasheet 508 | #define RA8875_INTC1_BTE 0x02 ///< See datasheet 509 | 510 | #define RA8875_INTC2 0xF1 ///< See datasheet 511 | #define RA8875_INTC2_KEY 0x10 ///< See datasheet 512 | #define RA8875_INTC2_DMA 0x08 ///< See datasheet 513 | #define RA8875_INTC2_TP 0x04 ///< See datasheet 514 | #define RA8875_INTC2_BTE 0x02 ///< See datasheet 515 | 516 | #define RA8875_SCROLL_BOTH 0x00 ///< See datasheet 517 | #define RA8875_SCROLL_LAYER1 0x40 ///< See datasheet 518 | #define RA8875_SCROLL_LAYER2 0x80 ///< See datasheet 519 | #define RA8875_SCROLL_BUFFER 0xC0 ///< See datasheet 520 | 521 | #endif 522 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 ErsatzMoco 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 | -------------------------------------------------------------------------------- /LispDeck.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/LispDeck.jpg -------------------------------------------------------------------------------- /LispboxLibrary.h: -------------------------------------------------------------------------------- 1 | /* 2 | LispBox LispLibrary - Version 1.2 - Mar 2025 3 | Hartmut Grawe - github.com/ersatzmoco - Jan 2025 4 | 5 | Some parts based on: 6 | ErsatzMoco microcontroller framework - github.com/ersatzmoco/ersatzmoco 7 | Hartmut Grawe - github.com/ersatzmoco - July 2020 8 | Please see there for further explanations on how to use the framework. 9 | M5Cardputer editor version by hasn0life - Nov 2024 - https://github.com/hasn0life/ulisp-sedit-m5cardputer 10 | 11 | This uLisp version licensed under the MIT license: https://opensource.org/licenses/MIT 12 | */ 13 | 14 | 15 | 16 | // MOCO-COMMANDS - not implemented as Lisp constants to save memory 17 | // following commentary sections just for reference - just use the decimal values and write code name into comment 18 | 19 | 20 | // EM_ACK = 0 #!< Acknowledge received command 21 | 22 | // EM_REC_PING = 1 #!< Wait for ping signal 23 | // EM_SEND_PING = 2 #!< Send ping signal 24 | 25 | // EM_ACT_DCM_SPEED = 3 #!< DC motor: Set speed 26 | // EM_ACT_DCM_STOP = 4 #!< DC motor: Stop motor 27 | // EM_ACT_DCM_BRAKE = 5 #!< DC motor: force stop 28 | // EM_ACT_DCM_CW = 6 #!< DC motor: set direction to clockwise 29 | // EM_ACT_DCM_CCW = 7 #!< DC motor: set direction to counterclockwise 30 | 31 | // EM_ACT_DOUT_HI = 8 #!< Set the indicated digital output pin to high state 32 | // EM_ACT_DOUT_LO = 9 #!< Set the indicated digital output pin to low state 33 | // EM_ACT_DOUT_INPUT = 10 #!< Set the indicated digital pin to input state 34 | // EM_ACT_DOUT_OUTPUT = 11 #!< Set the indicated digital pin to output state 35 | 36 | // EM_ACT_AOUT_VAL = 12 #!< Set the indicated analog pin to a value - see descendants of base type Actuator how to use this command 37 | 38 | // EM_ACT_PWM_VAL = 13 #!< Set the indicated analog pin to a pwm value - see descendants of base type Actuator how to use this command 39 | 40 | // EM_ACT_AUDIO_TRACK = 14 #!< Audio module: Select track to play 41 | // EM_ACT_AUDIO_PLAY = 15 #!< Audio module: Play selected track 42 | // EM_ACT_AUDIO_STOP = 16 #!< Audio module: Set volume 43 | // EM_ACT_AUDIO_VOL = 17 #!< Audio module: Stop playback 44 | 45 | // EM_ACT_SERVO_ANGLE = 18 #!< Servo: Set angle 46 | 47 | // EM_ACT_SERVOMOTOR_SPEED = 19 #!< Continuous servo: Set speed 48 | 49 | // EM_DISP_MSG = 20 #!< Display a message string 50 | // EM_DISP_CHAR = 21 #!< Display an ascii character indicated by an int number 51 | 52 | // EM_ACT_STM_STEP = 22 #!< Stepper motor: Execute one step 53 | // EM_ACT_STM_CW = 23 #!< Stepper motor: Set direction to clockwise 54 | // EM_ACT_STM_CCW = 24 #!< Stepper motor: Set direction to counterclockwise 55 | // EM_ACT_STM_SET_DIST = 25 #!< Stepper motor: Set distance to move the object driven by the stepper 56 | // EM_ACT_STM_SET_TIME = 26 #!< Stepper motor: Set time frame for covering the currently set distance 57 | // EM_ACT_STM_START = 27 #!< Stepper motor: Start motion from current position to distance in selected time frame 58 | // EM_ACT_STM_STOP = 28 #!< Stepper motor: Stop the motor within the deceleration period set in the StepperUnit header 59 | // EM_ACT_STM_EMERGENCY_STOP = 29 #!< Stepper motor: Stop motor immediately. CAUTION: This may damage the motor! 60 | // EM_ACT_STM_ENABLE = 30 #!< Stepper motor: Set driver to "enabled", i.e. connect power and force motor to maintain current position 61 | // EM_ACT_STM_DISABLE = 31 #!< Stepper motor: Set driver to "disbled", i.e. disconnect power. Motor may be moved by external forces. 62 | 63 | // EM_ACT_RELAY_OFF = 32 #!< Relay: Open contact 64 | // EM_ACT_RELAY_ON = 33 #!< Relay: Close contact 65 | 66 | // EM_RMT_SIGNAL = 40 #!< RemoteAction: Send Signal and require acknowledge 67 | // EM_RMT_SIGNAL_CANCEL = 41 #!< RemoteAction: Cancel sent signal 68 | // EM_RMT_REMOTE_TOGGLE = 42 #!< RemoteAction: Switch on remote function 69 | // EM_RMT_REMOTE_PULSE = 43 #!< RemoteAction: Switch off remote function 70 | // EM_RMT_SIGNAL_ACK = 44 #!< RemoteAction: Acknowledge signal 71 | 72 | 73 | const char LispLibrary[] PROGMEM = R"lisplibrary( 74 | 75 | #| SET THE FOLLOWING VARIABLE TO NIL TO DEACTIVATE LISPY LITTLE HELPER |# 76 | 77 | (defvar se:help-active t) 78 | 79 | #| BACKLIGHT OF SECONDARY DISPLAY DISABLED BY DEFAULT TO SAVE ENERGY |# 80 | 81 | (set-backlight 0) 82 | 83 | (backtrace t) 84 | 85 | ; 86 | ; Extended ULOS functions 87 | ; 88 | ; 89 | ; Define a class 90 | (defun class (&optional parent slots constructor) 91 | #.(format nil "(class [parent] [slotlist] [constructor t/nil])~%ULOS function to define a new class or instance of a class.~%To define a new class, pass it to a variable, adding a list of property/method slots according to ULOS mechanism, optionally passing a parent class to inherit from.~%To define an instance, pass a parent class (= the prototype), omit the slots and set constructor to t.~%That way, the slots of the parent class are automatically copied into the instance.~%Setting the slots of the parent is equivalent to setting class variables, then.") 92 | (let ((obj (when parent (list (cons 'parent parent))))) 93 | (when (and constructor parent) 94 | (when (symbolp parent) (setq parent (eval parent))) 95 | (loop 96 | (when (null parent) (return parent)) 97 | (unless (or (equal (search "_" (string (first parent))) 1) (search "parent" (string (first parent))) ) 98 | (push (cons (car (first parent)) (cdr (first parent))) obj)) 99 | (setq parent (cdr parent))) 100 | ) 101 | (loop 102 | (when (null slots) (return obj)) 103 | (push (cons (first slots) (second slots)) obj) 104 | (setq slots (cddr slots))) 105 | ) 106 | ) 107 | 108 | ; Get the value of a property slot in an instance/class or its parents 109 | (defun gtv (obj slot) 110 | #.(format nil "(gtv obj 'slot)~%ULOS function to get value of property slot in obj.") 111 | (when (symbolp obj) (setq obj (eval obj))) 112 | (let ((pair (assoc slot obj))) 113 | (if pair (cdr pair) 114 | (let ((p (cdr (assoc 'parent obj)))) 115 | (and p (gtv p slot)))) 116 | ) 117 | ) 118 | 119 | ; Update a property in an instance/class 120 | (defun stv (obj slot value) 121 | #.(format nil "(stv obj 'slot value)~%ULOS function to set value of property slot in obj.") 122 | (when (symbolp obj) (setq obj (eval obj))) 123 | (let ((pair (assoc slot obj))) 124 | (when pair (setf (cdr pair) value)) 125 | ) 126 | ) 127 | 128 | ; Add property and method slots 129 | (defun adp (obj slots) 130 | #.(format nil "(adp 'obj slotlist)~%ULOS function to add new property/method slots to obj, similar to JavaScript mechanism.") 131 | (let (newlist) 132 | (loop 133 | (when (null slots) (return)) 134 | (push (cons (first slots) (second slots)) newlist) 135 | (setq slots (cddr slots))) 136 | (set obj (append (eval obj) newlist)) 137 | ) 138 | ) 139 | 140 | ; Call a method in an object instance 141 | ; 142 | (defun cmt (obj method &rest arguments) 143 | #.(format nil "(cmt obj 'method [arguments])~%ULOS function to call method of obj, providing a list of arguments.") 144 | (apply (eval (gtv obj method)) (append (list obj) arguments)) 145 | ) 146 | 147 | 148 | ; 149 | ; RGB helper function 150 | ; 151 | ; 152 | (defun rgb (r g b) 153 | #.(format nil "(rgb r g b)~%Builds 16 bit color value from red, green and blue components provided as 8-bit integers.") 154 | (logior (ash (logand r #xf8) 8) (ash (logand g #xfc) 3) (ash b -3)) 155 | ) 156 | 157 | 158 | ; 159 | ; LispBox screen editor 160 | ; Functions without built-in help to save memory. 161 | ; 162 | ; 163 | (defun se:init (sk) 164 | (case sk 165 | (t 166 | (defvar se:code_col (rgb 255 155 55)) 167 | (defvar se:line_col (rgb 90 60 30)) 168 | (defvar se:border_col (rgb 63 40 0)) 169 | (defvar se:bg_col (rgb 10 5 0)) 170 | (defvar se:cursor_col (rgb 160 60 0)) 171 | (defvar se:emph_col (rgb 0 128 0)) 172 | (defvar se:alert_col (rgb 255 0 0)) 173 | (defvar se:input_col (rgb 255 255 255)) 174 | 175 | (defvar se:help_col (rgb 255 127 0)) 176 | ) 177 | ) 178 | 179 | (defvar se:origin (cons 34 18)) 180 | (defvar se:txtpos (cons 0 0)) 181 | (defvar se:lasttxtpos (cons 0 0)) 182 | (defvar se:txtmax (cons 94 26)) 183 | (defvar se:offset (cons 0 0)) 184 | (defvar se:scrpos (cons 0 0)) 185 | (defvar se:lastc nil) 186 | (defvar se:funcname nil) 187 | (defvar se:symname nil) 188 | (defvar se:filename nil) 189 | (defvar se:suffix nil) 190 | (defvar se:buffer ()) 191 | (defvar se:bufbak ()) 192 | (defvar se:editable t) 193 | (defvar se:curline "") 194 | (defvar se:copyline "") 195 | (defvar se:sniplist '("\"\"" "()" "(lambda ())" "(setf )" "(defvar )" "(let (()) )" "(when )" "(unless )" "(dotimes (i ) )" "#| |#")) 196 | (defvar se:tscale 1) 197 | (defvar se:leading (* 16 se:tscale)) 198 | (defvar se:cwidth (* 8 se:tscale)) 199 | (defvar se:openings ()) 200 | (defvar se:closings ()) 201 | (defvar se:lastmatch ()) 202 | (defvar se:match nil) 203 | (defvar se:exit nil) 204 | (defvar se:numtabs 2) 205 | 206 | (when se:help-active 207 | (defvar se:CLK 16) 208 | (defvar se:DT 14) 209 | (defvar se:SW 20) 210 | (pinmode se:CLK nil) 211 | (pinmode se:DT nil) 212 | (pinmode se:SW nil) 213 | 214 | (defvar se:sw-state t) 215 | (defvar se:clk-state (digitalread se:CLK)) 216 | ) 217 | 218 | (fill-screen) 219 | (set-cursor 0 0) 220 | (set-text-color se:code_col se:bg_col) 221 | 222 | (tft1-graphics-mode) 223 | (tft1-set-scroll-win 0 0 800 480) 224 | (tft1-set-scrollX 0) 225 | (tft1-set-scrollY 0) 226 | (tft1-fill-screen) 227 | (tft1-draw-line 33 17 33 451 se:border_col) 228 | (tft1-draw-line 0 451 799 451 se:border_col) 229 | (tft1-text-mode) 230 | #| (tft1-text-enlarge (1- se:tscale)) |# 231 | (tft1-set-cursor 0 0) 232 | (tft1-set-text-color se:bg_col se:cursor_col) 233 | (if se:help-active 234 | (tft1-write-text "F1/F2 chk () | F3 help | F5 bind | | F9 del | F10 save | F11 load | F12 dir") 235 | (tft1-write-text "F1/F2 chk () | F5 bind | | F9 del | F10 save | F11 load | F12 dir") 236 | ) 237 | ) 238 | 239 | (defun se:cleanup () 240 | (makunbound 'se:buffer) 241 | (makunbound 'se:bufbak) 242 | (makunbound 'se:openings) 243 | (makunbound 'se:closings) 244 | (makunbound 'se:curline) 245 | (makunbound 'se:copyline) 246 | (makunbound 'se:sniplist) 247 | (gc) 248 | ) 249 | 250 | (defun se:hide-cursor () 251 | (when se:lastmatch 252 | (let ((spos nil) (bpos (car se:lastmatch)) (br (cdr se:lastmatch))) 253 | (setf spos (se:calc-scrpos bpos)) 254 | (tft1-set-cursor (car spos) (cdr spos)) 255 | (tft1-set-text-color se:code_col se:bg_col) 256 | (tft1-write-text (string br)) 257 | (setf se:lastmatch nil) 258 | ) 259 | ) 260 | (when se:lastc 261 | (tft1-set-cursor (car se:scrpos) (cdr se:scrpos)) 262 | (tft1-set-text-color se:code_col se:bg_col) 263 | (tft1-write-text (string se:lastc)) 264 | (tft1-set-cursor 0 (cdr se:scrpos)) 265 | (tft1-set-text-color se:line_col) 266 | (tft1-write-text (string (1+ (cdr se:txtpos)))) 267 | ) 268 | ) 269 | 270 | (defun se:show-cursor (&optional forceb) 271 | (let ((x (car se:txtpos)) 272 | (y (cdr se:txtpos)) 273 | (ox (car se:offset)) 274 | (oy (cdr se:offset)) 275 | (padx (car se:origin)) 276 | (pady (cdr se:origin)) 277 | (myc (code-char 32))) 278 | (setf se:curline (nth y se:buffer)) 279 | (setf se:scrpos (se:calc-scrpos se:txtpos)) 280 | (tft1-set-cursor (car se:scrpos) (cdr se:scrpos)) 281 | (tft1-set-text-color se:code_col se:cursor_col) 282 | #| check if cursor is within line string or behind last char |# 283 | (when (< x (length se:curline)) (setf myc (char se:curline x))) 284 | (setf se:lastc myc) 285 | (if forceb 286 | (progn 287 | (setf se:match t) 288 | (se:write-char (char-code myc)) 289 | (setf se:match nil) 290 | ) 291 | (se:write-char (char-code myc)) 292 | ) 293 | (tft1-set-cursor 0 (cdr se:scrpos)) 294 | (tft1-set-text-color se:cursor_col) 295 | (tft1-write-text (string (1+ y))) 296 | ) 297 | ) 298 | 299 | (defun se:toggle-match () 300 | (keyboard-flush) 301 | (if se:match 302 | (progn 303 | (setf se:match nil) (setf se:openings ()) (setf se:closings ()) 304 | (tft1-set-cursor 0 0) 305 | (tft1-set-text-color se:bg_col se:cursor_col) 306 | (tft1-write-text "F1") 307 | (keyboard-flush) 308 | ) 309 | (progn 310 | (setf se:match t) 311 | (tft1-set-cursor 0 0) 312 | (tft1-set-text-color se:bg_col se:emph_col) 313 | (tft1-write-text "F1") 314 | (se:hide-cursor) 315 | (se:map-brackets) 316 | (keyboard-flush) 317 | (se:show-cursor) 318 | ) 319 | ) 320 | ) 321 | 322 | (defun se:checkbr () 323 | (keyboard-flush) 324 | (se:hide-cursor) 325 | (se:map-brackets t) 326 | (se:show-cursor t) 327 | (setf se:openings ()) 328 | (setf se:closings ()) 329 | (setf se:match nil) 330 | (tft1-set-cursor 0 0) 331 | (tft1-set-text-color se:bg_col se:cursor_col) 332 | (tft1-write-text "F1") 333 | (keyboard-flush) 334 | ) 335 | 336 | (defun se:map-brackets (&optional forcemp) 337 | (when (or se:match forcemp) 338 | (let ((myline "") (keys ()) (octr 0) (bl (length se:buffer))) 339 | (dotimes (y bl) 340 | (setf myline (nth y se:buffer)) 341 | (dotimes (x (length myline)) 342 | (when (equal (char-code (char myline x)) 40) (push (cons (cons x y) octr) se:openings) (push octr keys) (incf octr)) 343 | (when (equal (char-code (char myline x)) 41) (push (cons (cons x y) (if keys (pop keys) nil)) se:closings)) 344 | ) 345 | ) 346 | ) 347 | ) 348 | ) 349 | 350 | (defun se:find-closing-bracket () 351 | (let ((opentry (assoc* se:txtpos se:openings #'equal)) (clentry nil)) 352 | (if opentry 353 | (progn 354 | (setf clentry (reverse-assoc* (cdr opentry) se:closings #'equal)) 355 | (if clentry 356 | clentry 357 | nil 358 | ) 359 | ) 360 | nil 361 | ) 362 | ) 363 | ) 364 | 365 | (defun se:find-opening-bracket () 366 | (let ((clentry (assoc* se:txtpos se:closings #'equal)) (opentry nil)) 367 | (if clentry 368 | (progn 369 | (setf opentry (reverse-assoc* (cdr clentry) se:openings #'equal)) 370 | (if opentry 371 | opentry 372 | nil 373 | ) 374 | ) 375 | nil 376 | ) 377 | ) 378 | ) 379 | 380 | (defun se:in-window (pos) 381 | (if (and (>= (car pos) (car se:offset)) (<= (car pos) (+ (car se:offset) (car se:txtmax)))) 382 | (if (and (>= (cdr pos) (cdr se:offset)) (<= (cdr pos) (+ (cdr se:offset) (cdr se:txtmax)))) 383 | t 384 | nil 385 | ) 386 | nil 387 | ) 388 | ) 389 | 390 | (defun se:move-window (&optional forceshow) 391 | (let ((x (car se:txtpos)) 392 | (y (cdr se:txtpos)) 393 | (ox (car se:offset)) 394 | (oy (cdr se:offset)) 395 | (xm (car se:txtmax)) 396 | (ym (cdr se:txtmax))) 397 | (when (> x (+ ox xm)) 398 | (setf (car se:offset) (+ (car se:offset) (- x (+ ox xm)))) 399 | (setf forceshow t) 400 | ) 401 | (when (> y (+ oy ym)) 402 | (setf (cdr se:offset) (+ (cdr se:offset) (- y (+ oy ym)))) 403 | (setf forceshow t) 404 | ) 405 | (when (< x ox) 406 | (setf (car se:offset) (- (car se:offset) (- ox x))) 407 | (setf forceshow t) 408 | ) 409 | (when (< y oy) 410 | (setf (cdr se:offset) (- (cdr se:offset) (- oy y))) 411 | (setf forceshow t) 412 | ) 413 | (when forceshow 414 | (se:show-text) 415 | ) 416 | ) 417 | ) 418 | 419 | (defun se:calc-scrpos (tpos) 420 | (let ((sx 0) (sy 0) (ox (car se:offset)) (oy (cdr se:offset)) (padx (car se:origin)) (pady (cdr se:origin))) 421 | (setf sx (+ (* (- (car tpos) ox) se:cwidth) padx)) 422 | (setf sy (+ (* (- (cdr tpos) oy) se:leading) pady)) 423 | (cons sx sy) 424 | ) 425 | ) 426 | 427 | (defun se:calc-msgpos (tpos) 428 | (let ((sx 0) (sy 0) (padx (car se:origin)) (pady (cdr se:origin))) 429 | (setf sx (+ (* (car tpos) se:cwidth) padx)) 430 | (setf sy (+ (* (cdr tpos) se:leading) pady)) 431 | (cons sx sy) 432 | ) 433 | ) 434 | 435 | (defun se:write-char (cc) 436 | (let ((bpos nil) (spos nil)) 437 | (cond 438 | ((and (= cc 40) se:match) 439 | (setf bpos (se:find-closing-bracket)) 440 | (when bpos 441 | (when (se:in-window bpos) 442 | (setf spos (se:calc-scrpos bpos)) 443 | (tft1-set-cursor (car spos) (cdr spos)) 444 | (tft1-set-text-color se:code_col se:emph_col) 445 | (tft1-write-text ")") 446 | (setf se:lastmatch (cons bpos ")")) 447 | ) 448 | (tft1-set-text-color se:code_col se:emph_col) 449 | ) 450 | (tft1-set-cursor (car se:scrpos) (cdr se:scrpos)) 451 | (tft1-write-text (string (code-char cc))) 452 | (tft1-set-text-color se:code_col se:bg_col) 453 | ) 454 | ((and (= cc 41) se:match) 455 | (setf bpos (se:find-opening-bracket)) 456 | (when bpos 457 | (when (se:in-window bpos) 458 | (setf spos (se:calc-scrpos bpos)) 459 | (tft1-set-cursor (car spos) (cdr spos)) 460 | (tft1-set-text-color se:code_col se:emph_col) 461 | (tft1-write-text "(") 462 | (setf se:lastmatch (cons bpos "(")) 463 | ) 464 | (tft1-set-text-color se:code_col se:emph_col) 465 | ) 466 | (tft1-set-cursor (car se:scrpos) (cdr se:scrpos)) 467 | (tft1-write-text (string (code-char cc))) 468 | (tft1-set-text-color se:code_col se:bg_col) 469 | ) 470 | (t (tft1-write-text (string (code-char cc)))) 471 | ) 472 | ) 473 | ) 474 | 475 | (defun se:disp-line (y) 476 | (let ((ypos (+ (cdr se:origin) (* (- y (cdr se:offset)) se:leading))) (myl " ")) 477 | (when (nth y se:buffer) (setf myl (concatenate 'string (nth y se:buffer) myl))) 478 | (tft1-set-text-color se:line_col) 479 | (tft1-set-cursor 0 ypos) 480 | (tft1-write-text (string (1+ y))) 481 | 482 | (tft1-set-cursor (car se:origin) ypos) 483 | (tft1-set-text-color se:code_col se:bg_col) 484 | (when (> (length myl) (car se:offset)) 485 | (tft1-write-text (subseq myl (car se:offset) (min (length myl) (+ (car se:txtmax) (car se:offset) 1)))) 486 | ) 487 | ) 488 | ) 489 | 490 | (defun se:show-text () 491 | (tft1-fill-rect 34 18 763 432 se:bg_col) 492 | (tft1-fill-rect 0 18 33 432 se:bg_col) 493 | (let ((i 0) (ymax (min (cdr se:txtmax) (- (length se:buffer) (cdr se:offset) 1)))) 494 | (loop 495 | (se:disp-line (+ i (cdr se:offset))) 496 | (when (= i ymax) (return)) 497 | (incf i) 498 | ) 499 | ) 500 | ) 501 | 502 | (defun se:show-dir () 503 | (keyboard-flush) 504 | (se:hide-cursor) 505 | (if se:editable 506 | (progn 507 | (setf se:editable nil) 508 | (se:save-buffer) 509 | (let ((dirbuf (sd-card-dir 2))) 510 | (se:compile-dir dirbuf 0) 511 | (setq se:buffer (reverse se:buffer)) 512 | ) 513 | (se:map-brackets) 514 | (se:move-window t) 515 | 516 | (tft1-set-cursor (* 36 se:cwidth) 0) 517 | (tft1-set-text-color se:alert_col se:line_col) 518 | (tft1-write-text "SD DIRECTORY") 519 | 520 | ) 521 | (se:restore-buffer) 522 | ) 523 | (se:show-cursor) 524 | (keyboard-flush) 525 | ) 526 | 527 | (defun se:compile-dir (mydir tab) 528 | (let ((tabstr "")) 529 | (dotimes (i tab) 530 | (setf tabstr (concatenate 'string tabstr " ")) 531 | ) 532 | (dolist (entry mydir) 533 | (if (listp entry) 534 | (se:compile-dir entry (+ tab 3)) 535 | (push (concatenate 'string tabstr entry) se:buffer) 536 | ) 537 | ) 538 | ) 539 | ) 540 | 541 | (defun se:flush-buffer () 542 | (when se:editable 543 | (keyboard-flush) 544 | (when (se:alert "Flush buffer") 545 | (se:hide-cursor) 546 | (setq se:buffer (list "")) 547 | (setf se:txtpos (cons 0 0)) 548 | (setf se:offset (cons 0 0)) 549 | (setf se:filename nil) 550 | (setf se:funcname nil) 551 | (tft1-set-cursor (* 36 se:cwidth) 0) 552 | (tft1-set-text-color se:code_col se:cursor_col) 553 | (tft1-write-text " ") 554 | (se:show-text) 555 | (se:show-cursor) 556 | (keyboard-flush) 557 | ) 558 | ) 559 | ) 560 | 561 | (defun se:flush-line () 562 | (when se:editable 563 | (keyboard-flush) 564 | (se:hide-cursor) 565 | (let* ((x (car se:txtpos)) 566 | (y (cdr se:txtpos)) 567 | (myl se:curline) 568 | (firsthalf "")) 569 | (progn 570 | (setf firsthalf (subseq myl 0 x)) 571 | (setf se:copyline (subseq myl x (length myl))) 572 | (setf (nth y se:buffer) firsthalf) 573 | (setf se:curline (concatenate 'string (nth y se:buffer) " ")) 574 | (setf se:lastc nil) 575 | (se:disp-line y) 576 | ) 577 | ) 578 | (se:map-brackets) 579 | (se:show-text) 580 | (se:show-cursor) 581 | (keyboard-flush) 582 | ) 583 | ) 584 | 585 | (defun se:insert (newc) 586 | (when se:editable 587 | (se:hide-cursor) 588 | (let* ((x (car se:txtpos)) 589 | (y (cdr se:txtpos)) 590 | (myl se:curline) 591 | (firsthalf "") 592 | (scdhalf "")) 593 | (setf firsthalf (subseq myl 0 x)) 594 | (setf scdhalf (subseq myl x (length myl))) 595 | (setf (nth y se:buffer) (concatenate 'string firsthalf (string newc) scdhalf)) 596 | (incf (car se:txtpos)) 597 | (setf se:curline (nth y se:buffer)) 598 | (setf se:lastc nil) 599 | (if (> (car se:txtpos) (car se:txtmax)) (se:move-window) (se:disp-line y)) 600 | ) 601 | (se:map-brackets) 602 | (se:show-cursor) 603 | ) 604 | ) 605 | 606 | (defun se:tab (numtabs) 607 | (keyboard-flush) 608 | (dotimes (i numtabs) 609 | (se:insert #\032) 610 | ) 611 | (keyboard-flush) 612 | ) 613 | 614 | (defun se:enter () 615 | (when se:editable 616 | (se:hide-cursor) 617 | (let* ((x (car se:txtpos)) 618 | (y (cdr se:txtpos)) 619 | (myl se:curline) 620 | (firsthalf "") 621 | (scdhalf "") 622 | (newl () )) 623 | (setf firsthalf (subseq myl 0 x)) 624 | (setf scdhalf (subseq myl x (length myl))) 625 | (dotimes (i y) 626 | (push (nth i se:buffer) newl) 627 | ) 628 | (push firsthalf newl) 629 | (push scdhalf newl) 630 | (dotimes (i (- (length se:buffer) (1+ y))) 631 | (push (nth (+ i (1+ y)) se:buffer) newl) 632 | ) 633 | (setf se:buffer (reverse newl)) 634 | (setf (car se:txtpos) 0) 635 | (incf (cdr se:txtpos)) 636 | (setf se:curline (nth (1+ y) se:buffer)) 637 | (setf se:lastc nil) 638 | (setf (car se:offset) 0) 639 | (se:move-window t) 640 | ) 641 | (se:map-brackets) 642 | (se:show-cursor) 643 | ) 644 | ) 645 | 646 | (defun se:delete () 647 | (when se:editable 648 | (se:hide-cursor) 649 | (let* ((x (car se:txtpos)) 650 | (y (cdr se:txtpos)) 651 | (myl se:curline) 652 | (firsthalf "") 653 | (scdhalf "")) 654 | (if (> x 0) 655 | (progn 656 | (setf firsthalf (subseq myl 0 (1- x))) 657 | (setf scdhalf (subseq myl x (length myl))) 658 | (setf (nth y se:buffer) (concatenate 'string firsthalf scdhalf)) 659 | (setf se:curline (concatenate 'string (nth y se:buffer) " ")) 660 | (decf (car se:txtpos)) 661 | (setf se:lastc nil) 662 | (se:disp-line y) 663 | ) 664 | (when (> y 0) 665 | (setf scdhalf se:curline) 666 | (setf se:buffer (remove y se:buffer)) 667 | (decf (cdr se:txtpos)) 668 | (decf y) 669 | (setf se:curline (nth y se:buffer)) 670 | (setf firsthalf se:curline) 671 | (if firsthalf 672 | (progn 673 | (setf (nth y se:buffer) (concatenate 'string firsthalf scdhalf)) 674 | (setf (car se:txtpos) (length firsthalf)) 675 | ) 676 | (progn 677 | (setf (nth y se:buffer) scdhalf) 678 | (setf (car se:txtpos) 0) 679 | ) 680 | ) 681 | (se:move-window t) 682 | ) 683 | ) 684 | ) 685 | (se:map-brackets) 686 | (se:show-cursor) 687 | ) 688 | ) 689 | 690 | (defun se:copy () 691 | (keyboard-flush) 692 | (setf se:copyline se:curline) 693 | (keyboard-flush) 694 | ) 695 | 696 | (defun se:paste () 697 | (when se:editable 698 | (keyboard-flush) 699 | (when se:copyline 700 | (dotimes (i (length se:copyline)) 701 | (se:insert (char se:copyline i)) 702 | ) 703 | ) 704 | (keyboard-flush) 705 | ) 706 | ) 707 | 708 | (defun se:snippet (lk) 709 | (keyboard-flush) 710 | (let ((sn (nth (- lk 240) se:sniplist))) 711 | (when (> (length sn) 0) 712 | (dotimes (i (length sn)) 713 | (se:insert (char sn i)) 714 | ) 715 | ) 716 | ) 717 | (keyboard-flush) 718 | ) 719 | 720 | (defun se:left () 721 | (se:hide-cursor) 722 | (cond 723 | #| xpos > 0 |# 724 | ((> (car se:txtpos) 0) 725 | (decf (car se:txtpos)) 726 | (se:move-window) 727 | ) 728 | #| xpos == 0, but ypos > 0 |# 729 | ((> (cdr se:txtpos) 0) 730 | (decf (cdr se:txtpos)) 731 | (setf (car se:txtpos) (length (nth (cdr se:txtpos) se:buffer))) 732 | (se:move-window) 733 | ) 734 | ) 735 | (se:show-cursor) 736 | ) 737 | 738 | (defun se:right () 739 | (se:hide-cursor) 740 | (cond 741 | #| xpos < eol |# 742 | ((< (car se:txtpos) (length se:curline)) 743 | (incf (car se:txtpos)) 744 | (se:move-window) 745 | ) 746 | #| xpos == eol, but ypos < end of se:buffer |# 747 | ((< (cdr se:txtpos) (1- (length se:buffer))) 748 | (incf (cdr se:txtpos)) 749 | (setf (car se:txtpos) 0) 750 | (se:move-window) 751 | ) 752 | ) 753 | (se:show-cursor) 754 | ) 755 | 756 | (defun se:up () 757 | (se:hide-cursor) 758 | (cond 759 | #| ypos > 0 |# 760 | ((> (cdr se:txtpos) 0) 761 | (decf (cdr se:txtpos)) 762 | (setf se:curline (nth (cdr se:txtpos) se:buffer)) 763 | (when (> (car se:txtpos) (length se:curline)) 764 | (setf (car se:txtpos) (length se:curline)) 765 | ) 766 | (se:move-window) 767 | ) 768 | ) 769 | (se:show-cursor) 770 | ) 771 | 772 | (defun se:down () 773 | (se:hide-cursor) 774 | (cond 775 | #| ypos < length of se:buffer |# 776 | ((< (cdr se:txtpos) (1- (length se:buffer))) 777 | (incf (cdr se:txtpos)) 778 | (setf se:curline (nth (cdr se:txtpos) se:buffer)) 779 | (when (> (car se:txtpos) (1+ (length se:curline))) (setf (car se:txtpos) (length se:curline))) 780 | (se:move-window) 781 | ) 782 | ) 783 | (se:show-cursor) 784 | ) 785 | 786 | (defun se:linestart () 787 | (se:hide-cursor) 788 | (setf (car se:txtpos) 0) 789 | (se:move-window) 790 | (se:show-cursor) 791 | ) 792 | 793 | (defun se:lineend () 794 | (se:hide-cursor) 795 | (setf (car se:txtpos) (length se:curline)) 796 | (se:move-window) 797 | (se:show-cursor) 798 | ) 799 | 800 | (defun se:nextpage () 801 | (se:hide-cursor) 802 | (setf (cdr se:txtpos) (min (length se:buffer) (+ (cdr se:txtpos) (cdr se:txtmax) 1))) 803 | (se:move-window) 804 | (se:show-cursor) 805 | ) 806 | 807 | (defun se:prevpage () 808 | (se:hide-cursor) 809 | (setf (cdr se:txtpos) (max 0 (- (cdr se:txtpos) (cdr se:txtmax) 1))) 810 | (se:move-window) 811 | (se:show-cursor) 812 | ) 813 | 814 | (defun se:docstart () 815 | (se:hide-cursor) 816 | (setf se:txtpos (cons 0 0)) 817 | (se:move-window) 818 | (se:show-cursor) 819 | ) 820 | 821 | (defun se:run () 822 | (when se:editable 823 | (let ((body "") (fname (se:input "Symbol name: " se:funcname 60))) 824 | (mapc (lambda (x) (setf body (concatenate 'string body x))) se:buffer) 825 | (if fname 826 | (when (se:alert (concatenate 'string "Bind code to symbol " fname " ")) 827 | (eval (read-from-string (concatenate 'string (format nil "(defvar ~a" fname) (format nil " '~a)" body)))) 828 | (se:msg "Done! Returning to REPL") 829 | (delay 2000) 830 | (se:clr-msg) 831 | (se:cleanup) 832 | (setf se:exit t) 833 | ) 834 | (eval (read-from-string body)) 835 | ) 836 | ) 837 | ) 838 | ) 839 | 840 | (defun se:remove () 841 | (let ((fname (se:input "DELETE file name (UPPERCASE only): " nil 8 t)) (suffix (se:input "Suffix: ." "CL" 3 t))) 842 | (if (sd-file-exists (concatenate 'string fname "." suffix)) 843 | (when (se:alert (concatenate 'string "Delete file " fname "." suffix)) 844 | (sd-file-remove (concatenate 'string fname "." suffix)) 845 | (se:msg "Done! Returning to editor.") 846 | (delay 1000) 847 | (se:clr-msg) 848 | ) 849 | ) 850 | ) 851 | 852 | ) 853 | 854 | (defun se:save () 855 | (unless se:suffix (setf se:suffix "CL")) 856 | (let ((fname (se:input "SAVE file name (UPPERCASE only): " se:filename 8 t)) (suffix (se:input "Suffix: ." se:suffix 3 t)) (overwrite t) (fullname "")) 857 | (setf fullname (concatenate 'string fname "." suffix)) 858 | (if (sd-file-exists fullname) 859 | (unless (se:alert "File exists. Overwrite") 860 | (setf overwrite nil) 861 | ) 862 | ) 863 | (unless (or (< (length fname) 1) (< (length suffix) 1) (not overwrite)) 864 | (when overwrite (sd-file-remove fullname)) 865 | (with-sd-card (strm fullname 2) 866 | (dolist (line se:buffer) 867 | (princ line strm) 868 | (princ (code-char 10) strm) 869 | ) 870 | ) 871 | (tft1-set-cursor (* 36 se:cwidth) 0) 872 | (tft1-set-text-color se:code_col se:cursor_col) 873 | (setf se:filename fname) 874 | (setf se:suffix suffix) 875 | (tft1-write-text (concatenate 'string "FILE: " fname "." suffix " ")) 876 | (se:msg "Done! Returning to editor.") 877 | (delay 1000) 878 | (se:clr-msg) 879 | ) 880 | ) 881 | ) 882 | 883 | (defun se:quicksave () 884 | (when se:editable 885 | (keyboard-flush) 886 | (sd-file-remove "BACKUP.CL") 887 | (with-sd-card (strm "BACKUP.CL" 2) 888 | (dolist (line se:buffer) 889 | (princ line strm) 890 | (princ (code-char 10) strm) 891 | ) 892 | ) 893 | (se:msg "SAVED to BACKUP.CL") 894 | (delay 500) 895 | (keyboard-flush) 896 | (se:clr-msg) 897 | ) 898 | ) 899 | 900 | (defun se:load () 901 | (when se:editable 902 | (when (se:alert "Discard buffer and load from SD") 903 | (let ((fname (se:input "LOAD file name (UPPERCASE only): " nil 8 t)) (suffix (se:input "Suffix: ." "CL" 3 t)) (line "")) 904 | (unless (or (< (length fname) 1) (< (length suffix) 1) (not (sd-file-exists (concatenate 'string fname "." suffix)))) 905 | (setq se:buffer ()) 906 | (setf se:funcname nil) 907 | (with-sd-card (strm (concatenate 'string fname "." suffix) 0) 908 | (loop 909 | (setf line (read-line strm)) 910 | (if line 911 | (push line se:buffer) 912 | (return) 913 | ) 914 | ) 915 | ) 916 | (setf se:buffer (reverse se:buffer)) 917 | (se:hide-cursor) 918 | (se:map-brackets t) 919 | (tft1-set-cursor (* 36 se:cwidth) 0) 920 | (tft1-set-text-color se:code_col se:cursor_col) 921 | (setf se:filename fname) 922 | (setf se:suffix suffix) 923 | (tft1-write-text (concatenate 'string "FILE: " fname "." suffix " ")) 924 | (setf se:txtpos (cons 0 0)) 925 | (setf se:offset (cons 0 0)) 926 | (se:show-text) 927 | (se:show-cursor) 928 | ) 929 | ) 930 | ) 931 | ) 932 | ) 933 | 934 | (defun se:save-buffer () 935 | (setq se:bufbak (copy-list se:buffer)) 936 | (setf se:lasttxtpos (cons (car se:txtpos) (cdr se:txtpos))) 937 | (setf se:txtpos (cons 0 0)) 938 | (setq se:buffer ()) 939 | (tft1-set-cursor 0 0) 940 | (tft1-set-text-color se:code_col se:line_col) 941 | (if se:help-active 942 | (tft1-write-text "F1/F2 chk () | F3 help | F4 BACK | F9 del | F10 save ") 943 | (tft1-write-text "F1/F2 chk () | F4 BACK | F9 del | F10 save ") 944 | ) 945 | (when se:match 946 | (tft1-set-cursor 0 0) 947 | (tft1-set-text-color se:bg_col se:emph_col) 948 | (tft1-write-text "F1") 949 | ) 950 | ) 951 | 952 | (defun se:restore-buffer () 953 | (setq se:buffer (copy-list se:bufbak)) 954 | (makunbound 'se:bufbak) 955 | (defvar se:bufbak nil) 956 | (se:map-brackets) 957 | (tft1-set-cursor 0 0) 958 | (tft1-set-text-color se:bg_col se:cursor_col) 959 | (if se:help-active 960 | (tft1-write-text "F1/F2 chk () | F3 help | F5 bind | | F9 del | F10 save | F11 load | F12 dir") 961 | (tft1-write-text "F1/F2 chk () | F5 bind | | F9 del | F10 save | F11 load | F12 dir") 962 | ) 963 | (if (or se:funcname se:filename) 964 | (let ((myname "") (mytype "")) 965 | (if se:funcname 966 | (progn (setf myname se:funcname) (setf mytype "SYM: ")) 967 | (progn (setf myname se:filename) (setf mytype "FILE: ")) 968 | ) 969 | (tft1-set-cursor (* 36 se:cwidth) 0) 970 | (tft1-set-text-color se:code_col se:cursor_col) 971 | (if (> (length myname) 13) 972 | (tft1-write-text (concatenate 'string mytype (subseq myname 0 10) "...")) 973 | (tft1-write-text (concatenate 'string mytype myname)) 974 | ) 975 | ) 976 | (progn 977 | (tft1-set-cursor (* 36 se:cwidth) 0) 978 | (tft1-set-text-color se:code_col se:cursor_col) 979 | (tft1-write-text " ") 980 | ) 981 | ) 982 | (when se:match 983 | (tft1-set-cursor 0 0) 984 | (tft1-set-text-color se:bg_col se:emph_col) 985 | (tft1-write-text "F1") 986 | ) 987 | (setf se:txtpos (cons (car se:lasttxtpos) (cdr se:lasttxtpos))) 988 | (se:move-window t) 989 | (setf se:editable t) 990 | ) 991 | 992 | (defun se:viewsym () 993 | (keyboard-flush) 994 | (se:hide-cursor) 995 | (if se:editable 996 | (let ((symname (se:input "SYMBOL: " nil 60))) 997 | (when (boundp (read-from-string symname)) 998 | (setf se:editable nil) 999 | (se:save-buffer) 1000 | (setq se:buffer (cdr (split-string-to-list (string #\Newline) (string (with-output-to-string (str) (pprint (eval (read-from-string symname)) str)))))) 1001 | (se:map-brackets) 1002 | (se:move-window t) 1003 | 1004 | (tft1-set-cursor (* 36 se:cwidth) 0) 1005 | (tft1-set-text-color se:alert_col se:line_col) 1006 | (if (> (length symname) 13) 1007 | (tft1-write-text (concatenate 'string "SYM: " (subseq symname 0 10) "...")) 1008 | (tft1-write-text (concatenate 'string "SYM: " symname)) 1009 | ) 1010 | ) 1011 | ) 1012 | (se:restore-buffer) 1013 | ) 1014 | (se:show-cursor) 1015 | (keyboard-flush) 1016 | ) 1017 | 1018 | (defun se:loadview () 1019 | (keyboard-flush) 1020 | (se:hide-cursor) 1021 | (if se:editable 1022 | (let ((fname (se:input "VIEW file (UPPERCASE only): " nil 8 t)) (suffix (se:input "Suffix: ." "CL" 3 t)) (line "")) 1023 | (unless (or (< (length fname) 1) (< (length suffix) 1) (not (sd-file-exists (concatenate 'string fname "." suffix)))) 1024 | (setf se:editable nil) 1025 | (se:save-buffer) 1026 | (with-sd-card (strm (concatenate 'string fname "." suffix) 0) 1027 | (loop 1028 | (setf line (read-line strm)) 1029 | (if line 1030 | (push line se:buffer) 1031 | (return) 1032 | ) 1033 | ) 1034 | ) 1035 | (setf se:buffer (reverse se:buffer)) 1036 | (se:map-brackets t) 1037 | (se:move-window t) 1038 | (tft1-set-cursor (* 36 se:cwidth) 0) 1039 | (tft1-set-text-color se:alert_col se:line_col) 1040 | (tft1-write-text (concatenate 'string "FILE: " fname "." suffix " ")) 1041 | ) 1042 | ) 1043 | (se:restore-buffer) 1044 | ) 1045 | (se:show-cursor) 1046 | (keyboard-flush) 1047 | ) 1048 | 1049 | (defun se:alert (mymsg) 1050 | (keyboard-flush) 1051 | (se:msg (concatenate 'string mymsg " y/n ?") t) 1052 | (let ((lk nil)) 1053 | (loop 1054 | (when lk (return)) 1055 | (setf lk (keyboard-get-key t)) 1056 | ) 1057 | (se:clr-msg) 1058 | (keyboard-flush) 1059 | (if (or (= lk 121) (= lk 89)) 1060 | t 1061 | nil 1062 | ) 1063 | ) 1064 | ) 1065 | 1066 | (defun se:msg (mymsg &optional alert cursor) 1067 | (if alert 1068 | (tft1-set-text-color se:alert_col) 1069 | (tft1-set-text-color se:emph_col) 1070 | ) 1071 | (let ((spos (se:calc-msgpos (cons 0 (1+ (cdr se:txtmax)))))) 1072 | (tft1-set-cursor (+ (car spos) 2) (+ (cdr spos) 2)) 1073 | (tft1-write-text mymsg) 1074 | ) 1075 | (when cursor 1076 | (setf cursor (max 0 cursor)) 1077 | (let ((spos (se:calc-msgpos (cons cursor (1+ (cdr se:txtmax)))))) 1078 | (tft1-set-text-color se:code_col se:emph_col) 1079 | (tft1-set-cursor (+ (car spos) 2) (+ (cdr spos) 2)) 1080 | (tft1-write-text (subseq mymsg cursor (1+ cursor))) 1081 | ) 1082 | ) 1083 | ) 1084 | 1085 | (defun se:input (mymsg default maxlen &optional chkanum) 1086 | (keyboard-flush) 1087 | (let* ((ibuf "") (lastkey nil) (newkey nil) (lkd nil) (lku nil) 1088 | (lpos (1+ (cdr se:txtmax))) 1089 | (istart (length mymsg)) 1090 | (iend (min maxlen (- (car se:txtmax) istart 1))) 1091 | (ipos 0)) 1092 | 1093 | (when default (setf ibuf default)) 1094 | (se:msg (concatenate 'string mymsg ibuf " ") nil istart) 1095 | (loop 1096 | (when (not lastkey) 1097 | (setf lkd (keyboard-get-key t)) 1098 | (when lkd (setf lastkey lkd) (setf newkey t)) 1099 | ) 1100 | (when (and lastkey newkey) 1101 | (setf newkey nil) 1102 | (case lastkey 1103 | (216 (when (> ipos 0) (decf ipos))) 1104 | (215 (when (< ipos (length ibuf)) (incf ipos))) 1105 | (10 (se:clr-msg) (keyboard-flush) (return ibuf)) 1106 | (127 (if (> ipos 0) 1107 | (progn 1108 | (decf ipos) 1109 | (setf ibuf (concatenate 'string (subseq ibuf 0 ipos) (subseq ibuf (1+ ipos)))) 1110 | ) 1111 | (setf ibuf "") 1112 | ) 1113 | ) 1114 | (t 1115 | (if chkanum 1116 | (when (and (< (length ibuf) maxlen) (se:alphnum lastkey)) 1117 | (setf ibuf (concatenate 'string (subseq ibuf 0 ipos) (string (code-char lastkey)) (subseq ibuf ipos (length ibuf)))) 1118 | (incf ipos) 1119 | ) 1120 | (when (< (length ibuf) maxlen) 1121 | (setf ibuf (concatenate 'string (subseq ibuf 0 ipos) (string (code-char lastkey)) (subseq ibuf ipos (length ibuf)))) 1122 | (incf ipos) 1123 | ) 1124 | ) 1125 | ) 1126 | ) 1127 | (se:clr-msg) 1128 | (se:msg (concatenate 'string mymsg ibuf " ") nil (+ istart ipos)) 1129 | ) 1130 | (setf lku (keyboard-get-key)) 1131 | (when lku (setf newkey nil) (setf lastkey nil)) 1132 | ) 1133 | ) 1134 | ) 1135 | 1136 | (defun se:alphnum (chr) 1137 | (if (or (= chr 31) (= chr 45) (= chr 95) (and (> chr 64) (< chr 91)) (and (> chr 47) (< chr 58))) 1138 | t 1139 | nil 1140 | ) 1141 | ) 1142 | 1143 | (defun se:clr-msg () 1144 | (tft1-fill-rect 34 452 763 27 se:bg_col) 1145 | ) 1146 | 1147 | (defun se:sedit (&optional myform myskin) 1148 | #.(format nil "(se:sedit ['symbol])~%Invoke fullscreen editor, optionally providing the name of a bound symbol to be edited.") 1149 | (se:init myskin) 1150 | (let* ((lkd nil) 1151 | (lku nil) 1152 | (lastkey nil) 1153 | (k_pr nil) 1154 | (numline 0) 1155 | (kdelay 500) 1156 | (repcnt nil) 1157 | (newkey nil) 1158 | (krepeat nil) 1159 | (pollenc nil) 1160 | (numrot 0)) 1161 | 1162 | (if myform 1163 | (progn 1164 | (setf se:funcname (prin1-to-string myform)) 1165 | (setq se:buffer (cdr (split-string-to-list (string #\Newline) (string (with-output-to-string (str) (pprint (eval myform) str)))))) 1166 | (tft1-set-cursor (* 36 se:cwidth) 0) 1167 | (tft1-set-text-color se:code_col se:cursor_col) 1168 | (if (> (length se:funcname) 13) 1169 | (tft1-write-text (concatenate 'string "SYM: " (subseq se:funcname 0 10) "...")) 1170 | (tft1-write-text (concatenate 'string "SYM: " se:funcname)) 1171 | ) 1172 | ) 1173 | (setq se:buffer (list "")) 1174 | ) 1175 | (se:map-brackets) 1176 | (se:show-text) 1177 | (se:show-cursor) 1178 | (loop 1179 | (when se:help-active 1180 | (setf pollenc (second (se:poll-encoder))) 1181 | (when pollenc 1182 | (if (= numrot 1) 1183 | (progn 1184 | (if (equal pollenc "CW") 1185 | (se:up) 1186 | (se:down) 1187 | ) 1188 | (setf numrot 0) 1189 | ) 1190 | (setf numrot (1+ numrot)) 1191 | ) 1192 | ) 1193 | ) 1194 | (setf lkd (keyboard-get-key t)) 1195 | (when (and lkd (not (equal lkd lastkey))) (setf lastkey lkd) (setf repcnt (millis)) (setf newkey t) (setf krepeat nil)) 1196 | (when lastkey 1197 | (when (or newkey krepeat) 1198 | (case lastkey 1199 | ((1 210) (se:linestart)) 1200 | ((5 213) (se:lineend)) 1201 | ((3 17) (when (se:alert "Exit") (se:cleanup) (setf se:exit t)) (keyboard-flush) (setf lastkey nil)) 1202 | ((24 14 2) (se:flush-buffer) (setf lastkey nil)) 1203 | ((11 12 253) (se:flush-line) (setf lastkey nil)) 1204 | (94 (se:docstart)) 1205 | (211 (se:prevpage)) 1206 | (214 (se:nextpage)) 1207 | (194 (se:toggle-match) (setf lastkey nil)) 1208 | (195 (se:checkbr) (setf lastkey nil)) 1209 | (196 (se:help) (setf lastkey nil)) 1210 | (197 (se:viewsym) (setf lastkey nil)) 1211 | (198 (se:run) (setf lastkey nil)) 1212 | (200 (se:loadview) (setf lastkey nil)) 1213 | (201 (se:quicksave) (setf lastkey nil)) 1214 | (202 (se:remove) (setf lastkey nil)) 1215 | (203 (se:save) (setf lastkey nil)) 1216 | (204 (se:load) (setf lastkey nil)) 1217 | (205 (se:show-dir) (setf lastkey nil)) 1218 | (216 (se:left)) 1219 | (215 (se:right)) 1220 | (218 (se:up)) 1221 | (217 (se:down)) 1222 | (10 (se:enter)) 1223 | (9 (se:tab se:numtabs) (setf lastkey nil)) 1224 | (127 (se:delete)) 1225 | (251 (se:copy) (setf lastkey nil)) 1226 | (252 (se:paste) (setf lastkey nil)) 1227 | ((240 241 242 243 244 245 246 247 248 249 250) (se:snippet lastkey) (setf lastkey nil)) 1228 | (t (se:insert (code-char lastkey))) 1229 | ) 1230 | (setf newkey nil) 1231 | (when krepeat (delay 100)) 1232 | ) 1233 | (setf lku (keyboard-get-key)) 1234 | (when lku (setf lastkey nil) (setf lkd nil) (setf lku nil) (setf krepeat nil)) 1235 | (when (and lastkey (not krepeat)) 1236 | (when (> (millis) (+ repcnt kdelay)) (setf krepeat t) (setf repcnt nil)) 1237 | ) 1238 | ) 1239 | (when se:exit (tft1-fill-screen) (return t)) 1240 | ) 1241 | ) 1242 | (keyboard-flush) 1243 | nil 1244 | ) 1245 | 1246 | 1247 | ; 1248 | ; LispBox editor help screen 1249 | ; 1250 | ; 1251 | (defun se:ref (chr) 1252 | (mapcan 1253 | (lambda (x) 1254 | (let ((entry "")) 1255 | (when x 1256 | (setf entry (search chr (string x))) 1257 | (when entry 1258 | (when (and (< entry 1) (> (length (string x)) 0)) (list x)) 1259 | ) 1260 | ) 1261 | ) 1262 | ) 1263 | (apropos-list chr) 1264 | ) 1265 | ) 1266 | 1267 | 1268 | (defun se:build-ref (chr) 1269 | (let ((reflist nil) 1270 | (ele nil)) 1271 | (setf reflist (sort (mapcar princ-to-string (se:ref chr)) string<)) 1272 | (if reflist 1273 | (progn 1274 | (setf se:ref-array (make-array (length reflist))) 1275 | (dotimes (i (length reflist)) 1276 | (setf ele (pop reflist)) 1277 | (when (> (length ele) 0) (setf (aref se:ref-array i) ele)) 1278 | ) 1279 | ) 1280 | (progn 1281 | (setf se:ref-array (make-array 1)) 1282 | (setf (aref se:ref-array 0) "No entry") 1283 | ) 1284 | ) 1285 | ) 1286 | ) 1287 | 1288 | 1289 | (defun se:build-doc (ctr) 1290 | (when (> ctr (1- (length se:ref-array))) (setf ctr (1- (length se:ref-array)))) 1291 | (when (< ctr 0) (setf ctr 0)) 1292 | (let ((docstring (documentation (read-from-string (aref se:ref-array ctr)))) 1293 | (numlines 0) 1294 | (prlist nil) 1295 | (splitlist nil) 1296 | (linelist nil) 1297 | (text "") 1298 | (line "") 1299 | (headerlines 1)) 1300 | 1301 | (if (< (length docstring) 1) 1302 | (progn 1303 | (setf se:docline-array (make-array '(2 1))) 1304 | (setf (aref se:docline-array 0 0) "No doc") 1305 | (setf (aref se:docline-array 1 0) t) 1306 | ) 1307 | (progn 1308 | (setf prlist (split-string-to-list (string #\Newline) docstring)) 1309 | (if (<= (length (first prlist)) se:maxchar) 1310 | (setf linelist (list (pop prlist))) 1311 | (let ((header (pop prlist))) 1312 | (setf linelist (list (subseq header 0 se:maxchar))) 1313 | (setf header (subseq header se:maxchar (length header))) 1314 | (loop 1315 | (setf headerlines (1+ headerlines)) 1316 | (if (<= (length header) se:maxchar) 1317 | (progn 1318 | (setf linelist (append linelist (list header))) 1319 | (return) 1320 | ) 1321 | (progn 1322 | (setf linelist (append linelist (list (subseq header 0 (1+ se:maxchar))))) 1323 | (setf header (subseq header se:maxchar (length header))) 1324 | ) 1325 | ) 1326 | ) 1327 | ) 1328 | ) 1329 | 1330 | (loop 1331 | (unless prlist (return)) 1332 | (setf text (pop prlist)) 1333 | (setf splitlist (split-string-to-list " " text)) 1334 | (setf text "") 1335 | (setf line (pop splitlist)) 1336 | (loop 1337 | (unless splitlist (return)) 1338 | (setf text (pop splitlist)) 1339 | (if (<= (+ (length line) (length text) 1) se:maxchar) 1340 | (setf line (concatenate 'string line " " text)) 1341 | (progn 1342 | (setf linelist (append linelist (list line))) 1343 | (setf line text) 1344 | ) 1345 | ) 1346 | ) 1347 | (setf linelist (append linelist (list line))) 1348 | ) 1349 | (setf numlines (length linelist)) 1350 | (setf se:docline-array (make-array (list 2 numlines))) 1351 | 1352 | (dotimes (i numlines) 1353 | (setf (aref se:docline-array 0 i) (pop linelist)) 1354 | (if (< i headerlines) 1355 | (setf (aref se:docline-array 1 i) t) 1356 | (setf (aref se:docline-array 1 i) nil) 1357 | ) 1358 | ) 1359 | ) 1360 | ) 1361 | ) 1362 | ) 1363 | 1364 | 1365 | (defun se:print-ref (&optional new cctr) 1366 | (se:hide-tft-cursor) 1367 | (when new (fill-screen) (setf se:rctr 0)) 1368 | (let ((reflength (length se:ref-array)) 1369 | (refstart 0) 1370 | (offset (floor (/ se:maxlines 2))) 1371 | (refstr "") 1372 | (prstr "") 1373 | (ctr se:rctr)) 1374 | 1375 | (when cctr (setf ctr cctr)) 1376 | (setf ctr (constrain ctr 0 (- reflength 1))) 1377 | (setf se:rctr ctr) 1378 | 1379 | (if (and (not new) (or (and (< ctr offset) (> ctr 0)) (> ctr (- reflength offset)))) 1380 | (progn 1381 | (setf refstr (aref se:ref-array ctr)) 1382 | (setf prstr (subseq refstr 0 (min se:maxchar (length refstr)))) 1383 | (setf se:crlin prstr) 1384 | (if (<= ctr offset) 1385 | (setf se:tftcrs ctr) 1386 | (setf se:tftcrs (- (min se:maxlines reflength) (- reflength ctr))) 1387 | ) 1388 | ) 1389 | (progn 1390 | (fill-screen) 1391 | (setf refstart (max (- ctr offset) 0)) 1392 | (setf refstart (max (min (- reflength se:maxlines) refstart) 0)) 1393 | (dotimes (i (min se:maxlines reflength)) 1394 | (setf refstr (aref se:ref-array (+ refstart i))) 1395 | (setf prstr (subseq refstr 0 (min se:maxchar (length refstr)))) 1396 | (if (= (+ refstart i) ctr) 1397 | (progn 1398 | (setf se:crlin prstr) 1399 | (setf se:tftcrs i) 1400 | ) 1401 | (progn 1402 | (set-cursor 0 (* i se:cysize)) 1403 | (with-gfx (strm) 1404 | (princ prstr strm) 1405 | ) 1406 | ) 1407 | ) 1408 | ) 1409 | ) 1410 | ) 1411 | ) 1412 | (se:show-tft-cursor) 1413 | ) 1414 | 1415 | 1416 | (defun se:print-doc (&optional new cctr) 1417 | (fill-screen) 1418 | (set-cursor 0 0) 1419 | (let ((dalength (second (array-dimensions se:docline-array))) 1420 | (prstr "") 1421 | (ctr se:dctr)) 1422 | 1423 | (when cctr (setf ctr cctr)) 1424 | (setf ctr (constrain ctr 0 (min (- dalength se:maxlines) dalength))) 1425 | (setf se:dctr ctr) 1426 | 1427 | (dotimes (i (min se:maxlines dalength)) 1428 | (setf prstr (aref se:docline-array 0 (+ ctr i))) 1429 | (if (aref se:docline-array 1 (+ ctr i)) 1430 | (set-text-color se:hbg_col se:hhelp_col) 1431 | (set-text-color se:hcode_col se:hbg_col) 1432 | ) 1433 | (set-cursor 0 (* i se:cysize)) 1434 | (with-gfx (strm) 1435 | (princ prstr strm) 1436 | ) 1437 | ) 1438 | ) 1439 | ) 1440 | 1441 | (defun se:poll-encoder () 1442 | (let ((sw-event nil) 1443 | (rot-event nil)) 1444 | (unless (eq (digitalread se:SW) se:sw-state) 1445 | (delay 2) 1446 | (setf se:sw-state (digitalread se:SW)) 1447 | (setf sw-event t) 1448 | ) 1449 | 1450 | (unless (eq (digitalread se:CLK) se:clk-state) 1451 | (delay 1) 1452 | (setf se:clk-state (digitalread se:CLK)) 1453 | (if (eq (digitalread se:CLK) (digitalread se:DT)) 1454 | (setf rot-event "CCW") 1455 | (setf rot-event "CW") 1456 | ) 1457 | ) 1458 | (list sw-event rot-event) 1459 | ) 1460 | ) 1461 | 1462 | (defun se:wait-encoder () 1463 | (keyboard-flush) 1464 | (let ((sw-event nil) 1465 | (rot-event 0) 1466 | (lkd nil)) 1467 | (loop 1468 | (when (or (eq sw-event t) (= rot-event 2) lkd) (return)) 1469 | (unless (eq (digitalread se:SW) se:sw-state) 1470 | (delay 2) 1471 | (setf se:sw-state (digitalread se:SW)) 1472 | (setf sw-event t) 1473 | ) 1474 | 1475 | (unless (eq (digitalread se:CLK) se:clk-state) 1476 | (delay 1) 1477 | (setf se:clk-state (digitalread se:CLK)) 1478 | (if (eq (digitalread se:CLK) (digitalread se:DT)) 1479 | (setf se:direction "CCW") 1480 | (setf se:direction "CW") 1481 | ) 1482 | (setf rot-event (1+ rot-event)) 1483 | ) 1484 | 1485 | (setf lkd (keyboard-get-key t)) 1486 | ) 1487 | (list sw-event rot-event lkd) 1488 | ) 1489 | ) 1490 | 1491 | 1492 | (defun se:eval-encoder (cstart cmax rot-fun sw-fun &optional key-fun) 1493 | 1494 | (let ((sw-event nil) 1495 | (rot-event 0) 1496 | (key-event nil) 1497 | (wait-time 0) 1498 | (result nil) 1499 | (ctr cstart)) 1500 | 1501 | (loop 1502 | (setf wait-time (for-millis () (setf result (se:wait-encoder)))) 1503 | (setf sw-event (first result)) 1504 | (setf rot-event (second result)) 1505 | (setf key-event (third result)) 1506 | 1507 | (when key-event 1508 | (when key-fun (key-fun key-event)) 1509 | (keyboard-flush) 1510 | (return key-event) 1511 | ) 1512 | 1513 | (when (and sw-event se:sw-state) 1514 | (sw-fun ctr) 1515 | (return nil) 1516 | ) 1517 | (when (= rot-event 2) 1518 | (when (and (< wait-time 10) (not (equal se:direction se:previous-direction))) 1519 | (setf se:direction se:previous-direction)) 1520 | (if (equal se:direction "CCW") 1521 | (setf ctr (min cmax (1+ ctr))) 1522 | (setf ctr (max 0 (1- ctr))) 1523 | ) 1524 | (rot-fun nil ctr) 1525 | (setf rot-event 0) 1526 | (setf se:previous-direction se:direction) 1527 | ) 1528 | ) 1529 | key-event 1530 | ) 1531 | ) 1532 | 1533 | (defun se:insert-fun (ctr) 1534 | (let ((dalength (second (array-dimensions se:docline-array))) 1535 | (prstr "") 1536 | (ctr 0)) 1537 | (unless (equal (aref se:docline-array 0 0) "No doc") 1538 | (loop 1539 | (setf prstr (aref se:docline-array 0 ctr)) 1540 | (if (aref se:docline-array 1 ctr) 1541 | (progn 1542 | (when (boundp 'se:buffer) 1543 | (dotimes (i (length prstr)) 1544 | (se:insert (char prstr i)) 1545 | ) 1546 | ) 1547 | (setf se:last-cmd (concatenate 'string se:last-cmd prstr)) 1548 | (setf ctr (1+ ctr)) 1549 | ) 1550 | (return) 1551 | ) 1552 | ) 1553 | ) 1554 | ) 1555 | ) 1556 | 1557 | 1558 | (defun se:hide-tft-cursor () 1559 | (when (> (length se:crlin) 0) 1560 | (fill-rect 0 (* se:tftcrs se:cysize) se:xsize se:cysize 0) 1561 | (set-cursor 0 (* se:tftcrs se:cysize)) 1562 | (set-text-color se:hcode_col se:hbg_col) 1563 | (with-gfx (strm) 1564 | (princ se:crlin strm) 1565 | ) 1566 | ) 1567 | ) 1568 | 1569 | 1570 | (defun se:show-tft-cursor () 1571 | (when (> (length se:crlin) 0) 1572 | (set-cursor 0 (* se:tftcrs se:cysize)) 1573 | (set-text-color se:hbg_col se:hhelp_col) 1574 | (with-gfx (strm) 1575 | (princ se:crlin strm) 1576 | ) 1577 | ) 1578 | ) 1579 | 1580 | 1581 | (defun se:help () 1582 | #.(format nil "(se:help)~%Invoke Lispy Little Helper from REPL. Exit with F3 on USB keyboard.") 1583 | (when se:help-active 1584 | 1585 | (set-backlight 255) 1586 | 1587 | (defvar se:hcode_col (rgb 255 255 255)) 1588 | (defvar se:hline_col (rgb 90 90 90)) 1589 | (defvar se:hborder_col (rgb 63 40 0)) 1590 | (defvar se:hbg_col (rgb 0 0 0)) 1591 | (defvar se:hcursor_col (rgb 160 60 0)) 1592 | (defvar se:hemph_col (rgb 0 128 0)) 1593 | (defvar se:halert_col (rgb 255 0 0)) 1594 | (defvar se:hinput_col (rgb 255 255 255)) 1595 | 1596 | (defvar se:hhelp_col (rgb 255 127 0)) 1597 | 1598 | (defvar se:CLK 16) 1599 | (defvar se:DT 14) 1600 | (defvar se:SW 20) 1601 | 1602 | (pinmode se:CLK nil) 1603 | (pinmode se:DT nil) 1604 | (pinmode se:SW nil) 1605 | 1606 | (defvar se:sw-state t) 1607 | (defvar se:clk-state (digitalread se:CLK)) 1608 | (defvar se:direction nil) 1609 | (defvar se:previous-direction nil) 1610 | 1611 | (defvar se:rctr 0) 1612 | (defvar se:dctr 0) 1613 | (defvar se:tftcrs 0) 1614 | (defvar se:crlin "") 1615 | 1616 | (defvar se:ref-array nil) 1617 | (defvar se:docline-array nil) 1618 | (defvar se:last-cmd "") 1619 | (defvar se:xsize 160) 1620 | (defvar se:ysize 128) 1621 | (defvar se:cxsize 6) 1622 | (defvar se:cysize 8) 1623 | (defvar se:maxlines (floor (/ se:ysize se:cysize))) 1624 | (defvar se:maxchar (floor (/ se:xsize se:cxsize))) 1625 | 1626 | (let ((result nil) 1627 | (esc nil) 1628 | (dalength 0)) 1629 | 1630 | (fill-screen) 1631 | (set-cursor 0 0) 1632 | (set-text-color se:hcode_col se:hbg_col) 1633 | (with-gfx (strm) 1634 | (princ (concatenate 'string "Press key or encoder!" (string #\Newline) "F3 to exit.") strm) 1635 | ) 1636 | (setf result (se:wait-encoder)) 1637 | 1638 | (if (third result) 1639 | (progn 1640 | (if (and (> (third result) 32) (< (third result) 127)) 1641 | (se:build-ref (string (code-char (third result)))) 1642 | (se:build-ref "") 1643 | ) 1644 | (if (= (third result) 196) 1645 | (progn 1646 | (fill-screen) 1647 | (set-cursor 0 0) 1648 | (setf esc t) 1649 | ) 1650 | ) 1651 | ) 1652 | (se:build-ref "") 1653 | ) 1654 | (unless esc 1655 | (defvar se:sw-state t) 1656 | (se:print-ref t) 1657 | (loop 1658 | (setf result (se:eval-encoder se:rctr (1- (length se:ref-array)) se:print-ref se:build-doc)) 1659 | (when result 1660 | (when (= result 196) 1661 | (return) 1662 | ) 1663 | (if (and (> result 32) (< result 127)) 1664 | (se:build-ref (string (code-char result))) 1665 | (se:build-ref "") 1666 | ) 1667 | (setf se:dctr 0) 1668 | (se:print-ref t) 1669 | ) 1670 | (unless result 1671 | (fill-screen) 1672 | (se:print-doc) 1673 | (setf dalength (second (array-dimensions se:docline-array))) 1674 | (setf result (se:eval-encoder se:dctr (constrain dalength 0 (min (- dalength se:maxlines) dalength)) se:print-doc se:insert-fun)) 1675 | (when result 1676 | (when (= result 196) 1677 | (return) 1678 | ) 1679 | (if (and (> result 32) (< result 127)) 1680 | (se:build-ref (string (code-char result))) 1681 | (se:build-ref "") 1682 | ) 1683 | (setf se:rctr 0) 1684 | ) 1685 | (se:print-ref t se:rctr) 1686 | ) 1687 | ) 1688 | (fill-screen) 1689 | ) 1690 | (makunbound 'se:ref-array) 1691 | (makunbound 'se:docline-array) 1692 | 1693 | (set-backlight 0) 1694 | ) 1695 | ) 1696 | 1697 | (if se:help-active 1698 | se:last-cmd 1699 | "Deactivated. To activate LLH set se:help-active to t." 1700 | ) 1701 | ) 1702 | 1703 | 1704 | ; 1705 | ; Helper functions 1706 | ; 1707 | ; 1708 | (defun constrain (value mini maxi) 1709 | #.(format nil "(constrain value mini maxi)~%Constrain a value to interval between mini and maxi (including both).") 1710 | (max (min value maxi) mini) 1711 | ) 1712 | 1713 | ; Fn adopted from M5Cardputer editor version by hasn0life 1714 | ; recursion eliminated, requires search-str from extensions 1715 | (defun split-string-to-list (delim str) 1716 | #.(format nil "(split-string-to-list delimiter str)~%Split string str into list, cutting it at delimiter.") 1717 | (unless (or (eq str nil) (not (stringp str))) 1718 | (let* ((start 0) 1719 | (end (search-str delim str)) 1720 | (lst nil)) 1721 | (loop 1722 | (if (eq end nil) 1723 | (return (append lst (list (subseq str start)))) 1724 | (setq lst (append lst (list (subseq str start end))))) 1725 | (setq start (1+ end)) 1726 | (setq end (search-str delim str start)) 1727 | ) 1728 | ) 1729 | ) 1730 | ) 1731 | 1732 | (defun char-list-to-string (clist) 1733 | #.(format nil "(char-list-to-string clist)~%Build string from a list of characters.") 1734 | (let ((str "")) 1735 | (dolist (c clist) (setq str (concatenate 'string str c))) 1736 | str 1737 | ) 1738 | ) 1739 | 1740 | (defun to-hex-char (i) 1741 | #.(format nil "(to-hex-char i)~%Convert number i (<= 15) to hex char.") 1742 | (unless (equal i nil) 1743 | (let ((i (abs i))) 1744 | (code-char (+ i (if (<= i 9) 48 55)) ) 1745 | ) 1746 | ) 1747 | ) 1748 | 1749 | (defun byte-to-hexstr (i) 1750 | #.(format nil "(byte-to-hexstr i)~%Convert number i (<= 255) to hex string.") 1751 | (unless (equal i nil) 1752 | (let ((i (abs i))) 1753 | (concatenate 'string (string (to-hex-char (ash i -4))) (string (to-hex-char (logand i 15))) ) 1754 | ) 1755 | ) 1756 | ) 1757 | 1758 | (defun word-to-hexstr (i) 1759 | #.(format nil "(word-to-hexstr i)~%Convert number i (<= 65535) to hex string.") 1760 | (unless (equal i nil) 1761 | (let ((i (abs i))) 1762 | (concatenate 'string (byte-to-hexstr (ash i -8)) (byte-to-hexstr (logand i 255))) 1763 | ) 1764 | ) 1765 | ) 1766 | 1767 | (defun hexstr-to-int (s) 1768 | #.(format nil "(hexstr-to-int str)~%Convert hex string to int.") 1769 | (read-from-string (concatenate 'string "#x" s)) 1770 | ) 1771 | 1772 | (defun remove-if (fn lis) 1773 | #.(format nil "(remove-if fn lis)~%Remove list items when processing them with function fn evals to t.") 1774 | (mapcan #'(lambda (item) (unless (funcall fn item) (list item))) lis) 1775 | ) 1776 | 1777 | (defun remove-if-not (fn lis) 1778 | #.(format nil "(remove-if-not fn lis)~%Remove list items when processing them with function fn evals to nil.") 1779 | (mapcan #'(lambda (item) (when (funcall fn item) (list item))) lis) 1780 | ) 1781 | 1782 | (defun remove-item (ele lis) 1783 | #.(format nil "(remove-item ele lis)~%Remove item ele from list.") 1784 | (remove-if (lambda (item) (equal ele item)) lis) 1785 | ) 1786 | 1787 | (defun remove (place lis) 1788 | #.(format nil "(remove n lis)~%Remove nth item from list.") 1789 | (let ((newlis ())) 1790 | (dotimes (i place) 1791 | (push (pop lis) newlis) 1792 | ) 1793 | (pop lis) 1794 | (dotimes (i (length lis)) 1795 | (push (pop lis) newlis) 1796 | ) 1797 | (reverse newlis) 1798 | ) 1799 | ) 1800 | 1801 | (defun assoc* (a alist test) 1802 | #.(format nil "(assoc* key list testfn)~%Looks up a key in an association list of (key . value) pairs, and returns *all* matching pairs as a list, or nil if no pair is found.") 1803 | (cond 1804 | ((null alist) nil) 1805 | ((funcall test a (caar alist)) (car alist)) 1806 | (t (assoc* a (cdr alist) test)) 1807 | ) 1808 | ) 1809 | 1810 | (defun reverse-assoc* (a alist test) 1811 | #.(format nil "(assoc* val list testfn)~%Looks up a value in an association list of (key . value) pairs, and returns *all* matching pairs as a list, or nil if no pair is found.") 1812 | (cond 1813 | ((null alist) nil) 1814 | ((funcall test a (cdar alist)) (caar alist)) 1815 | (t (reverse-assoc* a (cdr alist) test)) 1816 | ) 1817 | ) 1818 | 1819 | (defun get-obj (aname anum) 1820 | #.(format nil "(get-obj aname index)~%Retrieve numbered object by providing the root name and a number.") 1821 | (read-from-string (eval (concatenate 'string aname (string anum)))) 1822 | ) 1823 | 1824 | 1825 | 1826 | ; 1827 | ; ErsatzMoco framework functions 1828 | ; using extended ULOS 1829 | ; 1830 | ; 1831 | ; 1832 | ; class moco-message 1833 | ; 1834 | (defvar moco-message 1835 | (class nil '( 1836 | command 0 1837 | id "0000" 1838 | require_ack nil 1839 | data "" 1840 | 1841 | timeout 10000 1842 | resend_ctr 0 1843 | error_code 0 1844 | 1845 | _build-from-string #'(lambda (self data) 1846 | (let ((parts (split-string-to-list ":" data))) 1847 | (cond 1848 | ((> (length data) 36) (stv self 'error_code 93)) 1849 | ((/= (length parts) 6) (stv self 'error_code 93)) 1850 | ((> (length (nth 4 parts)) 18) (stv self 'error_code 94)) 1851 | ((not (equal (nth 0 parts) "@EM")) (stv self 'error_code 98)) 1852 | ((not (equal (nth 5 parts) "ME@")) (stv self 'error_code 99)) 1853 | ((or (> (length (nth 1 parts)) 2) (< (length (nth 1 parts)) 1)) (stv self 'error_code 96)) 1854 | ((or (> (length (nth 2 parts)) 4) (< (length (nth 2 parts)) 1)) (stv self 'error_code 97)) 1855 | ((or (> (length (nth 3 parts)) 1) (< (length (nth 3 parts)) 1) (> (read-from-string (nth 3 parts)) 1) (< (read-from-string (nth 3 parts)) 0)) (stv self 'error_code 95)) 1856 | ) 1857 | (unless (/= (gtv self 'error_code) 0) 1858 | (stv self 'command (read-from-string (nth 1 parts))) 1859 | (stv self 'id (nth 2 parts)) 1860 | (if (= (read-from-string(nth 3 parts)) 1) (stv self 'require_ack t) (stv self 'require_ack nil)) 1861 | (stv self 'data (nth 4 parts)) 1862 | t 1863 | ) 1864 | ) 1865 | ) 1866 | 1867 | _build-from-scratch #'(lambda (self cmd ack mydata rc tmo) 1868 | (stv self 'id (word-to-hexstr (logand (abs (millis)) #xFFFF))) 1869 | (stv self 'timeout tmo) 1870 | (stv self 'resend_ctr rc) 1871 | (stv self 'command cmd) 1872 | (stv self 'require_ack (if ack t nil)) 1873 | (stv self 'data (string mydata)) 1874 | (when (cmt self '_msg-valid) t) 1875 | ) 1876 | 1877 | _build-acknowledge #'(lambda (self myid) 1878 | (when (symbolp myid) (setq myid (eval myid))) 1879 | (stv self 'timeout 10000) 1880 | (stv self 'resend_ctr 0) 1881 | (stv self 'command (gtv moco-command myid)) 1882 | (stv self 'require_ack nil) 1883 | (stv self 'id myid) 1884 | (stv self 'data "0") 1885 | ) 1886 | 1887 | _msg-valid #'(lambda (self) 1888 | (stv self 'error_code 0) 1889 | (cond 1890 | ((> (length (gtv self 'data)) 18) (stv self 'error_code 94)) 1891 | ((or (> (gtv self 'command) 99) (< (gtv self 'command) 0)) (stv self 'error_code 96)) 1892 | ((numberp (gtv self 'require_ack)) (stv self 'error_code 95)) 1893 | ) 1894 | (let ((ec (gtv self 'error_code))) 1895 | (if (/= ec 0) nil t) 1896 | ) 1897 | ) 1898 | 1899 | _to-string #'(lambda (self) 1900 | (concatenate 'string 1901 | "@EM:" (string (gtv self 'command)) ":" 1902 | (gtv self 'id) ":" 1903 | (if (gtv self 'require_ack) "1" "0") ":" 1904 | (string (gtv self 'data)) ":ME@" 1905 | ) 1906 | ) 1907 | 1908 | _decrease-resend-ctr #'(lambda (self) 1909 | (unless (< (gtv self 'resend_ctr) 1) 1910 | (stv self 'resend_ctr (1- (gtv self 'resend_ctr))) 1911 | ) 1912 | ) 1913 | ) 1914 | ) 1915 | ) 1916 | 1917 | 1918 | ; 1919 | ; class com-module 1920 | ; 1921 | ; 1922 | ; 1923 | ; Com module types 1924 | ; 1925 | ; UNDEFINED = 0 1926 | ; RFM69 = 1 1927 | ; XBEE = 2 1928 | ; SERCOM = 3 1929 | ; 1930 | (defvar com-module 1931 | (class nil '( 1932 | 1933 | recbuffer_size 10 1934 | ackbuffer_size 10 1935 | ack_timeout 200 1936 | 1937 | receive_buffer () 1938 | expect_ack_buffer () 1939 | type 0 1940 | 1941 | last_sent "" 1942 | last_received () 1943 | 1944 | alert_callback nil 1945 | 1946 | last_ack_check 0 1947 | last_expect_check 0 1948 | 1949 | _flush-expect-ack-buffer #'(lambda (self) 1950 | (stv self 'expect_ack_buffer () ) 1951 | ) 1952 | 1953 | _flush-receive-buffer #'(lambda (self) 1954 | (stv self 'receive_buffer () ) 1955 | ) 1956 | 1957 | _send-mmobject #'(lambda (self mmo) 1958 | (cmt self '_send (cmt mmo '_to-string)) 1959 | ) 1960 | 1961 | _build-and-send #'(lambda (self cmd ack data rc tmo) 1962 | (let ((mm (class 'moco-message nil t))) 1963 | (cmt mm '_build_from_scratch cmd ack data rc tmo) 1964 | (when (and ack (< (length (gtv self 'expect_ack_buffer)) (gtv com-module '_ackbuffer_size))) 1965 | (stv self 'expect_ack_buffer (append (gtv self 'expect_ack_buffer) (list mm))) 1966 | ) 1967 | (cmt self '_send (cmt mm '_to-string)) 1968 | ) 1969 | ) 1970 | 1971 | _resend #'(lambda (self mmo) 1972 | (cmt self '_send (cmt mmo '_to-string)) 1973 | (cmt mmo '_decrease-resend-ctr) 1974 | ) 1975 | 1976 | _handle-alert #'(lambda (self amm) 1977 | (if (gtv self 'alert_callback) 1978 | (cmt self 'alert_callback amm) 1979 | ) 1980 | ) 1981 | 1982 | _receive #'(lambda (self child) 1983 | (let ((mm (class 'moco-message nil t))) 1984 | (cmt mm '_build-from-string (char-list-to-string (gtv child 'last_received))) 1985 | 1986 | (cond 1987 | ((> (gtv mm 'error_code) 0) nil) 1988 | ((= (gtv mm 'command) 0) 1989 | (when (> (length (gtv child 'expect_ack_buffer)) 0) 1990 | (let* ((eab (gtv child 'expect_ack_buffer))) 1991 | (stv child 'expect_ack_buffer 1992 | (mapcan (lambda (am) (unless (equal (gtv am 'id) (gtv mm 'id)) 1993 | (list am))) 1994 | eab) 1995 | ) 1996 | ) 1997 | ) 1998 | nil 1999 | ) 2000 | ((> (length (gtv child 'receive_buffer)) 0) 2001 | (if (not 2002 | (dolist (known (gtv child 'receive_buffer)) 2003 | (when (equal (gtv known 'id) (gtv mm 'id)) 2004 | (return t) 2005 | ) 2006 | ) 2007 | ) 2008 | (progn 2009 | (when (>= (length(gtv child 'receive_buffer)) (gtv child '_recbuffer_size)) 2010 | (pop (gtv child 'receive_buffer)) 2011 | ) 2012 | (when (gtv mm 'ack_required) 2013 | (stv mm 'resend_ctr 3) 2014 | (stv mm 'timeout (gtv child '_ack_timeout)) 2015 | ) 2016 | (append (gtv child 'receive_buffer) (list mm)) 2017 | t 2018 | ) 2019 | nil 2020 | ) 2021 | ) 2022 | ) 2023 | ) 2024 | 2025 | ) 2026 | 2027 | _update #'(lambda (self) 2028 | (defvar curmil (millis)) 2029 | 2030 | (let ((eab (gtv self 'expect_ack_buffer))) 2031 | (when (> (length eab) 0) 2032 | (stv self 'expect_ack_buffer 2033 | (mapcan (lambda (mm) (when (> (gtv mm 'resend_ctr) 0) (progn 2034 | (print (concatenate "ACK never received " (string (gtv mm 'id)))) 2035 | (list mm)))) 2036 | eab) 2037 | ) 2038 | ) 2039 | ) 2040 | (let ((eab (gtv self 'expect_ack_buffer))) 2041 | (when (> (length eab) 0) 2042 | (dolist (mm eab) 2043 | (if (> curmil (+ (gtv mm 'timeout) (gtv self 'last_expect_check))) 2044 | (progn 2045 | (print (concatenate "Resend! " (gtv mm 'data))) 2046 | (cmt self '_resend mm) 2047 | ) 2048 | (progn 2049 | (print "Alert!") 2050 | (cmt self '_handle-alert mm) 2051 | ) 2052 | ) 2053 | (stv self 'last_expect_check curmil) 2054 | ) 2055 | ) 2056 | ) 2057 | (let ((rb (gtv self 'receive_buffer))) 2058 | (when (> (length rb) 0) 2059 | (dolist (mm rb) 2060 | (when (and (gtv mm 'require_ack) (> curmil (+ (gtv mm 'timeout) (gtv self 'last_ack_check)))) 2061 | (when (< (gtv mm 'resend_ctr) 0) 2062 | (let ((ackmm (class 'moco-message nil t))) 2063 | (cmt ackmm '_build-acknowledge (gtv mm 'id)) 2064 | (cmt self '_send-mmobject ackmm) 2065 | (cmt mm '_decrease-resend-ctr) 2066 | ) 2067 | ) 2068 | (stv self 'last_ack_check curmil) 2069 | ) 2070 | ) 2071 | ) 2072 | ) 2073 | (let ((rb (gtv self 'receive_buffer))) 2074 | (if (> (length rb) 0) 2075 | (stv self 'receive_buffer 2076 | (mapcan (lambda (mm) (when (and (gtv mm 'ack_required) (< (gtv mm 'resend_ctr) 1)) 2077 | (list mm))) 2078 | rb) 2079 | ) 2080 | ) 2081 | ) 2082 | ) 2083 | 2084 | ) 2085 | ) 2086 | ) 2087 | 2088 | 2089 | 2090 | (defvar sercom-module 2091 | (class 'com-module '( 2092 | 2093 | baud 9600 2094 | port 0 2095 | reading_message nil 2096 | message_complete nil 2097 | char_counter 0 2098 | intro_counter 0 2099 | outro_counter 0 2100 | 2101 | intro "@EM:" 2102 | outro ":ME@" 2103 | 2104 | alert_callback nil 2105 | last_sent () 2106 | last_received () 2107 | last_ack_check (millis) 2108 | last_expect_check (millis) 2109 | 2110 | 2111 | _init #'(lambda (self bd pt cb) 2112 | (stv self 'type 3) 2113 | (stv self 'baud bd) 2114 | (stv self 'port pt) 2115 | (stv self 'alert_callback cb) 2116 | ) 2117 | 2118 | _send #'(lambda (self packetstr) 2119 | (with-serial (strm (gtv self 'port) (gtv self 'baud)) 2120 | (write-string packetstr strm) 2121 | ) 2122 | ) 2123 | 2124 | _receive #'(lambda (self) 2125 | (with-serial (strm (gtv self 'port) (gtv self 'baud)) 2126 | (let* ((nbyte (read-byte strm)) 2127 | (nextbyte (if (nbyte) (string (code-char nbyte)) nil))) 2128 | (when (nextbyte) 2129 | (if (not (gtv self 'reading_message)) 2130 | (let* ((ic (gtv self 'intro_counter))) 2131 | (if (equal nextbyte (string (char (gtv self 'intro) ic))) 2132 | (stv self 'intro_counter (1+ ic)) 2133 | (stv self 'intro_counter 0) 2134 | ) 2135 | (when (= ic 4) 2136 | (stv self 'reading_message t) 2137 | (stv self 'intro_counter 0) 2138 | (stv self 'char_counter 0) 2139 | (stv self 'last_received (gtv self 'intro)) 2140 | ) 2141 | ) 2142 | (if (< (gtv self 'char_counter) 39) 2143 | (let* ((oc (gtv self 'outro_counter)) (cc (gtv self 'char_counter))) 2144 | (stv self 'last_received (push nextbyte (gtv self 'last_received))) 2145 | (if (equal nextbyte (string (char (gtv self 'outro) oc))) 2146 | (stv self 'outro_counter (1+ oc)) 2147 | (stv self 'outro_counter 0) 2148 | ) 2149 | (when (= oc 4) 2150 | (stv self 'reading_message nil) 2151 | (stv self 'message_complete t) 2152 | (stv self 'outro_counter 0) 2153 | (stv self 'char_counter 0) 2154 | ) 2155 | (stv self 'char_counter (1+ cc)) 2156 | ) 2157 | (progn 2158 | (stv self 'reading_message nil) 2159 | (stv self 'message_complete nil) 2160 | (stv self 'outro_counter 0) 2161 | (stv self 'char_counter 0) 2162 | ) 2163 | ) 2164 | ) 2165 | ) 2166 | (if (or (not nextbyte) (not (gtv self 'message_complete))) 2167 | nil 2168 | 2169 | (progn 2170 | (stv self 'message_complete nil) 2171 | (cmt (gtv self 'parent) '_receive self) 2172 | ) 2173 | ) 2174 | ) 2175 | ) 2176 | ) 2177 | ) 2178 | t 2179 | ) 2180 | ) 2181 | 2182 | 2183 | (defvar rfm69-module 2184 | (class 'com-module '( 2185 | 2186 | node_id 1 2187 | net_id 1 2188 | 2189 | alert_callback nil 2190 | last_sent () 2191 | last_received () 2192 | last_ack_check (millis) 2193 | last_expect_check (millis) 2194 | 2195 | 2196 | _init #'(lambda (self noid neid cb) 2197 | (stv self 'type 1) 2198 | (stv self 'node_id noid) 2199 | (stv self 'net_id neid) 2200 | (stv self 'alert_callback cb) 2201 | (rfm69-begin noid neid) 2202 | ) 2203 | 2204 | _send #'(lambda (self rec packetstr ack) 2205 | (rfm69-send rec packetstr ack) 2206 | ) 2207 | 2208 | _receive #'(lambda (self) 2209 | (let* ((rec (rfm69-receive))) 2210 | (if (not rec) 2211 | nil 2212 | (progn 2213 | (stv self 'last_received rec) 2214 | (cmt (gtv self 'parent) '_receive self) 2215 | ) 2216 | ) 2217 | ) 2218 | ) 2219 | 2220 | _get-rssi #'(lambda (self) 2221 | (rfm69-get-rssi) 2222 | ) 2223 | ) 2224 | t 2225 | ) 2226 | ) 2227 | 2228 | 2229 | (defvar shape-size 2230 | (class nil '( 2231 | width 0 2232 | height 0 2233 | 2234 | _has-size #'(lambda (self) 2235 | (if (and (> (gtv self 'width) 0) (> (gtv self 'height) 0)) 2236 | t 2237 | nil 2238 | ) 2239 | ) 2240 | 2241 | _size-one #'(lambda (self) 2242 | (stv self 'width 1) 2243 | (stv self 'height 1) 2244 | ) 2245 | 2246 | _set-size #'(lambda (self w h) 2247 | (stv self 'width w) 2248 | (stv self 'height h) 2249 | ) 2250 | ) 2251 | ) 2252 | ) 2253 | 2254 | 2255 | (defvar pos 2256 | (class nil '( 2257 | x 0 2258 | y 0 2259 | ) 2260 | ) 2261 | ) 2262 | 2263 | 2264 | ; 2265 | ; class color 2266 | ; 2267 | (defvar color 2268 | (class nil '( 2269 | red 0 2270 | green 0 2271 | blue 0 2272 | 2273 | _copy-color #'(lambda (self acol) 2274 | (stv self 'red (gtv acol 'r)) 2275 | (stv self 'green (gtv acol 'g)) 2276 | (stv self 'blue (gtv acol 'b)) 2277 | ) 2278 | 2279 | _set-rgb #'(lambda (self r g b) 2280 | (stv self 'red r) 2281 | (stv self 'green g) 2282 | (stv self 'blue b) 2283 | ) 2284 | 2285 | _set-rgb-list #'(lambda (self rgb) 2286 | (stv self 'red (first rgb)) 2287 | (stv self 'green (second rgb)) 2288 | (stv self 'blue (third rgb)) 2289 | ) 2290 | 2291 | _darken-by #'(lambda (self darken) 2292 | (let* ((darken (max 0 darken)) (r 0) (g 0) (b 0)) 2293 | (setq r (max 0 (- (gtv self 'red) darken))) 2294 | (setq g (max 0 (- (gtv self 'green) darken))) 2295 | (setq b (max 0 (- (gtv self 'blue) darken))) 2296 | 2297 | (list r g b) 2298 | ) 2299 | ) 2300 | 2301 | _brighten-by #'(lambda (self brighten) 2302 | (let* ((brighten (max 0 brighten)) (r 0) (g 0) (b 0)) 2303 | (setq r (min 255 (+ (gtv self 'red) brighten))) 2304 | (setq g (min 255 (+ (gtv self 'green) brighten))) 2305 | (setq b (min 255 (+ (gtv self 'blue) brighten))) 2306 | 2307 | (list r g b) 2308 | ) 2309 | ) 2310 | 2311 | _to-grayscale #'(lambda (self) 2312 | (min 255 (max 0 (floor (+ (* 0.21 (gtv self 'red)) (* 0.72 (gtv self 'green)) (* 0.07 (gtv self 'blue)))))) 2313 | ) 2314 | 2315 | _to-bw #'(lambda (self &optional (trs 128)) 2316 | (if (> (cmt self '_to-grayscale) trs) 2317 | 1 2318 | 0 2319 | ) 2320 | ) 2321 | 2322 | _to-hex-color #'(lambda (self) 2323 | (logior (ash (gtv self 'red) 16) (ash (gtv self 'green) 8) (gtv self 'red)) 2324 | ) 2325 | 2326 | _to-hex-string #'(lambda (self) 2327 | (concatenate 'string (byte-to-hexstr (gtv self 'red)) (byte-to-hexstr (gtv self 'green)) (byte-to-hexstr (gtv self 'blue))) 2328 | ) 2329 | 2330 | _to-16bit #'(lambda (self) 2331 | (let* ((r (gtv self 'red)) (g (gtv self 'green)) (b (gtv self 'blue))) 2332 | (logior (ash (logand r #xf8) 8) (ash (logand g #xfc) 3) (ash b -3)) 2333 | ) 2334 | ) 2335 | ) 2336 | ) 2337 | ) 2338 | 2339 | 2340 | ; 2341 | ; class display 2342 | ; 2343 | (defvar display 2344 | (class nil '( 2345 | 2346 | type 0 2347 | mono nil 2348 | 2349 | grid_space nil 2350 | grid_min_x 0 2351 | grid_max_x 0 2352 | grid_min_y 0 2353 | grid_max_y 0 2354 | 2355 | pix_max_x 0 2356 | pix_max_y 0 2357 | 2358 | buffer () 2359 | 2360 | _init #'(lambda (self) 2361 | (stv self 'grid_space (class 'shape-size nil t)) 2362 | ) 2363 | 2364 | _grid-to-pix #'(lambda (self gridpos) 2365 | (stv gridpos 'x (constrain (gtv gridpos 'x) (gtv self 'grid_min_x) (gtv self 'grid_max_x))) 2366 | (stv gridpos 'y (constrain (gtv gridpos 'y) (gtv self 'grid_min_y) (gtv self 'grid_max_y))) 2367 | 2368 | (let* ((px 0) (py 0)) 2369 | (setq px (+ (* (gtv self 'grid_min_x) (gtv (gtv self 'grid_space) 'width)) (* (gtv gridpos 'x) (gtv (gtv self 'grid_space) 'width)))) 2370 | (setq py (+ (* (gtv self 'grid_min_y) (gtv (gtv self 'grid_space) 'height)) (* (gtv gridpos 'y) (gtv (gtv self 'grid_space) 'height)))) 2371 | (class 'pos (list 'x px 'y py)) 2372 | ) 2373 | ) 2374 | 2375 | _get-grid-topleft #'(lambda (self) 2376 | (class 'pos (list 'x (gtv self 'grid_min_x) 'y (gtv self 'grid_min_y))) 2377 | ) 2378 | 2379 | _get-grid-bottomright #'(lambda (self) 2380 | (class 'pos (list 'x (gtv self 'grid_max_x) 'y (gtv self 'grid_max_y))) 2381 | ) 2382 | 2383 | _get-pix-bottomright #'(lambda (self) 2384 | (class 'pos (list 'x (gtv self 'pix_max_x) 'y (gtv self 'pix_max_y))) 2385 | ) 2386 | 2387 | _set-grid-space #'(lambda (self gs) 2388 | (let* ((grsp (gtv self 'grid_space))) 2389 | (stv grsp 'width (min (gtv gs 'width) (gtv self 'pix_max_x))) 2390 | (stv grsp 'height (min (gtv gs 'height) (gtv self 'pix_max_y))) 2391 | 2392 | (stv self 'grid_max_x (floor (/ (gtv self 'pix_max_x) (gtv grsp 'width)))) 2393 | (stv self 'grid_max_y (floor (/ (gtv self 'pix_max_y) (gtv grsp 'height)))) 2394 | ) 2395 | ) 2396 | 2397 | _set-grid-min-x #'(lambda (self gmix) 2398 | (stv self 'grid_min_x (max 0 gmix)) 2399 | ) 2400 | 2401 | _set-grid-min-y #'(lambda (self gmiy) 2402 | (stv self 'grid_min_y (max 0 gmiy)) 2403 | ) 2404 | 2405 | _set-grid-max-x #'(lambda (self gmax) 2406 | (let* ((grsp (gtv self 'grid_space))) 2407 | (stv self 'grid_max_x (min gmax (floor (/ (gtv self 'pix_max_x) (gtv grsp 'width))))) 2408 | ) 2409 | ) 2410 | 2411 | _set-grid-max-y #'(lambda (self gmay) 2412 | (let* ((grsp (gtv self 'grid_space))) 2413 | (stv self 'grid_max_y (min gmay (floor (/ (gtv self 'pix_max_y) (gtv grsp 'height))))) 2414 | ) 2415 | ) 2416 | 2417 | _set-grid-min #'(lambda (self gmin) 2418 | (cmt self '_set-grid-min-x (gtv gmin 'x)) 2419 | (cmt self '_set-grid-min-y (gtv gmin 'y)) 2420 | ) 2421 | 2422 | _set-grid-max #'(lambda (self gmax) 2423 | (cmt self '_set-grid-max-x (gtv gmax 'x)) 2424 | (cmt self '_set-grid-max-y (gtv gmax 'y)) 2425 | ) 2426 | 2427 | _set-grid-borders #'(lambda (self tleft bright) 2428 | (cmt self '_set-grid-min tleft) 2429 | (cmt self '_set-grid-max bright) 2430 | ) 2431 | 2432 | _add-element #'(lambda (self de) 2433 | (stv self 'buffer (cons de (reverse (gtv self 'buffer)))) 2434 | ) 2435 | 2436 | _remove-element #'(lambda (self de) 2437 | (stv self 'buffer 2438 | (mapcan (lambda (me) (unless (equal me de) 2439 | (list me))) 2440 | (gtv self 'buffer)) 2441 | ) 2442 | ) 2443 | 2444 | _get-element-by-num #'(lambda (self num) 2445 | (let* ((bf (gtv self 'buffer))) 2446 | (when (< num (length bf)) 2447 | (nth num bf) 2448 | ) 2449 | ) 2450 | ) 2451 | ) 2452 | ) 2453 | ) 2454 | 2455 | ; 2456 | ; Display element types 2457 | ; 2458 | ; UNDEFINED = 0 2459 | ; LABEL = 1 2460 | ; BUTTON = 2 2461 | ; IMAGE = 3 2462 | ; IMAGEBUTTON = 4 2463 | ; 2464 | (defvar display-element 2465 | (class nil '( 2466 | 2467 | type 0 2468 | name "" 2469 | 2470 | pixel_pos nil 2471 | grid_pos nil 2472 | pixel_size nil 2473 | grid_size nil 2474 | 2475 | fg_color nil 2476 | bg_color nil 2477 | border_color nil 2478 | 2479 | grid t 2480 | redraw t 2481 | 2482 | current_display nil 2483 | 2484 | _init #'(lambda (self) 2485 | (stv self 'pixel_pos (class 'pos nil t)) 2486 | (stv self 'pixel_size (class 'shape-size nil t)) 2487 | 2488 | (stv self 'grid_pos (class 'pos nil t)) 2489 | (stv self 'grid_size (class 'shape-size nil t)) 2490 | 2491 | (stv self 'fg_color (class 'color nil t)) 2492 | (stv self 'bg_color (class 'color nil t)) 2493 | (stv self 'border_color (class 'color nil t)) 2494 | 2495 | (cmt (gtv self 'pixel_size) '_size-one) 2496 | (cmt (gtv self 'grid_size) '_size-one) 2497 | ) 2498 | 2499 | _set-pixel-coords #'(lambda (self myx myy) 2500 | (let* ((cd (gtv self 'current_display)) (pp (gtv self 'pixel_pos))) 2501 | (unless (null cd) 2502 | (stv pp 'x (constrain myx 0 (gtv cd 'pix_max_x))) 2503 | (stv pp 'y (constrain myy 0 (gtv cd 'pix_max_y))) 2504 | 2505 | (stv self 'grid nil) 2506 | (stv self 'redraw t) 2507 | t 2508 | ) 2509 | ) 2510 | ) 2511 | 2512 | _set-pixel-pos #'(lambda (self mypos) 2513 | (cmt self '_set-pixel-coords (gtv mypos 'x) (gtv mypos 'y)) 2514 | ) 2515 | 2516 | _get-pixel-pos #'(lambda (self) 2517 | (gtv self 'pixel_pos) 2518 | ) 2519 | 2520 | _set-grid-coords #'(lambda (self myx myy) 2521 | (let* ((cd (gtv self 'current_display)) (gp (gtv self 'grid_pos))) 2522 | (unless (null cd) 2523 | (stv gp 'x (constrain myx (gtv cd 'grid_min_x) (gtv cd 'grid_max_x))) 2524 | (stv gp 'y (constrain myy (gtv cd 'grid_min_y) (gtv cd 'grid_max_y))) 2525 | 2526 | (stv self 'grid t) 2527 | (cmt self '_calculate-pixel-pos) 2528 | (stv self 'redraw t) 2529 | t 2530 | ) 2531 | ) 2532 | ) 2533 | 2534 | _set-grid-pos #'(lambda (self mypos) 2535 | (cmt self '_set-grid-coords (gtv mypos 'x) (gtv mypos 'y)) 2536 | ) 2537 | 2538 | _get-grid-pos #'(lambda (self) 2539 | (gtv self 'grid_pos) 2540 | ) 2541 | 2542 | _set-size #'(lambda (self width height) 2543 | (stv self 'grid nil) 2544 | (cmt (gtv self 'pixel_size) '_set-size width height) 2545 | (stv self 'redraw t) 2546 | ) 2547 | 2548 | _set-grid-size #'(lambda (self width height) 2549 | (let* ((cd (gtv self 'current_display)) (gs (gtv self 'grid_size))) 2550 | (unless (or (null cd) (< width 1) (< height 1)) 2551 | (stv gs 'width (min width (+ (- (gtv cd 'grid_max_x) (gtv cd 'grid_min_x)) 1))) 2552 | (stv gs 'height (min height (+ (- (gtv cd 'grid_max_y) (gtv cd 'grid_min_y)) 1))) 2553 | 2554 | (cmt self '_calculate-pixel-size) 2555 | (stv self 'redraw t) 2556 | t 2557 | ) 2558 | ) 2559 | ) 2560 | 2561 | _set-grid-shape #'(lambda (self mysize) 2562 | (cmt self '_set-grid-size (gtv mysize 'width) (gtv mysize 'height)) 2563 | ) 2564 | 2565 | _calculate-pixel-pos #'(lambda (self) 2566 | (let* ((cd (gtv self 'current_display))) 2567 | (unless (null cd) 2568 | (stv self 'pixel_pos (cmt cd '_grid-to-pix (gtv self 'grid_pos))) 2569 | t 2570 | ) 2571 | ) 2572 | ) 2573 | 2574 | _calculate-pixel-size #'(lambda (self) 2575 | (let* ((cd (gtv self 'current_display))) 2576 | (unless (null cd) 2577 | (let* ((gsp (gtv cd 'grid_space)) (ps (gtv self 'pixel_size)) (gsz (gtv self 'grid_size))) 2578 | (stv ps 'width (constrain (* (gtv gsz 'width) (gtv gsp 'width)) 1 (gtv cd 'pix_max_x))) 2579 | (stv ps 'height (constrain (* (gtv gsz 'height) (gtv gsp 'height)) 1 (gtv cd 'pix_max_y))) 2580 | ) 2581 | t 2582 | ) 2583 | ) 2584 | ) 2585 | 2586 | _coords-within #'(lambda (self coords) 2587 | (let* ((pp (gtv self 'pixel_pos)) 2588 | (ps (gtv self 'pixel_size)) 2589 | (xmi (gtv pp 'x)) 2590 | (ymi (gtv pp 'y)) 2591 | (xma (+ xmi (gtv ps 'width) -1)) 2592 | (yma (+ ymi (gtv ps 'height) -1))) 2593 | 2594 | (if (and (>= (first coords) xmi) (<= (first coords) xma)) 2595 | (if (and (>= (second coords) ymi) (<= (second coords) yma)) 2596 | t 2597 | nil 2598 | ) 2599 | nil 2600 | ) 2601 | ) 2602 | ) 2603 | 2604 | _set-display #'(lambda (self myd &optional (rfr nil)) 2605 | (unless (null (gtv self 'current_display)) 2606 | (cmt (gtv self 'current_display) '_remove-element self) 2607 | ) 2608 | (stv self 'current_display myd) 2609 | (cmt myd '_add-element (read-from-string (gtv self 'name))) 2610 | (when rfr 2611 | (cmt self '_reframe-grid-pos) 2612 | ) 2613 | ) 2614 | 2615 | _set-colors #'(lambda (self fg bg bd) 2616 | (stv self 'fg_color fg) 2617 | (stv self 'bg_color bg) 2618 | (stv self 'border_color bd) 2619 | (stv self 'redraw t) 2620 | ) 2621 | 2622 | _use-grid #'(lambda (self ongrid) 2623 | (stv self 'grid ongrid) 2624 | (stv self 'redraw t) 2625 | ) 2626 | 2627 | _uses-grid #'(lambda (self) 2628 | (gtv self 'grid) 2629 | ) 2630 | 2631 | _reframe-grid-pos #'(lambda (self) 2632 | (unless (null (gtv self 'current_display)) 2633 | 2634 | (let* ((dp (gtv self 'current_display)) 2635 | (gp (gtv self 'grid_pos)) 2636 | (gs (gtv self 'grid_size)) 2637 | (cdmix (gtv dp 'grid_min_x)) 2638 | (cdmax (gtv dp 'grid_max_x)) 2639 | (cdmiy (gtv dp 'grid_min_y)) 2640 | (cdmay (gtv dp 'grid_max_y))) 2641 | (stv gp 'x (constrain (gtv gp 'x) cdmix cdmax)) 2642 | (stv gp 'y (constrain (gtv gp 'y) cdmiy cdmay)) 2643 | 2644 | (stv gs 'width (min (gtv gs 'width) (- cdmax cdmix))) 2645 | (stv gs 'height (min (gtv gs 'height) (- cdmay cdmiy))) 2646 | ) 2647 | (cmt self '_calculate-pixel-pos) 2648 | (stv self 'redraw t) 2649 | ) 2650 | ) 2651 | ) 2652 | ) 2653 | ) 2654 | 2655 | 2656 | (defvar label 2657 | (class 'display-element '( 2658 | 2659 | font "" 2660 | text_pos nil 2661 | text_size 1 2662 | text "" 2663 | stroke 1 2664 | 2665 | _init #'(lambda (self &optional (aname "empty") (atext "")) 2666 | (stv self 'type 1) 2667 | (stv self 'text_pos (class 'pos nil t)) 2668 | (stv self 'name aname) 2669 | (stv self 'text atext) 2670 | (stv self 'type 1) 2671 | (stv self 'pixel_size (class 'shape-size nil t)) 2672 | (stv self 'grid nil) 2673 | (stv self 'current_display nil) 2674 | (stv self 'pixel_pos (class 'pos nil t)) 2675 | 2676 | (stv self 'grid_pos (class 'pos nil t)) 2677 | (stv self 'grid_size (class 'shape-size nil t)) 2678 | 2679 | (stv self 'fg_color (class 'color nil t)) 2680 | (stv self 'bg_color (class 'color nil t)) 2681 | (stv self 'border_color (class 'color nil t)) 2682 | 2683 | (cmt (gtv self 'pixel_size) '_set-size 16 16) 2684 | (cmt (gtv self 'grid_size) '_size-one) 2685 | ) 2686 | 2687 | _set-text-size #'(lambda (self scale) 2688 | (stv self 'text_size scale) 2689 | (stv self 'redraw t) 2690 | ) 2691 | 2692 | _set-text #'(lambda (self atext) 2693 | (stv self 'text (string atext)) 2694 | (stv self 'redraw t) 2695 | ) 2696 | 2697 | _set-stroke #'(lambda (self st) 2698 | (let* ((dp (gtv self 'current_display))) 2699 | (unless (null dp) 2700 | (stv self 'stroke (constrain st 1 (min (gtv dp 'pix_max_x) (gtv dp 'pix_max_y)))) 2701 | (stv self 'redraw t) 2702 | ) 2703 | ) 2704 | ) 2705 | 2706 | _draw #'(lambda (self) 2707 | (unless (null (gtv self 'current_display)) 2708 | (when (gtv self 'grid) 2709 | (cmt self '_reframe-grid-pos) 2710 | ) 2711 | (let* ((pp (gtv self 'pixel_pos)) (ps (gtv self 'pixel_size)) (tp (gtv self 'text_pos)) (st (gtv self 'stroke)) (minus 0)) 2712 | (fill-rect (gtv pp 'x) (gtv pp 'y) (gtv ps 'width) (gtv ps 'height) (cmt (gtv self 'bg_color) '_to-16bit)) 2713 | (dotimes (plus st) 2714 | (setq minus (* plus 2)) 2715 | (draw-rect (+ (gtv pp 'x) plus) (+ (gtv pp 'y) plus) (- (gtv ps 'width) minus) (- (gtv ps 'height) minus) (cmt (gtv self 'border_color) '_to-16bit)) 2716 | ) 2717 | 2718 | (let* ((ts (gtv self 'text_size)) (tl (length (gtv self 'text))) (ix 0) (iy 0) ) 2719 | (when (> tl 0) 2720 | (set-text-size ts) 2721 | (setq ix (max 0 (round (/ (+ (- (gtv ps 'width) (* 6 tl ts)) ts) 2)))) 2722 | (setq iy (max 0 (round (/ (- (gtv ps 'height) (* 7 ts)) 2)))) 2723 | (set-cursor (+ (gtv pp 'x) ix) (+ (gtv pp 'y) iy)) 2724 | (set-text-color (cmt (gtv self 'fg_color) '_to-16bit)) 2725 | (set-text-size (gtv self 'text_size)) 2726 | (with-gfx (str) 2727 | (princ (gtv self 'text) str) 2728 | ) 2729 | ) 2730 | ) 2731 | ) 2732 | (stv self 'redraw nil) 2733 | ) 2734 | ) 2735 | ) 2736 | t 2737 | ) 2738 | ) 2739 | 2740 | 2741 | (defvar button 2742 | (class 'label '( 2743 | 2744 | downtext "" 2745 | isdown nil 2746 | 2747 | _init #'(lambda (self &optional (aname "empty") (atext "") (adtext "")) 2748 | (stv self 'type 2) 2749 | (stv self 'text_pos (class 'pos nil t)) 2750 | (stv self 'name aname) 2751 | (stv self 'text atext) 2752 | (stv self 'downtext adtext) 2753 | (stv self 'type 1) 2754 | (stv self 'pixel_size (class 'shape-size nil t)) 2755 | (stv self 'grid nil) 2756 | (stv self 'current_display nil) 2757 | (stv self 'pixel_pos (class 'pos nil t)) 2758 | 2759 | (stv self 'grid_pos (class 'pos nil t)) 2760 | (stv self 'grid_size (class 'shape-size nil t)) 2761 | 2762 | (stv self 'fg_color (class 'color nil t)) 2763 | (stv self 'bg_color (class 'color nil t)) 2764 | (stv self 'border_color (class 'color nil t)) 2765 | 2766 | (cmt (gtv self 'pixel_size) '_set-size 16 16) 2767 | (cmt (gtv self 'grid_size) '_size-one) 2768 | ) 2769 | 2770 | _is-down #'(lambda (self) 2771 | (gtv self 'isdown) 2772 | ) 2773 | 2774 | _down #'(lambda (self) 2775 | (stv self 'isdown t) 2776 | (stv self 'redraw t) 2777 | ) 2778 | 2779 | _up #'(lambda (self) 2780 | (stv self 'isdown nil) 2781 | (stv self 'redraw t) 2782 | ) 2783 | 2784 | _toggle #'(lambda (self) 2785 | (stv self 'isdown (not (gtv self 'isdown))) 2786 | (stv self 'redraw t) 2787 | ) 2788 | 2789 | _set-down-text #'(lambda (self atext) 2790 | (stv self 'downtext (string atext)) 2791 | (stv self 'redraw t) 2792 | ) 2793 | 2794 | _draw #'(lambda (self) 2795 | (unless (null (gtv self 'current_display)) 2796 | (when (gtv self 'grid) 2797 | (cmt self '_reframe-grid-pos) 2798 | ) 2799 | 2800 | (let* ((pp (gtv self 'pixel_pos)) 2801 | (ps (gtv self 'pixel_size)) 2802 | (tp (gtv self 'text_pos)) 2803 | (st (gtv self 'stroke)) 2804 | (dtext (class 'color nil t)) 2805 | (ishad (class 'color nil t)) 2806 | (bshad (class 'color nil t)) 2807 | (bgc (class 'color nil t)) 2808 | (fgc (class 'color '(red 255 green 255 blue 255))) 2809 | (minus 0) 2810 | (isd (gtv self 'isdown)) 2811 | (mono (gtv (gtv self 'current_display) 'mono))) 2812 | 2813 | (cmt dtext '_set-rgb-list (cmt (gtv self 'fg_color) '_darken-by 80)) 2814 | (cmt ishad '_set-rgb-list (cmt (gtv self 'bg_color) '_darken-by 80)) 2815 | (cmt bshad '_set-rgb-list (cmt (gtv self 'border_color) '_darken-by 80)) 2816 | 2817 | (if isd 2818 | (if mono 2819 | (fill-rect (gtv pp 'x) (gtv pp 'y) (gtv ps 'width) (gtv ps 'height) (cmt bgc '_to-16bit)) 2820 | (fill-rect (gtv pp 'x) (gtv pp 'y) (gtv ps 'width) (gtv ps 'height) (cmt ishad '_to-16bit)) 2821 | ) 2822 | (if mono 2823 | (fill-rect (gtv pp 'x) (gtv pp 'y) (gtv ps 'width) (gtv ps 'height) (cmt bgc '_to-16bit)) 2824 | (fill-rect (gtv pp 'x) (gtv pp 'y) (gtv ps 'width) (gtv ps 'height) (cmt (gtv self 'bg_color) '_to-16bit)) 2825 | ) 2826 | ) 2827 | 2828 | (let* ((ulcol (if isd bshad (gtv self 'border_color))) 2829 | (drcol (if isd (gtv self 'border_color) bshad))) 2830 | (when mono 2831 | (progn 2832 | (setq ulcol (if isd fgc bgc)) 2833 | (setq drcol (if isd bgc fgc)) 2834 | ) 2835 | ) 2836 | (dotimes (plus st) 2837 | (draw-line (+ (gtv pp 'x) plus) (+ (gtv pp 'y) plus) (+ (gtv pp 'x) plus) (+ (gtv pp 'y) (- (gtv ps 'height) plus)) (cmt ulcol '_to-16bit)) 2838 | (draw-line (+ (gtv pp 'x) plus) (+ (gtv pp 'y) (- (gtv ps 'height) plus)) (+ (gtv pp 'x) (- (gtv ps 'width) plus)) (+ (gtv pp 'y) (- (gtv ps 'height) plus)) (cmt drcol '_to-16bit)) 2839 | (draw-line (+ (gtv pp 'x) (- (gtv ps 'width) plus)) (+ (gtv pp 'y) (- (gtv ps 'height) plus)) (+ (gtv pp 'x) (- (gtv ps 'width) plus)) (+ (gtv pp 'y) plus) (cmt drcol '_to-16bit)) 2840 | (draw-line (+ (gtv pp 'x) (- (gtv ps 'width) plus)) (+ (gtv pp 'y) plus) (+ (gtv pp 'x) plus) (+ (gtv pp 'y) plus) (cmt ulcol '_to-16bit)) 2841 | ) 2842 | ) 2843 | 2844 | (let* ((ts (gtv self 'text_size)) 2845 | (myt (if isd (gtv self 'downtext) (gtv self 'text))) 2846 | (tl (length myt)) 2847 | (ix 0) 2848 | (iy 0)) 2849 | (when (> tl 0) 2850 | (set-text-size ts) 2851 | (setq ix (max 0 (round (/ (+ (- (gtv ps 'width) (* 6 tl ts)) ts) 2)))) 2852 | (setq iy (max 0 (round (/ (- (gtv ps 'height) (* 7 ts)) 2)))) 2853 | (set-cursor (+ (gtv pp 'x) ix) (+ (gtv pp 'y) iy)) 2854 | (if mono 2855 | (set-text-color (cmt fgc '_to-16bit)) 2856 | (if isd 2857 | (set-text-color (cmt dtext '_to-16bit)) 2858 | (set-text-color (cmt (gtv self 'fg_color) '_to-16bit)) 2859 | ) 2860 | ) 2861 | (set-text-size (gtv self 'text_size)) 2862 | (with-gfx (str) 2863 | (if isd 2864 | (princ (gtv self 'downtext) str) 2865 | (princ (gtv self 'text) str) 2866 | ) 2867 | ) 2868 | ) 2869 | ) 2870 | ) 2871 | (stv self 'redraw nil) 2872 | ) 2873 | ) 2874 | ) 2875 | t 2876 | ) 2877 | ) 2878 | 2879 | (backtrace) 2880 | 2881 | )lisplibrary"; 2882 | -------------------------------------------------------------------------------- /LispyLittleHelper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/LispyLittleHelper.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ulisp-lispbox --- Firmware for LispBox and LispDeck 2 | Modified version of ulisp-arm (see below) for use with a self-contained uLisp computer based on the Teensy 4.1, a TFT screen with RA8875 controller and touchscreen support (if applicable) and an USB keyboard. The REPL works locally and via serial connection simultaneously and prints to the TFT as well. 3 | 4 | **ADDENDUM:** Added "Lispy Little Helper", please see below screenshot 5 | 6 | Contains several modifications to the ulisp-arm version (many based on the uLisp firmware for the LilyGO T-Deck) 7 | as well as a set of suitable uLisp extensions including RFM69 support and a Lisp library providing an extended ULOS system, the most important parts of a uLisp port of ErsatzMoco (github.com/ersatzmoco/ersatzmoco) and a full-screen uLisp and text editor. 8 | The editor features full SD card support, direct binding to uLisp symbols, full bracket matching and some keyboard shortcuts partially compatible with EMACS: 9 | 10 | * CTRL-q / CTRL-c --- quit editor and return to REPL 11 | * CTRL-x / CTRL-b / CTRL-n --- discard current text buffer (i.e. new file) 12 | 13 | * CTRL-k / CTRL-l / ALT-x --- delete line starting at cursor position (deleted part is copied before) 14 | * ALT-c --- copy current line 15 | * ALT-v --- insert copy buffer at cursor position 16 | 17 | **Note:** ALT-v also serves as a rudimentary undo. If you accidentally delete part of a line using CTRL-k, CTRL-l or ALT-x you can insert that part again using ALT-v. 18 | 19 | * CTRL-a / HOME --- move cursor to start of line 20 | * CTRL-e / END --- move cursor to end of line 21 | * ^ --- move cursor to beginning of buffer 22 | * PG UP/PG DOWN --- move one page up or down 23 | 24 | * F1 --- toggle bracket matching on/off 25 | * F2 --- check whether bracket under the cursor has a matching bracket in the buffer. If so, both are temporarily highlighted. (Use when continuous bracket matching is off.) 26 | * F3 --- invoke "Lispy Little Helper" if applicable, see below 27 | * F4 --- load the code of a symbol of your choice *read-only* into the editor. You may scroll through it and copy lines, but editing is blocked. To return to your text buffer press F4 again (or F7 or F12). 28 | * F5 --- bind contents of the text buffer to a symbol of your choice and quit editor 29 | 30 | * F7 --- load text from SD card *read-only* into the editor. You may scroll through it and copy lines, but editing is blocked. To return to your text buffer press F7 again (or F4 or F12). 31 | * F8 --- save current buffer to backup file "BACKUP.CL" (overwriting old backup file). This is intended as a quick save function to prevent the worst case scenario of running out of battery before having saved your current work. It is recommended to use F8 at regular intervals. 32 | * F9 --- delete a file on the SD card 33 | * F10 --- save text buffer to SD card 34 | * F11 --- load text from SD card into buffer, discarding the present one 35 | * F12 --- show directory of SD card in *read-only* buffer. To return to your text buffer press F12 again (or F4 or F7). 36 | Note: file names for SD card follow the 8.3 standard and thus must be given in capital letters. 37 | 38 | * ALT-0 to ALT-9 --- insert one of up to ten predefined snippets at cursor position 39 | The snippets are defined in function `se:init` and reside in the global variable `se:sniplist` during runtime of the editor. You may change them according to your needs in file "LispboxLibrary.h" (re-flash your MCU with this firmware after change). 40 | 41 | 42 | The editor is written in uLisp. To invoke it type 43 | 44 | (se:sedit) or (se:sedit 'symbol) where "symbol" can be any symbol name already present in uLisp 45 | 46 | ![Editor screenshot](screenshot_editor.jpg) 47 | 48 | # ADDENDUM 49 | 50 | The Lisp Library of the Lisp Box now contains "Lispy Little Helper". This is a gadget using a KY-040 rotary encoder and a small second TFT display with ST7735 driver chip (see photo below, encoder on the right placed behind and below the Teensy). The default settings use a resolution of 160x128 pixels. 51 | 52 | The Lispy Little Helper collects built-in help information of uLisp symbols as a kind of virtual Rolodex lexicon, accessible from the REPL and the fullscreen editor as well. 53 | 54 | *If you do not intend to use this addendum, please set variable "se:help-active" to nil. This is done either by modifying the first active line of the Lisp Library (file LispboxLibrary.h) before uploading the firmware to your Teensy or by executing (setf se:help-active nil) in the REPL after startup.* 55 | 56 | **When `se:help-active` is set to `t`, the rotary encoder also controls vertical movement of the cursor in the fullscreen editor, as an alternative to the up/down cursor keys.** 57 | 58 | **The backlight of the secondary display is set to `0` by default to reduce the power draw and save some energy. If you want to use the TFT for own experiments, use `(set-backlight level)` to make it visible. `level` may be any integer number between 0 and 255.** 59 | 60 | If you want to add the Lispy Little Helper to your Lisp Box, connect the rotary encoder and the display to the following pins (you may change them within the function `se:help`): 61 | 62 | **Encoder:** "+" to 3.3V, "GND" to GND, "CLK" to pin 16, "DT" to pin 14, "SW" to pin 20. 63 | 64 | **Display** (using the default SPI port): "SCK" to SCK (pin 13), "SDA" to MOSI (pin 11), "CS" to pin 9, "A0" to pin 6, "RST" to pin 8 and LED to pin 5. 65 | 66 | **Usage of Lispy Little Helper:** 67 | 68 | The help screen works both within the fullscreen editor and with the REPL. In the editor, you can access the lexicon by pressing "F3". The TFT display is activated with the message: `Press key or encoder!` If you press an alphanumeric key on the USB keyboard, a scrollable list of all uLisp symbols that begin with the chosen character will appear. If there are none, `No entry` will be displayed. If instead of pressing a key, you directly turn or press the encoder, the list of *all* symbols currently included in uLisp will appear, i.e., functions and global variables. 69 | 70 | Now turn the encoder until the entry you want to view is highlighted. Press the encoder, and the display will show the help text for it, if available. For example, if it is a global variable, which naturally does not have help text, the display will show `No doc`. Most help texts also provide a function prototype, which is an empty dummy of the correct function call. If you press the encoder again from the help text, this function prototype will be directly written into the fullscreen editor, and the lexicon will return to the list. 71 | 72 | If you type a starting letter in the help text (or in the list) instead, the corresponding list will be shown. Pressing "F3" again will exit the helper. 73 | 74 | To use it in the REPL, enter `(se:help)` [Enter] - the rest works as described. With one exception: when you press the encoder in the help text, the function prototype will not be output. Instead, the lexicon remembers all function prototypes you view and outputs them when you exit the helper (also with "F3") as feedback in the REPL, so you have them as a reminder and can type them accordingly if needed. 75 | 76 | ![Lispy Little Helper](LispyLittleHelper.jpg) 77 | ![LispDeck](LispDeck.jpg) 78 | 79 | Lisp Box firmware is based on ulisp-arm by David Johnson-Davies: 80 | # ulisp-arm 81 | A version of the Lisp programming language for boards based on the ARM processor: 82 | 83 | * Arduino Zero and MKRZero. 84 | * Arduino Uno R4 Minima and WiFi. 85 | * Adafruit ItsyBitsy M0, Feather M0, and Gemma M0. 86 | * Adafruit Metro M4, ItsyBitsy M4, Feather M4, and Grand Central M4. 87 | * Adafruit PyBadge and PyGamer. 88 | * Adafruit CLUE and ItsyBitsy nRF52840. 89 | * Raspberry Pi Pico and Raspberry Pi Pico W. 90 | * BBC Micro Bit. 91 | * Maxim MAX32620FTHR. 92 | * Teensy 4.0/4.1. 93 | 94 | For more information see: http://www.ulisp.com/ 95 | -------------------------------------------------------------------------------- /screenshot_editor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ErsatzMoco/ulisp-lispbox/425fc6bc64186839e3a5e6c007fc9f4c6af34350/screenshot_editor.jpg --------------------------------------------------------------------------------