module main author 'Turgut Guneysu' version 1 9 depends 'OLED Graphics' description 'Demonstrates the OLED Library use. Works with Lib v1.9 ' variables S1 S2 _msg1 _msg2 _msg3 _picNo debug S3 spec ' ' 'OLEDDemo' 'OLEDDemo' spec ' ' 'dataLoop' 'dataLoop _ _ _ _' 'auto auto auto auto' '10' '10' '10' '10' spec ' ' 'CTRLPanel' 'CTRLPanel' spec ' ' 'Contrast1-4' 'Contrast1-4' spec ' ' 'MBLogo and Title' 'MBLogo and Title' spec ' ' 'OLEDCharset' 'OLEDCharset' spec ' ' 'animatedSprites' 'animatedSprites' spec ' ' 'drawCircles' 'drawCircles' spec ' ' 'drawCirclesMatrix' 'drawCirclesMatrix' spec ' ' 'drawLines' 'drawLines' spec ' ' 'drawRectangles' 'drawRectangles' spec ' ' 'mbitCharSet' 'mbitCharSet' spec ' ' 'lineDrawBT' 'lineDrawBT' spec ' ' 'lineDrawLR' 'lineDrawLR' spec ' ' 'lineDrawRL' 'lineDrawRL' spec ' ' 'lineDrawTB' 'lineDrawTB' spec 'r' '_makeSpriteINT' '_makeSpriteINT _' 'auto' '10' spec ' ' 'OLEDreveal' 'reveal delay _' 'auto' 1 spec ' ' '_dispByte' 'disp byte value _ row _ col _' 'auto auto auto' 1 1 1 to CTRLPanel { comment 'Demo of Control Panel with 3 live values updated Touch value is updated as an icon.' OLEDclear local 'Toff1' ('[data:split]' '3C,42,81,81,81,81,81,81' ',') for i (size Toff1) { atPut i Toff1 (hexToInt (at i Toff1)) } local 'Toff2' ('[data:split]' '81,81,81,81,81,81,42,3C' ',') for i (size Toff2) { atPut i Toff2 (hexToInt (at i Toff2)) } local 'Ton1' ('[data:split]' '3C,42,81,99,99,81,81,81' ',') for i (size Ton1) { atPut i Ton1 (hexToInt (at i Ton1)) } local 'Ton2' ('[data:split]' '81,81,81,99,99,81,42,3C' ',') for i (size Ton2) { atPut i Ton2 (hexToInt (at i Ton2)) } OLEDwrite ' Control Panel ' 0 0 true OLEDwrite 'Light:' 0 16 false OLEDwrite 'Temp:' 0 32 false OLEDwrite 'Touch:' 0 48 false dataLoop Toff1 Toff2 Ton1 Ton2 } to 'Contrast1-4' { comment 'Adjust CONTRAST 1 - 4' for i 4 { OLEDwrite ('[data:join]' ' ' i ' ') 48 24 false OLEDcontrast i OLEDshowGDBuffer waitMillis 1000 } OLEDcontrast 1 } to 'MBLogo and Title' { comment 'MicroBlocks Logo & Title' OLEDclear BunnyPIC OLEDdrawImage _imgData 0 0 OLEDwrite 'Micro Blocks Is GREAT!!!' 56 0 false OLEDshowGDBuffer } to OLEDCharset { OLEDclear OLEDcontrast 1 OLEDwrite '_CHARACTER SET_' 0 0 false OLEDwrite _cTABLE 2 0 false OLEDshowGDBuffer } to OLEDDemo { comment 'Demo program to show various display features.' '_initCheck' OLEDclear for i 56 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'Micro Blocks Is GREAT!!!' 48 (7 + i) false OLEDshowGDBuffer } for i 56 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'Micro Blocks Is GREAT!!!' 48 (60 - i) false OLEDshowGDBuffer } BunnyPIC for i 63 { OLEDdrawImage _imgData 0 (63 - i) } OLEDsetVideo 'Inverse' waitMillis 2000 OLEDsetVideo 'Normal' } to OLEDreveal delay { comment 'Display _GDBuffer content random bytes at a time with delay.' '_clearDisplay' local 'randNums' (newList 1024) local 'base' 128 repeatUntil (-1 == ('[data:find]' 0 randNums)) { local 'num' (random 0 1023) if (0 == (at (num + 1) randNums)) { atPut (num + 1) randNums 1 '_dispByte' (at (num + 1) _GDBuffer) (num / base) (num % base) waitMillis delay } } } to '_dispByte' value row col { comment 'Copies a byte from _GDBuffer to Display Values are DEC.' local '_cmdPrefix' ('[data:newByteArray]' 1 (hexToInt 'C0')) '_sendCmd' ('[data:join]' '22' _comma ('_dec2hex' row) _comma ('_dec2hex' row) _comma '21' _comma ('_dec2hex' col) _comma ('_dec2hex' col)) if (_comMode == 'i2c') { '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _cmdPrefix ('[data:newByteArray]' 1 value)) } else { '_SPIWriteData' spiSend value } } to '_makeSpriteINT' 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: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 animatedSprites { comment 'Make 2 Sprites and Loop them on display in horizontal and vertical directions. Upon collision, display explosion pattern.' OLEDclear S1 = (OLEDmakeImage 7829959) S2 = (OLEDmakeImage 10948740) S3 = (OLEDmakeImage 22506965) sendBroadcast 'loop' } to dataLoop t1 t2 t3 t4 { forever { 'defer display updates' OLEDwrite ('[data:join]' '' ('[display:lightLevel]') ' ') 64 16 false OLEDwrite ('[data:join]' '' ('[sensors:temperature]') ' ') 64 32 false if ('logo touched') { OLEDdrawImage t3 64 48 OLEDdrawImage t4 72 48 } else { OLEDdrawImage t1 64 48 OLEDdrawImage t2 72 48 } OLEDshowGDBuffer waitMillis 250 } } to drawCircles { comment 'Concentric circles, out, in' OLEDclear OLEDcontrast 1 for i 64 { if ((i % 2) == 0) { 'defer display updates' OLEDdrawCircle 64 32 i false OLEDshowGDBuffer } } for i 64 { if (((65 - i) % 2) == 0) { 'defer display updates' OLEDdrawCircle 64 32 (65 - i) true OLEDshowGDBuffer } } } to drawCirclesMatrix { comment 'Draw Circles across the display Center every 10 pixels, Radius = 3' OLEDclear OLEDcontrast 1 _delayGDUpd = (booleanConstant false) for y 63 { if ((y % 8) == 0) {for x 127 { if ((x % 10) == 0) {OLEDdrawCircle x y 3 false} } } } OLEDshowGDBuffer } to drawLines { comment 'Lines from 0,0 to opposite y-range Place OLEDShowGDBuffer into loops (slow) or at the end (fast)' OLEDclear OLEDcontrast 1 for i 64 { if ((i % 2) == 1) { 'defer display updates' OLEDdrawLine 0 0 127 (i - 1) false OLEDshowGDBuffer } } comment 'Lines from 127,0 to origin y-range' for i 64 { if ((i % 2) == 1) { 'defer display updates' OLEDdrawLine 127 0 0 (i - 1) false OLEDshowGDBuffer } } } to drawRectangles { comment 'Concentric Rectangles, in, in' OLEDclear OLEDcontrast 1 for i 28 { if (((i - 1) % 2) == 0) { 'defer display updates' OLEDdrawRect (i - 1) (i - 1) (127 - (i * 2)) (63 - (i * 2)) false 3 } OLEDshowGDBuffer } for i 28 { if (((i - 1) % 2) == 0) { 'defer display updates' OLEDdrawRect (i - 1) (i - 1) (127 - (i * 2)) (63 - (i * 2)) true 3 } OLEDshowGDBuffer } } to lineDrawBT { for y 42 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'MicroBlocks' 32 (50 - y) false OLEDdrawRect 25 ((50 - y) - 7) 101 19 false 3 OLEDdrawRect 27 ((50 - y) - 5) 97 15 false 3 OLEDshowGDBuffer } waitMillis 50 } to lineDrawLR { for x 24 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'MicroBlocks' (8 + x) 50 false OLEDdrawRect ((8 + x) - 7) (50 - 7) 101 19 false 3 OLEDdrawRect ((8 + x) - 5) (50 - 5) 97 15 false 3 OLEDshowGDBuffer } waitMillis 50 } to lineDrawRL { for x 24 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'MicroBlocks' (32 - x) 8 false OLEDdrawRect ((32 - x) - 7) 1 101 19 false 3 OLEDdrawRect ((32 - x) - 5) 3 97 15 false 3 OLEDshowGDBuffer } } to lineDrawTB { for y 42 { _GDBuffer = ('[data:newByteArray]' 1024) 'defer display updates' OLEDwrite 'MicroBlocks' 8 (8 + y) false OLEDdrawRect 1 ((8 + y) - 7) 101 19 false 3 OLEDdrawRect 3 ((8 + y) - 5) 97 15 false 3 OLEDshowGDBuffer } waitMillis 50 } to mbitCharSet { comment 'Using Sprite capability to draw the micro:bit character set of the LED Library Uses 5x5 matrix of letter instead of 8x8.' OLEDclear local 'string' 'Using Sprite capability to draw the 5x5 micro:bit character set: ' OLEDwrite string 0 0 false OLEDshowGDBuffer for c string { OLEDdrawImage ('_makeSpriteINT' ('[display:mbShapeForLetter]' ('[data:unicodeAt]' 1 c))) _textX (_textY + 5) OLEDshowGDBuffer _textX += 5 if (_textX >= 123) { _textY += 6 _textX = 0 } } } script 90 40 { comment 'Please make sure to modify the OLEDInit blocks according to your display type and connectivity, as well as provide the I2C address, and other pin info as it pertains to your environment.' } script 90 120 { whenStarted comment 'SPI ' OLEDInit_SPI 'OLED_2.42in' 16 8 OLEDcontrast 3 OLEDwrite 'Hello!' 0 0 false OLEDDemo } script 492 155 { comment 'I2C' OLEDInit_I2C 'OLED_0.96in' '3C' 0 false OLEDcontrast 1 OLEDwrite 'Hello!' 0 0 false } script 88 341 { whenButtonPressed 'A' comment 'Display the character and linedraw set tables' OLEDCharset } script 482 343 { whenButtonPressed 'B' comment 'Using Sprite capability to draw the micro:bit character set of the LED Library Uses 5x5 matrix of letter instead of 8x8.' mbitCharSet } script 75 503 { comment '====================== LIBRARY USE SAMPLES ARE PROVIDED BELOW ========================== To run, click on each examples comment block.' } script 93 627 { comment 'Full line of text' OLEDclear OLEDwrite '0123456789ABCDEF' 0 0 false } script 93 760 { comment 'Adjust CONTRAST 1 - 4' 'Contrast1-4' } script 93 837 { comment 'MicroBlocks Logo & Title' 'MBLogo and Title' } script 95 909 { comment 'REVERSE VIDEO Test' OLEDclear OLEDwrite ' TESTING INVERSE VIDEO ' 0 0 true } script 98 1085 { comment 'Text framed with rectangle and animated' lineDrawTB lineDrawLR lineDrawBT lineDrawRL } script 90 1327 { comment 'Lines from 0,0 to opposite y-range Place OLEDShowGDBuffer into loops (slow) or at the end (fast)' drawLines } script 90 1428 { comment 'Draw Circles across the display Center every 10 pixels, Radius = 3' drawCirclesMatrix } script 90 1528 { comment 'Concentric circles, out, in' drawCircles } script 90 1598 { comment 'Concentric Rectangles, in, in' drawRectangles } script 90 1668 { comment '====================== SPRITE SPECIFIC EXAMPLES PROVIDED BELOW (Make use of the GDBuffer) ==========================' } script 90 1735 { comment 'Make 2 Sprites and Loop them on display in horizontal and vertical directions. Upon collision, display explosion pattern.' animatedSprites } script 624 1740 { whenBroadcastReceived 'loop' forever { local 's2R' 59 local 's2C' 56 for c 120 { s2R = (maximum 1 (s2R - 5)) if (s2R < 4) { if (and (c > (s2C - 5)) (c < (s2C + 5))) {repeat 3 { OLEDdrawImage S3 s2C 0 waitMillis 200 OLEDdrawImage ('[data:newByteArray]' 5) s2C 0 waitMillis 200 } } s2R = 59 } OLEDdrawImage S1 c 0 OLEDdrawImage S2 56 s2R waitMillis 50 OLEDclear } } } script 87 1848 { comment 'Demo of Control Panel with 3 live values updated Touch value is updated as an icon.' CTRLPanel } script 87 1952 { comment 'Picture of Jens & John Reveals GDBuffer onto Display by random pixels.' OLEDclear OLEDcontrast 1 JJPIC OLEDdrawImage _imgData 0 0 waitMillis 2000 '_clearDisplay' OLEDreveal 0 waitMillis 4000 '_clearDisplay' } script 90 2277 { comment 'AV Control Panel Displays equalizer bars with a picture show of MB team. On SPI displays, adjust speed 1000 - 10000000.' local 'picBMPs' ('[data:makeList]') JMPIC '[data:addLast]' _imgData picBMPs BRPIC '[data:addLast]' _imgData picBMPs JMoPIC '[data:addLast]' _imgData picBMPs KGPIC '[data:addLast]' _imgData picBMPs OLEDclear OLEDcontrast 1 MPPIC OLEDdrawImage _imgData 0 0 for i 300 { 'defer display updates' if ((i % 25) == 0) { _imgWidth = 32 _imgHeight = 32 _picNo = (random 1 4) OLEDdrawImage (at _picNo picBMPs) 90 8 } local 'c' 0 repeat 9 { c += 8 local 'r' 40 repeat (random 1 4) { r += -8 _imgWidth = 7 _imgHeight = 8 OLEDdrawImage ('[data:newByteArray]' 7 119) c r } } OLEDshowGDBuffer local 'c' 0 r = 40 repeat 9 { c += 8 local 'r' 40 'defer display updates' for i 4 { OLEDdrawImage ('[data:newByteArray]' 7) c (r - (8 * i)) } OLEDshowGDBuffer } } } module '32BR' author unknown version 1 0 description '' variables _imgBMPTbl _imgBMPTbl2 spec ' ' 'BR1' 'BR1' spec ' ' 'BRPIC' 'BRPIC' to BR1 { comment 'Place this under P1' local '_imgHex' '20203C1F1F071B1B1F1B07070707070703010101010303030703030F0B0D1D157171DE00001CF0C8F8F8F8F8F8FCFCFCFEFEFEFF7E7F3F3F3F7E7CF8F8F0C00000A980818080C0030F1D3D79F8F0F8DD7F7F7FBC3C34842CBC3E3FFFFFFF7F000011010200000000000000000001033022030604080000020401010181C0E0F07C3E' '_process image data' _imgHex _imgHex = '' } to BRPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 32 _imgHeight = 32 _byteCount = 0 BR1 } module '32JM' author unknown version 1 0 description '' variables _imgBMPTbl _imgBMPTbl2 spec ' ' 'JM1' 'JM1' spec ' ' 'JMPIC' 'JMPIC' to JM1 { comment 'Place this under P1' local '_imgHex' '20207FFFDF0F8F03010C0F8FCFCFCF9F1F7FFFFF9FDFDFDFFFFFFFFFFFFFFEF8F0E0E03FBF030000284031E0C828140400040F9FDF9CFCBC7CFDFFFFFFFFFBFFFFFFC4C080E0000000010255AA010000000303830387878FDEFBFFFFFFFFFFFF7F1FFFFFFFF1C00000000000000000000008250A5D3F7F7FFFFFFFFF7F1FBF330000' '_process image data' _imgHex _imgHex = '' } to JMPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 32 _imgHeight = 32 _byteCount = 0 JM1 } module '32JMo' author unknown version 1 0 description '' variables _imgBMPTbl _imgBMPTbl2 spec ' ' 'JMo1' 'JMo1' spec ' ' 'JMoPIC' 'JMoPIC' to JMo1 { comment 'Place this under P1' local '_imgHex' '20200000000000000000009CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFBFFFFFFFFFFF80080000000000006078B8B5B0F0F0F0F3FFFFFFFEFFBFFFFFFFFFFFFFF1F1FFFFEF8E3DEF800083EFFFD3E1C1C8A8880E4FF9FDFFFEF7FFFFFFFFFFFFFA080FFFFFFFFFFFFFEB0E30D130F1F1F3C78F9F9FFFFFFFFFFFFFFFFFFFFFF03FFFF' '_process image data' _imgHex _imgHex = '' } to JMoPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 32 _imgHeight = 32 _byteCount = 0 JMo1 } module '32KG' author unknown version 1 0 description '' variables _imgBMPTbl _imgBMPTbl2 spec ' ' 'KG1' 'KG1' spec ' ' 'KGPIC' 'KGPIC' to KG1 { comment 'Place this under P1' local '_imgHex' '2020FFFF3F3F1FFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFEF180000000000000030E1D0FFF2CE0FEFFFFFFFBFBF1FBFBFFFFFF0F077BFFFFC6CC8E000000000000000000FF01FFFFFFFFFFFFFFBFBF3B3F3B9370503BFF7F3F070F0000000000000000FCFFFE7001FFFFFFFFBF7F7F3F7D0D1E0B0F0707000000000000000000000000' '_process image data' _imgHex _imgHex = '' } to KGPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 32 _imgHeight = 32 _byteCount = 0 KG1 } module 'Basic Sensors' Input author MicroBlocks version 1 1 tags tilt acceleration light sensor choices accelerometerRange '1' '2' '4' '8' description 'Provides blocks to read tilt in the three axes, acceleration, temperature and light level. Many boards come with this particular set of sensors, such as the micro:bit, the Circuit Playground Express, the Calliope or the Citilab ED1.' spec 'r' '[sensors:tiltX]' 'tilt x' spec 'r' '[sensors:tiltY]' 'tilt y' spec 'r' '[sensors:tiltZ]' 'tilt z' spec 'r' '[sensors:acceleration]' 'acceleration' spec 'r' '[display:lightLevel]' 'light level' spec 'r' '[sensors:temperature]' 'temperature (C)' spec ' ' '_setAccelRange' 'set acceleration range _ g = 100' 'menu.accelerometerRange' '1' to '_setAccelRange' n { '[sensors:setAccelerometerRange]' (0 + n) } module BunnyPic author 'Turgut Guneysu' version 1 0 description 'Uses the new image format.' variables _imgBMPTbl spec ' ' 'B1' 'B1' spec ' ' 'BunnyPIC' 'BunnyPIC' to B1 { comment 'Place this under P1' local '_imgHex' '2A400000000000C0E070180C0E06E3FFDFE330180C06060203E3FF1F03000000000000000000000000000000000000F8FF030000000000F0FF0FFFE100000000000080FF1F00000000000000000000000000000000000000001FFFE00000000000FF7F001FFFC000000000C0FF3F00000000000000000000000000000000000000000000019FFC600000070706060603030000000003030303030206060C0C18183060C08000000000000000E0F81E07010000000000000000000000000000000000000000000000000000000001030F7CF00000007EFF0100000000000000000000000000E0E0E000000000000070707000000000000000000000FFFF000000071F78E08000000000000008181030606040C0C2C6FEFEC6C0C06060301018080080C0F03C0F010000000000000003070E0C183030606060C0C0C0C0C3C7C6C7C3C24363603030181C0C0603010000000000' '_process image data' _imgHex _imgHex = '' } to BunnyPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 42 _imgHeight = 64 _byteCount = 0 B1 } module JensJohnPic author unknown version 1 0 description '' variables _imgBMPTbl spec ' ' 'JJ1' 'JJ1' spec ' ' 'JJ2' 'JJ2' spec ' ' 'JJPIC' 'JJPIC' to JJ1 { comment 'Place this under P1' local '_imgHex' '6840FFFFFFFFFFFF7F1F1F1F0D0D0000000001000000000000000080C0C1E0E0E0E1C0818101010303070F7FFFFFFFFFFFFF00FFDFBFBFBF7F7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFEFEFEFCFCF8F8B08000000000000000000000000000007F3F0F0301000000000000000000000000000080C0E0F0F8FEFFFFFFFFFFFFFFFFFFFFFFFCF8F0C0001CFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFF3FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFCF8F080000000000000000000000000000000000000000000000000000000021FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFFF00FFFF3F7FFFFF9FE32101000001037373737171717373675F7FFFFFFFFFF77F7F3F3F7B77FFFFFFFFFFFFFFFFFFFFFFFEFCF8F080000000FFFCE080000000000000000000000000000C0E0F4F4F4F5F3F3F3FFFFFFFFFFFFF7F1B1FDFFFFFFFFFFFFFFFFFFFFFFF00FFFFC0F8FFFF3F03000020F8F0F0FCF8F8FCFC7C3C2603000E1F1FFFFF3F3EFEFEFEFEFEFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE080' '_process image data' _imgHex _imgHex = '' } to JJ2 { comment 'Place this under P2' local '_imgHex' 'FFFFFFFFE08000000080000000000000000000000001000000000000010FFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF0100FFFFFF03010300000000000103071FFFFFFF071D000010181E1E3E3FBFBF3F3F7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFBFFFFFFFFFFFFFCF0C08F300000000000003EBE3E0E0602000000000080C07F0F0F87F7F3E3777F7FF7EFFFFFFFFFFFB800FFFFFFFCF8F0FEFF000000000000000F3FFF0E000000000008F0F8F8F8F8F0F0F0F0FDFFFFFFFFFFFFFFFFFFFFFF0F030103030300FFFFFFFFFFFFFFFFFFFFFFFFFFFEF0C080000000011E3C3C38000000030607E7F7FFFFFFFFFFFCFEFFFFFFFFFFFFFFFF0F0700FFFFFFFFFFFFFFF8E0000000000000000001000000000006073F7F7FFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F0FFF3100000000000000FFFFFFFF7FFFFFBFFFFFFFFFBFFFFBF3FBFCF000000000000000000000060F1F7FFFFFFFFFFFFFFFFFFFFFFFFFFF7F0FF0FF00FFFFFFFFFFFFFFFFFF7F7C783C10800000000000000000000000000000000080C1CFFFFFFFFFFFFFDF0000003FF800000000000000FFFF' '_process image data' _imgHex _imgHex = '' } to JJPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 104 _imgHeight = 64 _byteCount = 0 JJ1 JJ2 } module 'LED Display' Output author MicroBlocks version 1 2 tags pixel matrix led tft description 'Display primitives for the 5x5 LED display on the BBC micro:bit, Calliope mini and M5Atom Matrix. Boards with TFT displays (such as the Citilab ED1 or the M5Stack family) also support this primitives in a simulated "fat pixel" display.' variables _stop_scrolling_text spec ' ' '[display:mbDisplay]' 'display _' 'microbitDisplay' 15237440 spec ' ' '[display:mbDisplayOff]' 'clear display' spec ' ' '[display:mbPlot]' 'plot x _ y _' 'num num' 3 3 spec ' ' '[display:mbUnplot]' 'unplot x _ y _' 'num num' 3 3 spec ' ' 'displayCharacter' 'display character _' 'str' 'A' spec ' ' 'scroll_text' 'scroll text _ : pausing _ ms' 'str num' 'HELLO ROSA!' 100 spec ' ' 'stopScrollingText' 'stop scrolling' to displayCharacter s { s = ('[data:join]' '' s) if ((size s) == 0) { '[display:mbDisplayOff]' return 0 } '[display:mbDrawShape]' ('[display:mbShapeForLetter]' (at 1 s)) } to scroll_text text optionalDelay { text = ('[data:join]' text '') delay = 100 if ((pushArgCount) > 1) { delay = optionalDelay } _stop_scrolling_text = (booleanConstant false) local 'length' (size text) for position ((length * 6) + 6) { if _stop_scrolling_text {return 0} for i length { '[display:mbDrawShape]' ('[display:mbShapeForLetter]' ('[data:unicodeAt]' i text)) (((i * 6) + 2) - position) 1 } waitMillis delay } } to stopScrollingText { _stop_scrolling_text = (booleanConstant true) waitMillis 10 '[display:mbDisplayOff]' } module MusicPanel author unknown version 1 0 description '' variables _imgBMPTbl _imgBMPTbl2 spec ' ' 'MP1' 'MP1' spec ' ' 'MP2' 'MP2' spec ' ' 'MP3' 'MP3' spec ' ' 'MPPIC' 'MPPIC' to MP1 { comment 'Place this under P1' local '_imgHex' '8040FC04F41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414F404F4141414141414141414141414141414141414141414141414141414141414141414141414141414F404FCFF00FF0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FF000000000100000000000000000000000000000000000000000000000000000000000100000000FF00FFFF00FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FF000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FF' '_process image data' _imgHex _imgHex = '' } to MP2 { comment 'Place this under P2' local '_imgHex' 'FF00FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FF000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FFFF00FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00FF000000008000000000000000000000000000000000000000000000000000000000000080000000FF00FF1F1097959494949494949494949494949494949414141494949494949494949494949494949494949414141494949494949494949494949494949494949414141414949494949494949494949494949494949497101714949494949494949494949494949494949494141414949494949494949494949494949494949497101F' '_process image data' _imgHex _imgHex = '' } to MP3 { comment 'Place this under P3' local '_imgHex' '0000FF00FEFE40E0F8FCFEFEE0F8FCFEFE0000FF000000FF00FEFEFCFCF8F8F8F0F0F0E0E0404000FF000000FF0000FEFEFEFEFEFEFEFEFEFEFEFE0000FF00000000FF000000FEFEFEFE0000FEFEFEFE000000FF000000FF0000FEFEFCF8E0FEFEFCF8E040FEFE00FF000000FF0008080810E0C020100808BE1C080000FF000000003F202F2F202023272F2F2023272F2F20203F0000003F202F2F272723232321212120202020203F0000003F20202F2F2F2F2F2F2F2F2F2F2F2F20203F000000003F2020202F2F2F2F20202F2F2F2F2020203F0000003F20202F2F2723202F2F272320202F2F203F0000003F20222222212020212222222F272220203F0000' '_process image data' _imgHex _imgHex = '' } to MPPIC { comment 'Place this under PIC' _imgData = 0 _imgWidth = 128 _imgHeight = 64 _byteCount = 0 MP1 MP2 MP3 } module 'OLED Graphics' Output author 'Turgut Guneysu' version 1 9 choices DispTypeMenu 'OLED_0.96in' 'OLED_2.42in' choices OnOffMenu On Off choices VideoMenu Inverse Normal choices ModeMenu Horizontal Vertical 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 - image draw bug fix - stack overflow fix ' variables OLEDReady OLEDi2cAddr _GDBuffer _begCol _begRow _cDecTBL _comma _cTABLE _comMode _dcPin _delayGDUpd _displayType _endCol _endRow _eol _resetPin _textX _textY _dataPrefix timer _byteCount _imgData _imgWidth _imgHeight spec ' ' 'OLEDInit_I2C' 'initialize i2c _ address(hex) _ reset pin# _ flip _' 'str.DispTypeMenu auto auto 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 ' ' '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 ' ' '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 ' ' 'OLEDshowGDBuffer' 'show display buffer' 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)) if (dispType == 'OLED_0.96in') { _displayType = 6 _resetPin = resetPin } else { _displayType = 9 _resetPin = resetPin } '_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 (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 '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)) } } if (not _delayGDUpd) { OLEDshowGDBuffer } } to OLEDdrawImage image x y { comment '_imgHeight has to be mod8 or 1-8' 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) { 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) { if (not _delayGDUpd) {OLEDshowGDBuffer} return 0 } } waitMillis 0 } y += 8 } 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' 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)) { if (not _delayGDUpd) {OLEDshowGDBuffer} done = (booleanConstant true) } e2 = (2 * err) if (e2 >= dy) { err += dy x0 += sx } if (e2 <= dx) { err += dx y0 += sy } } } 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 '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 } if (not _delayGDUpd) { OLEDshowGDBuffer } } 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 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 1024 Locations 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' if (and (and (x >= 0) (x <= 127)) (and (y >= 0) (y <= 63))) { local 'page#' (y / 8) local 'pagePixel#' (y % 8) local 'GDIndex' ((x + ((y / 8) * 128)) + 1) local 'byteBMP' (at GDIndex _GDBuffer) if (not erase) { byteBMP = (byteBMP | (1 << pagePixel#)) } else { comment 'Turn off n th bit' byteBMP = (byteBMP & ('~' (1 << pagePixel#))) } atPut GDIndex _GDBuffer byteBMP if (not _delayGDUpd) { OLEDshowGDBuffer } } } 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 61 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' '_verifyXY' x y local 'origX' x 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 if (not _delayGDUpd) { OLEDshowGDBuffer } 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 } 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 _begCol = 0 _endCol = 127 _begRow = 0 _endRow = 7 } 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' local 'clearBuff' ('[data:newByteArray]' 60 0) if ('i2c' == _comMode) { repeat 17 { '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _dataPrefix clearBuff) } '[sensors:i2cWrite]' OLEDi2cAddr ('[data:join]' _dataPrefix clearBuff) } 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)) } } if (not _delayGDUpd) { OLEDshowGDBuffer } } to '_dec2hex' num { comment 'Fast version w/o inversion. (~115uSecs)' local '_hexTbl' '0123456789ABCDEF' local 'hexNum' '' repeatUntil (num < 0) { if ((num / 16) != 0) { hexNum = ('[data:join]' (at ((num % 16) + 1) _hexTbl) hexNum) num = (num / 16) } else { hexNum = ('[data:join]' (at ((num % 16) + 1) _hexTbl) hexNum) num = -1 } } comment 'If not half-byte length, pad it.' repeatUntil (((size hexNum) % 4) == 0) { hexNum = ('[data:join]' '0' 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 [A0] C0 - Scan Direction C0:0-127, C8:127-0 [C0] DA 12 - COM pin hw config 02:double-high 12:normal bits 81 7F - Set contrast 00-FF (00:dimmest, FF:brightest) 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,7F,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,7F,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 _begRow = 0 _begCol = 0 _endRow = 7 _endCol = 127 _delayGDUpd = (booleanConstant false) '_initChars' OLEDReady = (booleanConstant true) '_OLEDsetDisplay' 'On' setUserLED true waitMillis 1000 setUserLED false } 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 ((size image) / 2) { atPut (_byteCount + byte) _imgData (hexToInt ('[data:copyFromTo]' image _ptr (_ptr + 1))) _ptr += 2 } _byteCount += byte } 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) } module 'Touch (microbit)' Input author MicroBlocks version 1 0 description 'Capacitive touch sensing for micro:bit v1 and v2.' variables _lowCount _isHigh spec 'r' 'touch' 'pin _ touched : threshold _' 'num num' 0 0 spec 'r' 'logo touched' 'logo touched' to 'logo touched' { if ((boardType) == 'micro:bit') {return (booleanConstant false)} return (touch 26 0) } to touch pin optionalThreshold { comment 'Discharge pin' digitalWriteOp pin false local 'threshold' 0 if ((pushArgCount) > 1) { threshold = optionalThreshold } if (threshold <= 0) { comment 'Select threshold based on board type' if ((boardType) == 'micro:bit') { threshold = 9 } else { threshold = 15 } } local 'n' 0 comment 'Wait for pin to become high, incrementing n' repeatUntil (digitalReadOp pin) { n += 1 if (n >= threshold) { comment 'Long charging time means pin is touched' _isHigh = (booleanConstant true) _lowCount = 0 digitalWriteOp pin false return _isHigh } } digitalWriteOp touchPin false if (_isHigh == 0) { _isHigh = (booleanConstant false) } comment 'count is < threshold so pin not touched' if _isHigh { comment 'Require several low counts in a row to exit "isHigh" state to avoid jitter.' _lowCount += 1 if (_lowCount > 2) { _isHigh = (booleanConstant false) } } return _isHigh }