From bddb9dba45b8f43f8bf35cdb5f410775d0f95196 Mon Sep 17 00:00:00 2001 From: Fatima Idrees Date: Wed, 30 Jul 2025 10:26:24 +0300 Subject: [PATCH] 2nd --- Downloads/Blue_I2C.ubl | 52 ++ Downloads/Green_Analog.ubl | 32 + Downloads/Orange_MultiDigitalPins.ubl | 66 ++ Downloads/Red_Digital.ubl | 84 +++ Downloads/Yellow_PWM.ubl | 102 ++++ Downloads/iScreen.ubl | 843 ++++++++++++++++++++++++++ README.md | 10 +- 7 files changed, 1188 insertions(+), 1 deletion(-) create mode 100644 Downloads/Blue_I2C.ubl create mode 100644 Downloads/Green_Analog.ubl create mode 100644 Downloads/Orange_MultiDigitalPins.ubl create mode 100644 Downloads/Red_Digital.ubl create mode 100644 Downloads/Yellow_PWM.ubl create mode 100644 Downloads/iScreen.ubl diff --git a/Downloads/Blue_I2C.ubl b/Downloads/Blue_I2C.ubl new file mode 100644 index 0000000..d1c5d49 --- /dev/null +++ b/Downloads/Blue_I2C.ubl @@ -0,0 +1,52 @@ +module Spark_I2C 'cat;Output' +author FABLAB +version 1 1 +depends '_Gesture (PAJ7620)' +choices direction clockwise 'counter-clockwise' +description '' +variables Gesture + + spec 'r' 'Gesture Read' 'Gesture Read' + space + spec ' ' 'Motor Driver A' 'Motor Driver A Direction _ Speed _' 'menu.direction num' 'clockwise' 10 + spec ' ' 'Motor Driver B' 'Motor Driver B Direction _ Speed _' 'menu.direction num' 'clockwise' 10 + spec 'r' '_Direction' '_Motor Direction _' 'menu.direction' '10' + +to Direction Direction { + if (Direction == ('[data:toString]' 'counter-clockwise')) { + return (booleanConstant false) + } else { + return (booleanConstant true) + } +} + +to 'Gesture Read' { + return ('paj7620 read') +} + +to 'Motor Driver A' Direction Speed { + if ((Direction Direction) == (booleanConstant true)) { + i2cSet 0 1 Speed + i2cSet 0 2 0 + } ((Direction Direction) == (booleanConstant false)) { + i2cSet 0 1 0 + i2cSet 0 2 Speed + } else { + i2cSet 0 1 0 + i2cSet 0 2 0 + } +} + +to 'Motor Driver B' Direction Speed { + if ((Direction Direction) == (booleanConstant true)) { + i2cSet 0 3 Speed + i2cSet 0 4 0 + } ((Direction Direction) == (booleanConstant false)) { + i2cSet 0 3 0 + i2cSet 0 4 Speed + } else { + i2cSet 0 3 0 + i2cSet 0 4 0 + } +} + diff --git a/Downloads/Green_Analog.ubl b/Downloads/Green_Analog.ubl new file mode 100644 index 0000000..2e4aee9 --- /dev/null +++ b/Downloads/Green_Analog.ubl @@ -0,0 +1,32 @@ +module Spark_Analog 'cat;Operators' +author 'FABLAB BH' +version 1 1 +description '' + + choices analog_pins '3' '4' '6' '7' '8' + spec 'r' '_Analog Pins' '_Analog Pins _' 'num' 3 + spec 'r' 'Film Pressure Pin' 'Film Pressure Pin _' 'menu.analog_pins' 3 + spec 'r' 'PhotoResistance Pin' 'Photoresistance Pin _' 'menu.analog_pins' 3 + spec 'r' 'Potentiometer' 'Potentiometer Pin _' 'menu.analog_pins' 3 + spec 'r' 'Steam Sensor' 'Steam Sensor _' 'menu.analog_pins' 3 + +to 'Analog Pins' Pin { + return (at Pin ('[data:makeList]' 0 0 4 39 0 36 35 34 0)) +} + +to 'Film Pressure Pin' Pin { + return (analogReadOp ('Analog Pins' Pin)) +} + +to 'PhotoResistance Pin' Pin { + return (analogReadOp ('Analog Pins' Pin)) +} + +to Potentiometer Pin { + return (analogReadOp ('Analog Pins' Pin)) +} + +to 'Steam Sensor' Pin { + return (analogReadOp ('Analog Pins' Pin)) +} + diff --git a/Downloads/Orange_MultiDigitalPins.ubl b/Downloads/Orange_MultiDigitalPins.ubl new file mode 100644 index 0000000..98bfc27 --- /dev/null +++ b/Downloads/Orange_MultiDigitalPins.ubl @@ -0,0 +1,66 @@ +module Spark_MP 'cat;Variables' +author FABLAB +version 1 1 +choices MP_pins '1' '9' +description '' + + spec 'r' 'Ultrasonic Pin' 'Ultrasonic Pin _' 'menu.MP_pins' 1 + spec 'r' '_Multipins' 'Multipins _' 'menu.MP_pins' '1' + space + spec ' ' 'RGBLED3 Pin' 'RGBLED Pin _ R _ G _ B _' 'menu.MP_pins bool bool bool' 1 true true true + spec ' ' 'Traffic Light' 'Traffic Light Pin _ R _ Y _ G _' 'menu.MP_pins bool bool bool' 1 true true true + space + spec ' ' 'RGBLED3' 'RGBLED Pin _ R _ G _ B _' 'menu.MP_pins num num num' 1 50 50 50 + spec ' ' 'Traffic Light Pin' 'Traffic Light Pin _ R _ Y _ G _' 'menu.MP_pins num num num' 1 255 255 255 + +to Multipins Pin { + return (at Pin ('[data:makeList]' 12 0 0 0 0 0 0 0 17)) +} + +to RGBLED3 Pin Red Green Blue { + analogWriteOp (Multipins Pin) Red + analogWriteOp ((Multipins Pin) + 1) Green + analogWriteOp ((Multipins Pin) + 2) Blue +} + +to 'RGBLED3 Pin' Pin Red Green Blue { + digitalWriteOp (Multipins Pin) Red + digitalWriteOp ((Multipins Pin) + 1) Green + digitalWriteOp ((Multipins Pin) + 2) Blue +} + +to 'Traffic Light' Pin Red Yellow Green { + digitalWriteOp (Multipins Pin) Red + digitalWriteOp ((Multipins Pin) + 1) Yellow + digitalWriteOp ((Multipins Pin) + 2) Green +} + +to 'Traffic Light Pin' Pin Red Yellow Green { + analogWriteOp (Multipins Pin) Red + analogWriteOp ((Multipins Pin) + 1) Yellow + analogWriteOp ((Multipins Pin) + 2) Green +} + +to 'Ultrasonic Pin' Pin { + comment 'Contributed by Joan Guillén and Josep Ferràndiz' + digitalWriteOp ((Multipins Pin) + 1) false + waitMicros 2 + digitalWriteOp ((Multipins Pin) + 1) true + waitMicros 50 + digitalWriteOp ((Multipins Pin) + 1) false + local 'start' (microsOp) + waitUntil (or (not (digitalReadOp ((Multipins Pin) + 2))) (((microsOp) - start) > 23320)) + waitUntil (or (digitalReadOp ((Multipins Pin) + 2)) (((microsOp) - start) > 23320)) + if (((microsOp) - start) > 23320) { + comment 'Distance sensor not ready; return the last distance reading' + return _sr04_last + } + comment 'Pulse sent. Measure time until echo is detected.' + start = (microsOp) + waitUntil (or (not (digitalReadOp ((Multipins Pin) + 2))) (((microsOp) - start) > 23320)) + _sr04_last = ((10 * ((microsOp) - start)) / 583) + comment 'Leave some time for reverberations to die away.' + waitMillis 10 + return _sr04_last +} + diff --git a/Downloads/Red_Digital.ubl b/Downloads/Red_Digital.ubl new file mode 100644 index 0000000..ad69b84 --- /dev/null +++ b/Downloads/Red_Digital.ubl @@ -0,0 +1,84 @@ +module Spark_Digital Data +author 'FABLAB BH' +version 1 1 +depends '_Temperature Humidity (DHT11, DHT22)' +choices digital_pins '1' '2' '3' '4' '6' '7' '8' '9' +description '' + spec 'r' '_DigitalPins' '_DigitalPins _' 'menu.digital_pins' 1 + spec 'r' 'Button Pin' 'Button Pin _' 'menu.digital_pins' 1 + spec 'r' 'Hall Magnetic Pin' 'Hall Magnetic Pin _' 'menu.digital_pins' 1 + spec 'r' 'Photo Interrupter Pin' 'Photo Interrupter Pin _' 'menu.digital_pins' 1 + spec 'r' 'Tilt Switch Pin' 'Tilt Switch Pin _' 'menu.digital_pins' 1 + spec 'r' 'Touch Pin' 'Touch Pin _' 'menu.digital_pins' 1 + spec 'r' 'Humidity Pin' 'Humidity Pin _' 'menu.digital_pins' 1 + spec 'r' 'Temperature Pin' 'Temperature Pin _' 'menu.digital_pins' 1 + space + space + spec ' ' 'Buzzer2' 'Buzzer Pin _ State _' 'menu.digital_pins bool' 1 false + spec ' ' 'LED' 'LED Pin _ State _' 'menu.digital_pins bool' 1 false + spec ' ' 'Relay Pin' 'Relay Pin _ State _' 'menu.digital_pins bool' 1 false + space + spec ' ' 'Buzzer' 'Buzzer Pin _ Tone _' 'menu.digital_pins num' 1 1000 + spec ' ' 'LED2 Pin' 'LED Pin _ Brightness _' 'menu.digital_pins num' 1 1000 + +to DigitalPins Pin { + return (at Pin ('[data:makeList]' 13 2 26 27 0 23 16 5 18)) +} + +to 'Button Pin' Pin { + local 'Read1' (digitalReadOp (DigitalPins Pin) 'up') + if (Read1 == (booleanConstant true)) { + return (not Read1) + } else { + return (booleanConstant true) + } +} + +to Buzzer Pin Tone { + analogWriteOp (DigitalPins Pin) Tone +} + +to Buzzer2 Pin State { + digitalWriteOp (DigitalPins Pin) State +} + +to 'Humidity Pin' Pin { + return (humidity_DHT11 (DigitalPins Pin)) +} + +to LED Pin State { + digitalWriteOp (DigitalPins Pin) State +} + +to 'LED2 Pin' Pin Brightness { + analogWriteOp (DigitalPins Pin) Brightness +} + +to 'Photo Interrupter Pin' Pin { + return (digitalReadOp (DigitalPins Pin)) +} + +to 'Relay Pin' Pin State { + digitalWriteOp (DigitalPins Pin) State +} + +to 'Temperature Pin' Pin { + return (temperature_DHT11 (DigitalPins Pin)) +} + +to 'Tilt Switch Pin' Pin { + return (digitalReadOp (DigitalPins Pin)) +} + +to 'Touch Pin' Pin { + return (digitalReadOp (DigitalPins Pin)) +} + +to 'Hall Magnetic Pin' Pin { + local 'Read1' (digitalReadOp (DigitalPins Pin) 'up') + if (Read1 == (booleanConstant true)) { + return (not Read1) + } else { + return (booleanConstant true) + } +} diff --git a/Downloads/Yellow_PWM.ubl b/Downloads/Yellow_PWM.ubl new file mode 100644 index 0000000..5775880 --- /dev/null +++ b/Downloads/Yellow_PWM.ubl @@ -0,0 +1,102 @@ +module Spark_PWM 'cat;Control' +author 'FABLAB BH' +version 1 1 +depends _Servo +choices PWM_pins '1' '9' +choices PWM_pins2 '3' '4' '6' '7' '8' +choices direction clockwise 'counter-clockwise' +choices servo_pins '32' '33' +description '' + + spec 'r' '_PWM Pin' '_PWM Pin _' 'menu.PWM_pins' 1 + spec 'r' '_Direction' '_Direction _' 'menu.direction' 'clockwise' + + spec ' ' 'Fan Motor3' 'Fan Motor Pin _ Speed _ (0-100)' 'menu.PWM_pins2 num' 3 50 + spec ' ' 'Fan Motor4' 'Fan Motor Pin _ Speed _ (0-1023)' 'menu.PWM_pins2 num' 3 50 + space + spec ' ' 'Fan Motor' 'Fan Motor Pin _ Direction _ Speed _ (0-100)' 'menu.PWM_pins menu.direction num' 1 'clockwise' 50 + spec ' ' 'Fan Motor2' 'Fan Motor Pin _ Direction _ Speed _ (0-1023)' 'menu.PWM_pins menu.direction num' 1 'clockwise' 50 + space + spec ' ' 'Servo' 'Servo Motor Pin _ Speed _ (-100 to 100)' 'menu.servo_pins num' 33 50 + spec ' ' 'Servo Motor Pin' 'Servo Motor Pin _ Degrees _ (-90 to 90)' 'menu.servo_pins num' 33 90 + +to Direction Direction { + if (Direction == ('[data:toString]' 'counter-clockwise')) { + return (booleanConstant false) + } else { + return (booleanConstant true) + } +} + +to 'Fan Motor' Pin Direction Speed { + if (and (Speed > 0) (Speed <= 100)) { + local 'PWM' (absoluteValue (((Speed - 1) * ((1023 - 1) / 99)) + 1)) + if ((Direction Direction) == (not true)) { + if (and (PWM > 0) (PWM < 1024)) { + digitalWriteOp ('PWM Pin' Pin) true + analogWriteOp (('PWM Pin' Pin) + 1) (1023 - PWM) + } + } else { + if (and (PWM > 0) (PWM < 1024)) { + digitalWriteOp ('PWM Pin' Pin) false + analogWriteOp (('PWM Pin' Pin) + 1) PWM + } + } + } (Speed == 0) { + digitalWriteOp ('PWM Pin' Pin) false + digitalWriteOp (('PWM Pin' Pin) + 1) false + } else { + sayIt 'The range is between 0 and 100' + } +} + +to 'Fan Motor2' Pin Direction Speed { + if (and (Speed > 0) (Speed <= 1023)) { + if ((Direction Direction) == (not true)) { + digitalWriteOp ('PWM Pin' Pin) true + analogWriteOp (('PWM Pin' Pin) + 1) (1023 - Speed) + } else { + digitalWriteOp ('PWM Pin' Pin) false + analogWriteOp (('PWM Pin' Pin) + 1) Speed + } + } (Speed == 0) { + digitalWriteOp ('PWM Pin' Pin) false + digitalWriteOp (('PWM Pin' Pin) + 1) false + } else { + sayIt 'The range is between 0 and 1023' + } +} + +to 'Fan Motor3' Pin Speed { + if (and (Speed > 0) (Speed <= 100)) { + local 'PWM' (absoluteValue (((Speed - 1) * ((1023 - 1) / 99)) + 1)) + analogWriteOp ('PWM Pin' Pin) PWM + } (Speed == 0) { + digitalWriteOp ('PWM Pin' Pin) false + } else { + sayIt 'The range is between 0 and 100' + } +} + +to 'Fan Motor4' Pin Speed { + if (and (Speed > 0) (Speed <= 1023)) { + analogWriteOp ('PWM Pin' Pin) Speed + } (Speed == 0) { + digitalWriteOp ('PWM Pin' Pin) false + } else { + sayIt 'The range is between 0 and 1023' + } +} + +to 'PWM Pin' Pin { + return (at Pin ('[data:makeList]' 13 0 26 27 0 23 16 5 18)) +} + +to Servo Pin Speed { + setServoSpeed Pin Speed +} + +to 'Servo Motor Pin' Pin Degrees { + setServoAngle Pin Degrees +} + diff --git a/Downloads/iScreen.ubl b/Downloads/iScreen.ubl new file mode 100644 index 0000000..fa3ee45 --- /dev/null +++ b/Downloads/iScreen.ubl @@ -0,0 +1,843 @@ +module 'Spark' 'cat;Input' +author 'FABLAB BH credits Turgut for the OLED Graphics' +version 1 1 +depends /Spark_Digital /Spark_Analog /Spark_MP /Spark_PWM /Spark_I2C +choices ModeMenu Horizontal Vertical +choices OnOffMenu On Off +choices VideoMenu Inverse Normal +choices DispTypeMenu 'OLED_0.96in' 'OLED_2.42in' +description 'Supports 0.96in and 2.42in OLED Displays with SD1306 and SD1309 chipsets. Comm mode is I2C or SPI. +Changes: +- always display buffer +- defer display updates block +- remove reveal +- switch to x (0-127), y (0-63) +- Pruned commands and vars +- textX and textY +- Text at any x and y +- handles newLines +- removed dependencies +- unified data format for chars, sprites, and images +- image draw at any x,y +- filled rectangle +- image draw bug fix +- stack overflow fix +- improve conversion ops, i2c io, rect fill, img processing, and buffer displays +- reduce i2c buffer to 128 bytes +- reduce i2c buffer to 64 bytes +- correct internal draws, clean-up vars, restore _clearDisplay +' +variables OLEDReady OLEDi2cAddr _GDBuffer _cDecTBL _comma _cTABLE _comMode _dcPin _delayGDUpd _displayType _eol _resetPin _textX _textY _dataPrefix _byteCount _imgData _imgWidth _imgHeight + + spec ' ' 'OLEDInit_I2C' 'initialize i2c _ address(hex) _ reset pin# _ flip _' 'str.DispTypeMenu auto str bool' 'OLED_0.96in' '3C' '-' false + spec ' ' 'OLEDInit_SPI' 'initialize spi _ d/c pin# _ reset pin# _ flip _' 'str.DispTypeMenu auto auto bool' 'OLED_2.42in' 16 8 false + spec ' ' 'OLEDwrite' 'write _ at x _ y _ inverse _' 'auto auto auto bool' 'Hello!' 0 0 false + spec ' ' 'OLEDshowGDBuffer' 'show display buffer' + spec ' ' 'OLEDclear' 'clear' + spec ' ' 'OLEDcontrast' 'set contrast (1-4) _' 'auto' 2 + spec ' ' 'OLEDdrawCircle' 'draw circle at x _ y _ radius _ erase _' 'auto auto auto bool' 64 32 '10' false + spec ' ' 'OLEDdrawImage' 'draw image _ at x _ y _' 'auto auto auto' 0 0 0 + spec ' ' 'OLEDdrawLine' 'draw line from x _ y _ to x _ y _ erase _' 'auto auto auto auto bool' 0 0 127 63 false + spec ' ' 'OLEDdrawRect' 'draw rectangle x _ y _ w _ h _ erase _ rounding(3-15) _' 'auto auto auto auto bool auto' 0 0 127 63 false 0 + spec ' ' 'OLEDfillRect' 'fill rectangle x _ y _ w _ h _ erase _' 'auto auto auto auto bool' 20 20 30 20 false + spec ' ' '_OLEDflip' '_flip display top _' 'bool' false + spec 'r' 'OLEDmakeImage' 'make image _' 'microbitDisplay' 33084991 + spec ' ' 'OLEDpixel' 'set pixel x _ y _ erase _' 'auto auto bool' 0 0 false + spec ' ' 'OLEDsetVideo' 'set video _' 'str.VideoMenu' 'Inverse' + spec 'r' 'OLEDwru' 'cursor location' + spec ' ' 'defer display updates' 'defer display updates' + spec ' ' '_GDDRAMoff' '_GDDRAMoff' + spec ' ' '_GDDRAMon' '_GDDRAMon' + spec ' ' '_OLEDcursorReset' '_cursor reset' + spec ' ' '_OLEDsetDisplay' '_set display _' 'str.OnOffMenu' 'On' + spec ' ' '_OLEDreset' '_set reset Pin# _' 'auto' '0' + spec ' ' '_SPIWriteCmd' '_SPIWriteCmd' + spec ' ' '_SPIWriteData' '_SPIWriteData' + spec ' ' '_T1' '_T1' + spec ' ' '_T2' '_T2' + spec ' ' '_T3' '_T3' + spec 'r' '_cBMP' '_cBMP _ InvYN _' 'auto bool' '' false + spec ' ' '_clearDisplay' '_clearDisplay' + spec ' ' '_corner' '_corner _ _ _ _ _' 'auto auto auto auto bool' 'TL' 32 1 0 true + spec 'r' '_dec2hex' '_dec2hex _' 'auto' 0 + spec ' ' '_initChars' '_initChars' + spec ' ' '_initCheck' '_initCheck' + spec ' ' '_initDisplayHW' '_initDisplayHW' + spec ' ' '_initLibrary' '_initLibrary' + spec ' ' '_process image data' '_process image data _' 'auto' ' ' + spec ' ' '_sendCmd' '_sendCmd _' 'auto' '' + spec ' ' '_verifyXY' '_verifyXY _ _' 'auto auto' 0 0 + +to OLEDInit_I2C dispType i2cAddr resetPin flip { + comment 'Sets display type and interface and initializes HW settings. +Do NOT set a ResetPin# unless one exists on the display hardware. +NOTE: +Displays supported: +- OLED 0.96in (SD1306 chip) and +- OLED 2.42" (SD1309 chip) +Both displays are 128x64 pixels or 16x8 characters in size. +Displays come in dual mode version (i2c and spi) and pure i2c. +Pure i2c models do not have a Reset pin. + +flip setting controls display hardware write direction: +- false: top to bottom +- true: bottom to top' + _comma = ('[data:unicodeString]' 44) + _comMode = 'i2c' + OLEDi2cAddr = (hexToInt ('[data:join]' ('[data:unicodeString]' 32) i2cAddr)) + _resetPin = resetPin + _displayType = (ifExpression (dispType == 'OLED_0.96in') 9 6) + '_initDisplayHW' + if flip { + '_OLEDflip' true + } + '_initLibrary' + OLEDclear +} + +to OLEDInit_SPI dispType dcPin resetPin flip { + comment 'Sets display type and interface and initializes HW settings. +SPI four wire in Mode-0 is supported. Max speed=10000000. + +Do NOT set a ResetPin# unless one exists on the display hardware. +NOTE: +Displays supported: +- OLED 0.96in (SD1306 chip) and +- OLED 2.42" (SD1309 chip) +Both displays are 128x64 pixels or 16x8 characters in size. +Displays come in dual mode version (i2c and spi) and pure i2c. +Pure i2c models do not have a Reset pin. +flip setting controls display hardware write direction: +- false: top to bottom +- true: bottom to top' + _comma = ('[data:unicodeString]' 44) + _comMode = 'spi' + _dcPin = dcPin + if (_displayType != 0) { + return + } + if (dispType == 'OLED_0.96in') { + _displayType = 6 + _resetPin = resetPin + } else { + _displayType = 9 + _resetPin = resetPin + } + '[sensors:spiSetup]' 10000000 + '_initDisplayHW' + if flip { + '_OLEDflip' true + } + '_initLibrary' + OLEDclear +} + +to OLEDclear { + comment 'Set bounds to FullScreen and CLEARs display +and GDBuffer.' + _GDBuffer = ('[data:newByteArray]' 1024) + '_initCheck' + '_OLEDcursorReset' + OLEDshowGDBuffer +} + +to OLEDcontrast contrast { + comment 'Sets the brightness control of the display to one of four values. +1 is the least bright, 4 is the brightest setting.' + '_initCheck' + local 'cLevels' ('[data:makeList]' 0 '1F' '2F' 'F0') + if (and (contrast >= 1) (contrast <= 4)) { + local 'i2cCmd' ('[data:join]' '81' _comma (at contrast cLevels)) + '_sendCmd' i2cCmd + } else { + sayIt 'Error in CONTRAST Level' + } +} + +to OLEDdrawCircle cx cy r erase { + comment 'Bresenham Circle: +Draws circles, even partially bigger than the display. +x: 0-127 +y: 0-63 +void plotCircle(int xm, int ym, int r) +{ + int x = -r, y = 0, err = 2-2*r; /* II. Quadrant */ + do { + setPixel(xm-x, ym+y); /* I. Quadrant */ + setPixel(xm-y, ym-x); /* II. Quadrant */ + setPixel(xm+x, ym-y); /* III. Quadrant */ + setPixel(xm+y, ym+x); /* IV. Quadrant */ + r = err; + if (r <= y) err += ++y*2+1; /* e_xy+e_y < 0 */ + if (r > x || err > y) err += ++x*2+1; /* e_xy+e_x > 0 or no 2nd y-step */ + } while (x < 0); +}' + '_initCheck' + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + local 'x' (-1 * r) + local 'y' 0 + local 'err' (2 - (2 * r)) + repeatUntil (x >= 0) { + OLEDpixel (cx - x) (cy + y) erase + OLEDpixel (cx - y) (cy - x) erase + OLEDpixel (cx + x) (cy - y) erase + OLEDpixel (cx + y) (cy + x) erase + r = err + if (r <= y) { + y += 1 + err = (err + ((y * 2) + 1)) + } + if (or (r > x) (err > y)) { + x += 1 + err = (err + ((x * 2) + 1)) + } + } + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDdrawImage image x y { + comment '_imgHeight has to be mod8 or 1-8' + if (0 == image) { + return 0 + } + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + for row# (maximum 1 ((minimum _imgHeight (64 - y)) / 8)) { + local 'GDidx' ((((y / 8) * 128) + x) + 1) + local 'imgDispl' ((row# - 1) * _imgWidth) + for byte# (minimum _imgWidth (128 - x)) { + comment 'If y is on page boundary, just copy' + if (0 == (y % 8)) { + atPut GDidx _GDBuffer (at (imgDispl + byte#) image) + GDidx += 1 + if (GDidx > 1024) { + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } + return 0 + } + } else { + comment 'Else, copy GDLowBits + shiftedByte + GDHiBits to GDBuffer and GDBuffer +128' + local 'shiftedByte' ('_dec2hex' ((at (imgDispl + byte#) image) << (y % 8))) + local 'temp' 0 + local 'tempHI' ('[data:copyFromTo]' shiftedByte 1 2) + local 'tempLO' ('[data:copyFromTo]' shiftedByte 3 4) + local 'GDLowBits' ((1 << (y % 8)) - 1) + local 'GDHiBits' (255 - GDLowBits) + tempLO = ((hexToInt tempLO) | ((at GDidx _GDBuffer) & GDLowBits)) + atPut GDidx _GDBuffer tempLO + if ((GDidx + 128) <= 1024) { + tempHI = ((hexToInt tempHI) | ((at (GDidx + 128) _GDBuffer) & GDHiBits)) + atPut (GDidx + 128) _GDBuffer tempHI + } + GDidx += 1 + if (GDidx > 1024) { + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } + return 0 + } + } + waitMillis 0 + } + y += 8 + } + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDdrawLine x0 y0 x1 y1 erase { + comment 'Draws a line from x0,y0 to x1,y1 using the Bresenham Algorithm +x: 0-127 +y: 0-63 +plotLine(int x0, int y0, int x1, int y1) + dx = abs(x1-x0); + sx = x0= dy) /* e_xy+e_x > 0 */ + err += dy; + x0 += sx; + end if + if (e2 <= dx) /* e_xy+e_y < 0 */ + err += dx; + y0 += sy; + end if + end while' + '_initCheck' + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + results = ('[data:makeList]') + local 'dx' (absoluteValue (x1 - x0)) + local 'dy' (-1 * (absoluteValue (y1 - y0))) + local 'err' (dx + dy) + local 'e2' 0 + local 'done' (booleanConstant false) + if (x0 < x1) { + local 'sx' 1 + } else { + local 'sx' -1 + } + if (y0 < y1) { + local 'sy' 1 + } else { + local 'sy' -1 + } + repeatUntil done { + OLEDpixel x0 y0 erase + if (and (x0 == x1) (y0 == y1)) { + done = (booleanConstant true) + } + e2 = (2 * err) + if (e2 >= dy) { + err += dy + x0 += sx + } + if (e2 <= dx) { + err += dx + y0 += sy + } + } + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDdrawRect TLx TLy width height erase cornerRad { + comment 'Draw Rectangle with optional rounded corners with radius R. +Does not check for reversed rectangle coordinates for round corners.' + '_initCheck' + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + local 'BRx' (TLx + width) + local 'BRy' (TLy + height) + if (cornerRad >= 3) { + '_corner' 'TL' TLx TLy cornerRad erase + '_corner' 'TR' BRx TLy cornerRad erase + '_corner' 'BR' BRx BRy cornerRad erase + '_corner' 'BL' TLx BRy cornerRad erase + comment 'TOP - Adjust x' + OLEDdrawLine (TLx + cornerRad) TLy ((BRx - 1) - cornerRad) TLy erase + comment 'RIGHT- Adjust y' + OLEDdrawLine BRx ((TLy + 1) + cornerRad) BRx ((BRy - 1) - cornerRad) erase + comment 'BOTTOM - Adjust x' + OLEDdrawLine ((BRx - 1) - cornerRad) BRy ((TLx + 1) + cornerRad) BRy erase + comment 'LEFT - Adjust y' + OLEDdrawLine TLx ((BRy - 1) - cornerRad) TLx ((TLy + 1) + cornerRad) erase + } else { + OLEDdrawLine TLx TLy BRx TLy erase + OLEDdrawLine BRx (TLy + 1) BRx BRy erase + OLEDdrawLine (BRx - 1) BRy TLx BRy erase + OLEDdrawLine TLx (BRy - 1) TLx (TLy + 1) erase + } + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDfillRect x y w h erase { + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + for row ('[data:range]' 0 (h - 1)) { + for col ('[data:range]' 0 (w - 1)) { + OLEDpixel (x + col) (y + row) erase + } + } + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDmakeImage spr# { + comment 'Receives a spr# representing 5x5 image matrix. +Converts it to a HOR array of 5 VERT bitmap numbers. +This can be displayed with the draw image block. +sprNum max is 33554431' + '_initCheck' + local 'spriteList' ('[data:newByteArray]' 5) + local 'val' 0 + for col 5 { + for row ('[data:asByteArray]' ('[data:makeList]' 0 5 10 15 20)) { + local 'bit' (col + row) + local 'vertBit#' (bit / 5) + if ((spr# & (1 << (bit - 1))) != 0) { + if (col != 5) { + val += (1 << vertBit#) + } else { + val += (1 << (vertBit# - 1)) + } + } + } + atPut col spriteList val + val = 0 + } + _imgWidth = 5 + _imgHeight = 5 + return spriteList +} + +to OLEDpixel x y erase { + comment 'Places a pixel at x,y in the virtual GDBuffer +Use OLEDshowGDBuffer to display it +8192 Pixels over 1024 Bytes +x: 0-127 +y: 0-63 +page#: 0-7 +pagePixel#: 0-7 +GDIndex: 1-1024 + +RangeCheck: +verify x and y are in range of display limits +if X <= num <= Y' + '_initCheck' + local 'pagePixel#' (y % 8) + local 'GDIndex' ((x + ((y / 8) * 128)) + 1) + local 'byteBMP' (at GDIndex _GDBuffer) + byteBMP = (ifExpression (not erase) (byteBMP | (1 << pagePixel#)) (byteBMP & ('~' (1 << pagePixel#)))) + atPut GDIndex _GDBuffer byteBMP +} + +to OLEDsetVideo videoMode { + comment 'Switches the entire display: +Inverse: inverse video mode (bit 0 = on) +Normal: normal video mode (bit 1 = on). +Any image on the display will be preserved when mode changes.' + '_initCheck' + if (videoMode == 'Inverse') { + local 'i2cCmd' 'A7' + } else { + local 'i2cCmd' 'A6' + } + '_sendCmd' i2cCmd +} + +to OLEDshowGDBuffer { + comment 'Copies contents of virtual _GDBuffer to display +i2c: + in 60 byte chunks for speed. + 1 byte is used for the command 40 +spi: + fastest is dump buffer + _GDBuffer is in decimal' + '_initCheck' + if (_comMode == 'i2c') { + local 'idx' 0 + repeat 17 { + '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _dataPrefix ('[data:copyFromTo]' _GDBuffer idx (idx + 60))) + idx += 61 + } + } else { + '_SPIWriteData' + '[sensors:spiExchange]' ('[data:copyFromTo]' _GDBuffer 1) + } + _delayGDUpd = (booleanConstant false) +} + +to OLEDwrite string x y invFlag { + comment 'Writes strings to display at any x,y; processing CR LF and wrapping at col x. +_textX and _textY are next write locations.' + '_initCheck' + local 'oldDelayGDUpd' _delayGDUpd + _delayGDUpd = (booleanConstant true) + '_verifyXY' x y + local 'origX' x + if (not (isType string 'string')) { + string = ('[data:join]' '' string) + } + for char string { + comment 'If in table process it - LINE SET is not supported.' + if (('[data:find]' char _cTABLE) != -1) { + OLEDdrawImage ('_cBMP' char invFlag) x y + x += 8 + if (x > 127) { + x = origX + y += 8 + if (y > 63) { + y = 0 + } + } + } (13 == ('[data:unicodeAt]' 1 char)) { + noop + } (10 == ('[data:unicodeAt]' 1 char)) { + x = origX + y += 8 + if (y > 63) { + y = 0 + } + } else { + comment 'bad char - STOP' + sayIt 'Invalid CHAR value:' char 'uniCode:' ('[data:unicodeAt]' 1 char) + stopTask + } + } + _textX = x + _textY = y + _delayGDUpd = oldDelayGDUpd + if (not _delayGDUpd) { + OLEDshowGDBuffer + } +} + +to OLEDwru { + comment 'Next Row and Column to print +_textY, _textX' + return ('[data:asByteArray]' ('[data:makeList]' _textY _textX)) +} + +to '_GDDRAMoff' { + comment 'Displays a full empty screen of reverse video. +It disengages the hardware GDBuffer. ' + local 'i2cCmd' 'A5' + '_sendCmd' i2cCmd +} + +to '_GDDRAMon' { + comment 'It disables the GDDRAMoff mode and engages the hardware GDBuffer for display content.' + local 'i2cCmd' 'A4' + '_sendCmd' i2cCmd +} + +to '_OLEDcursorReset' { + comment 'Sets display bounds to full range and resets cursor +to the origin top-left (0,0) +Rows: 0-7 +Cols: 0-127 +Cursor position is affected by any display operation +and also by OLEDColMode block.' + '_initCheck' + local 'cmdString' '22,00,07,21,00,7F' + '_sendCmd' cmdString + _textX = 0 + _textY = 0 +} + +to '_OLEDflip' flip { + comment 'Flips the display initialization horizontally or vertically. +Horizontal or vertical is based on the pin connector location.' + if flip { + '_sendCmd' 'A0,C0' + } else { + '_sendCmd' 'A1,C8' + } +} + +to '_OLEDreset' pin { + comment 'Does a power off and on on the display, +thus forcing a hardware initialization.' + digitalWriteOp pin false + waitMillis 1 + digitalWriteOp pin true + waitMillis 1 +} + +to '_OLEDsetDisplay' onoff { + comment 'Puts the display into +Off:SLEEP On:WAKE mode. +Images on display are preserved.' + '_initCheck' + if (onoff == 'On') { + local 'i2cCmd' 'AF' + } else { + local 'i2cCmd' 'AE' + } + '_sendCmd' i2cCmd +} + +to '_SPIWriteCmd' { + comment 'In SPI mode, we send either a write command +or write data control code. Then follow it with +the appropriate command/data bundle.' + digitalWriteOp _dcPin false +} + +to '_SPIWriteData' { + comment 'In SPI mode, we send either a write command +or write data control code. Then follow it with +the appropriate command/data bundle.' + digitalWriteOp _dcPin true +} + +to '_T1' { + comment 'THIN-SS Character Set +Range: space - ?' + local '_cHEX1' '00000000000000000000005F00000000000007000007000000147F14147F140000242A6B6B2A12000046261008646200304A454D324848000000040300000000001C224100000000000041221C000000082A1C1C1C2A08000008083E080800000000806000000000000808080808080000000060000000000040201008040200003E615149453E000044427F4040000000625151494966000022414949493600101814527F5010000027454545453900003C4A4949493000000301710905030000364949494936000006494949291E00000000660000000000008066000000000008142241000000002424242424240000000041221408000002010151090600' + local 'idx' 1 + for i 256 { + atPut i _cDecTBL (hexToInt ('[data:copyFromTo]' _cHEX1 idx (idx + 1))) + idx += 2 + } + _cHEX1 = '' +} + +to '_T2' { + comment 'THIN-SS Character Set +Range: @ - _ (underscore)' + local '_cHEX2' '003E415D55551E00007C121111127C0000417F4949493600001C22414141220000417F4141221C0000417F495D41630000417F491D010300001C224151517200007F080808087F000000417F4100000000304040413F010000417F081422414000417F4140406000007F01020402017F007F010204087F00003E414141413E0000417F4909090600001E212131215E4000417F49192946000026494949493200000301417F410103003F404040403F00000F10204020100F003F40403840403F004122140814224100010244784402010043615149454361007F4141410000000102040810204000004141417F00000008040201020408008080808080808080' + local 'idx' 1 + for i 256 { + atPut (256 + i) _cDecTBL (hexToInt ('[data:copyFromTo]' _cHEX2 idx (idx + 1))) + idx += 2 + } + _cHEX2 = '' +} + +to '_T3' { + comment 'THIN-SS Character Set +Range: '' - . (last char)' + local '_cHEX3' '0000000304000000002054545454784000017F304848483000384444444428000030484848317F4000385454545418000000487E490102000098A4A4A4A4780400417F08040478000000447D400000000060808080847D0000017F10284440000000417F40000000007C040478040478007C08040404780000384444444438000084FC98242418000018242498FC840000447C480404180000485454545424000004043F44442000003C404040207C00000C10204020100C003C40403840403C0044281028440000009CA0A0A0A07C00004464544C44000000080836414100000000007700000000000041413608080000020101020201000000000000000000' + local 'idx' 1 + for i 256 { + atPut (512 + i) _cDecTBL (hexToInt ('[data:copyFromTo]' _cHEX3 idx (idx + 1))) + idx += 2 + } + _cHEX3 = '' +} + +to '_cBMP' char invFlag { + comment 'Returns DEC char bitmap from _cHexTbl and +optionally converts it to inverse (XOR). +Line segments are NOT supported. +A: 00,7c,12,11,12,7c,00 +dec: 0,124,18,17,17,124,0 +inv: 255,131,237,238,238,131,255' + local 'key' (((('[data:unicodeAt]' 1 char) - 32) * 8) + 1) + local 'charList' ('[data:copyFromTo]' _cDecTBL key (key + 7)) + comment 'inverse' + if invFlag { + for item# (size charList) { + atPut item# charList ((at item# charList) ^ 255) + } + } + _imgWidth = 8 + _imgHeight = 8 + return charList +} + +to '_clearDisplay' { + comment 'Clear Screen without initializing _GDBuffer' + '_initCheck' + '_OLEDcursorReset' + if ('i2c' == _comMode) { + repeat 17 { + '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _dataPrefix ('[data:newByteArray]' 60)) + } + '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _dataPrefix ('[data:newByteArray]' 4)) + } else { + '_SPIWriteData' + '[sensors:spiExchange]' ('[data:newByteArray]' 1024) + } +} + +to '_corner' loc cx cy r erase { + comment 'Calculates and displays the rounded corners for the rectangles. +loc is one of TL, TR, BL, BR ... topLeft, topright, bottomleft, bottomright +cx,cy are the corner coordinates for the rounded corner. +r is the radius in pixels of the arc to be calculated.' + local 'x' (-1 * r) + local 'y' 0 + local 'err' (2 - (2 * r)) + if (loc == 'TL') { + cx += r + cy += r + } (loc == 'TR') { + cx += (-1 * r) + cy += r + } (loc == 'BL') { + cx += r + cy += (-1 * r) + } (loc == 'BR') { + cx += (-1 * r) + cy += (-1 * r) + } + repeatUntil (x >= 0) { + if (loc == 'TL') { + OLEDpixel (cx + x) (cy - y) erase + } (loc == 'TR') { + OLEDpixel (cx + y) (cy + x) erase + } (loc == 'BL') { + OLEDpixel (cx - y) (cy - x) erase + } (loc == 'BR') { + OLEDpixel (cx - x) (cy + y) erase + } + r = err + if (r <= y) { + y += 1 + err = (err + ((y * 2) + 1)) + } + if (or (r > x) (err > y)) { + x += 1 + err = (err + ((x * 2) + 1)) + } + } +} + +to '_dec2hex' num { + comment 'Fast version w/o inversion. (~115uSecs)' + local '_hexTbl' '0123456789ABCDEF' + local 'hexNum' '' + repeatUntil (num < 0) { + local 'temp' ('[data:join]' (at ((num % 16) + 1) _hexTbl) hexNum) + hexNum = temp + num = (ifExpression ((num / 16) != 0) (num / 16) -1) + } + comment 'If not half-byte length, pad it.' + hexNum = ('[data:join]' ('[data:copyFromTo]' '000' 1 (4 - (size hexNum))) hexNum) + return hexNum +} + +to '_initChars' { + comment 'Creates the character set used in the Library (96 characters) +used JOIN for SPACE (uni-32) character so it won''t be deleted by mistake. +For each character, _cDecTbl is updated with 8 byte array values.' + _cTABLE = ('[data:join]' ('[data:unicodeString]' 32) '!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~.') + '_T1' + '_T2' + '_T3' +} + +to '_initCheck' { + comment 'Verifies Library initialization status.' + if (not OLEDReady) { + sayIt 'Display needs to be initialized before using the library blocks.' + stopTask + } +} + +to '_initDisplayHW' { + comment '*** DO NOT CHANGE THESE WITHOUT UNDERSTANDING THEIR MEANINGS *** +*** IT CAN MAKE THE DISPLAY NOT OPERATE CORRECTLY *** + +Initializes display HW timings +OLED INITIALIZATION STRINGS: +1306: pins are on top +1309: pins are on the right + +A8 3F - Multiplex Ratio 0F-3F (16mux to 64mux) +D3 00 - Display Offset (vertical) 00-63 +40 - Display Start Line 40-7F (40:0) +A0 - Set Segment Remap A0: Remap 0:0, A1: 127:0 [A1] +C0 - Scan Direction C0:0-127, C8:127-0 [C8] +DA 12 - COM pin hw config 02:double-high 12:normal bits +81 F0 - Set contrast 00-FF (00:dimmest, FF:brightest) [F0] +A4 - A4:display shows GDRAM, A5:display all ON pixels +A6 - A6:Normal video, A7:Inverse video +D5 F0 - Set display clock HB:OSC freq / LB:divide ratio (00-FF) +D9 22 - Set pre-charge period HB:Phase2 / LB:Phase1 (1-15 DCLK) +DB 20 - Set Vcomh deselect level 20:1306(~0.77xVcc), 34:1309(~0.78xVcc) +8D 14 - Charge Pump Setting 10:disable CP, 14:enable CP +20 00 - Set HORIZONTAL mode +AF - Display ON/OFF AE:off (sleep mode), AF:on' + if (_resetPin != '-') { + '_OLEDreset' _resetPin + } + if (9 == _displayType) { + local 'initCmd' 'A8,3F,D3,00,40,A1,C8,DA,12,81,F0,A4,A6,D5,70,D9,22,DB,34,8D,14,20,00,AF' + } else { + local 'initCmd' 'A8,3F,D3,00,40,A1,C8,DA,12,81,F0,A4,A6,D5,70,D9,22,DB,20,8D,14,20,00,AF' + } + '_sendCmd' initCmd +} + +to '_initLibrary' { + comment 'Sets all Library variables and initializes the display hardware. +It also initializes the virtual GDBuffer, and clears the display. +NOTE: +Displays supported: OLED1306 (0.96in) and OLED1309 (2.42"), selected via boolean position. +OLED1309 requires the connection of RESET pin to a digital pin. +Both displays are 128x64 pixels or 16x8 characters in size. +Make sure the character hex tables are \n (LF) terminated. +Otherwise, extra lines are added in between and it gets messed up. +eg: A: 00,7C,12,11,11,12,7C,00\n +Max i2c IO is 64 bytes: buffered writes need to be max that size - 16 x 64' + _comma = ('[data:unicodeString]' 44) + _eol = ('[data:unicodeString]' 10) + comment 'Col starts are in HEX' + _dataPrefix = ('[data:newByteArray]' 1 (hexToInt '40')) + comment 'There is no FF/255 in th cHexTBL. +this value is used to build the byteArray.' + _cDecTBL = ('[data:newByteArray]' 768 255) + _GDBuffer = ('[data:newByteArray]' 1024) + _textX = 0 + _textY = 0 + _delayGDUpd = (booleanConstant false) + '_initChars' + OLEDReady = (booleanConstant true) + '_OLEDsetDisplay' 'On' + repeat 2 { + setUserLED true + waitMillis 50 + setUserLED false + waitMillis 50 + } +} + +to '_process image data' image { + comment 'Processes the new hex image data format. +Each _imgHex gets added to _imgData in DEC byteArray format. +_byteCount keeps track of total bytes processed. +_imgWidth and _imgHeight (mod8) are dimensions.' + local '_ptr' 1 + comment '_imgData is not initialized yet.' + if (or (0 == _imgData) (not (isType _imgData 'byte array'))) { + _imgWidth = (hexToInt ('[data:copyFromTo]' image 1 2)) + _imgHeight = (hexToInt ('[data:copyFromTo]' image 3 4)) + image = ('[data:copyFromTo]' image 5) + comment 'If _imgHeight is partial byte, adjust to full byte' + if (not (0 == (_imgHeight % 8))) { + _imgHeight += (8 - (_imgHeight % 8)) + } + _imgData = ('[data:newByteArray]' ((_imgWidth * _imgHeight) / 8)) + } + for byte ('[data:range]' 1 (size image) 2) { + atPut (_byteCount + _ptr) _imgData (hexToInt ('[data:copyFromTo]' image byte (byte + 1))) + _ptr += 1 + } + _byteCount += (_ptr - 1) +} + +to '_sendCmd' cmdString { + comment 'Input is a comma sep. STRING. +MAKE SURE ALL INPUT PARAMETERS ARE HEX' + local '_cList' ('[data:split]' cmdString _comma) + local 'cmdPrefix' (hexToInt '80') + if ('i2c' == _comMode) { + for cmd _cList { + '[sensors:i2cWrite]' OLEDi2cAddr ('[data:asByteArray]' ('[data:makeList]' cmdPrefix (hexToInt cmd))) + } + } else { + '_SPIWriteCmd' + for cmd _cList { + spiSend (hexToInt cmd) + } + } +} + +to '_verifyXY' x y { + if (and (and (x >= 0) (x <= 127)) (and (y >= 0) (y <= 63))) { + return 0 + } else { + sayIt 'x or y value error:' ('[data:unicodeString]' 10) 'x:' x ' y:' y + stopTask + } +} + +to 'defer display updates' { + _delayGDUpd = (booleanConstant true) +} + diff --git a/README.md b/README.md index e5cfe46..ea7540e 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -MicroBlocks Library! \ No newline at end of file +# Spark Kit! + +[Spark](https://fablab.bh/spark/) is a course by FABLAB BH that teaches students the basics of electronics and coding using the Spark Kit and MicroBlocks. What’s cool is that students in the program also teach other students! + +## Microcontroller + + +## Issues and Solusions +