pxt-ev3
Version:
LEGO MINDSTORMS EV3 for Microsoft MakeCode
1 lines • 5.27 MB
JSON
{"id":"ev3","platformid":"linux","nickname":"lego","name":"LEGO® MINDSTORMS® Education EV3","title":"LEGO® MINDSTORMS® Education EV3 - Blocks / Javascript editor","description":"A Blocks / JavaScript code editor for the LEGO® MINDSTORMS® Education EV3.","corepkg":"ev3","bundleddirs":["libs/base","libs/core","libs/music","libs/color-sensor","libs/touch-sensor","libs/ultrasonic-sensor","libs/infrared-sensor","libs/gyro-sensor","libs/nxt-light-sensor","libs/screen","libs/ev3","libs/storage","libs/broadcast"],"simulator":{"autoRun":true,"autoRunLight":false,"aspectRatio":0.5,"parts":false,"enableTrace":true,"boardDefinition":{"visual":"ev3"}},"cloud":{"workspace":false,"packages":true,"sharing":true,"publishing":true,"importing":true,"preferredPackages":[],"githubPackages":true,"cloudProviders":{"github":{}}},"compile":{"isNative":true,"useUF2":true,"useELF":true,"hasHex":true,"deployDrives":"EV3","deployFileMarker":"INFO_UF2.TXT","driveName":"EV3","flashCodeAlign":256,"floatingPoint":true,"taggedInts":true,"stackAlign":2,"gc":true,"nativeType":"thumb","switches":{},"jsRefCounting":false,"utf8":true},"serial":{"vendorId":"0x0694","productId":"0x0005","rawHID":true,"useEditor":true,"log":true},"runtime":{"mathBlocks":true,"loopsBlocks":true,"logicBlocks":true,"variablesBlocks":true,"textBlocks":true,"listsBlocks":true,"functionBlocks":true,"onStartNamespace":"loops","onStartWeight":100,"onStartColor":"#58AB41","pauseUntilBlock":{"category":"loops"},"breakBlock":true,"continueBlock":true,"bannedCategories":[]},"compileService":{"buildEngine":"dockermake","dockerImage":"pext/ev3:zlib","serviceId":"ev3"},"appTheme":{"accentColor":"#0089BF","logoWide":true,"logoUrl":"https://education.lego.com/","logo":"@cdnUrl@/blob/327f1c59e56127be2439ec6e715d1f7904d6da93/static/lego_education_logo.png","docsLogo":"@cdnUrl@/blob/327f1c59e56127be2439ec6e715d1f7904d6da93/static/lego_education_logo.png","portraitLogo":"@cdnUrl@/blob/327f1c59e56127be2439ec6e715d1f7904d6da93/static/lego_education_logo.png","cardLogo":"@cdnUrl@/blob/4800c370dcc589501253dbfe7027df3b9f3ca883/static/icons/android-chrome-192x192.png","appLogo":"@cdnUrl@/blob/4800c370dcc589501253dbfe7027df3b9f3ca883/static/icons/android-chrome-192x192.png","organization":"Microsoft MakeCode","organizationUrl":"https://makecode.com/org","organizationLogo":"@cdnUrl@/blob/bfd3fb263a38f1f21688867cf570e2d7a6b0d10d/static/Microsoft-logo_rgb_c-gray-square.png","organizationWideLogo":"@cdnUrl@/blob/0d6aa104d16c9bc53a708643814733dbf901c68d/static/Microsoft-logo_rgb_c-gray.png","homeUrl":"https://makecode.mindstorms.com/","embedUrl":"https://makecode.mindstorms.com/","privacyUrl":"https://go.microsoft.com/fwlink/?LinkId=521839","termsOfUseUrl":"https://go.microsoft.com/fwlink/?LinkID=206977","githubUrl":"https://github.com/Microsoft/pxt-ev3","driveDisplayName":"EV3","boardName":"LEGO® MINDSTORMS® Education EV3","copyrightText":"LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.","crowdinProject":"makecode","selectLanguage":true,"blocksCollapsing":true,"highContrast":true,"greenScreen":true,"availableLocales":["en","de","ja","ru","zh-CN","fr"],"lightToc":true,"docMenu":[{"name":"Support","path":"https://forum.makecode.com/"},{"name":"Troubleshoot","path":"https://makecode.mindstorms.com/troubleshoot"},{"name":"Blocks","path":"/blocks"},{"name":"JavaScript","path":"/javascript"},{"name":"Reference","path":"/reference"},{"name":"FIRST LEGO League","path":"/fll"}],"print":true,"showHomeScreen":true,"homeScreenHero":"@cdnUrl@/blob/5ae0215eb99642e6e826b06c5b9fa63289dc1589/static/hero.png","invertedMenu":false,"invertedMonaco":false,"monacoToolbox":true,"invertedToolbox":false,"coloredToolbox":true,"hasAudio":true,"saveInMenu":true,"usbHelp":[],"extendEditor":true,"extendFieldEditors":true,"scriptManager":true,"showProjectSettings":true,"debugger":true,"errorList":true,"workspaceSearch":true,"importExtensionFiles":true,"allowPackageExtensions":true,"addNewTypeScriptFile":true,"experiments":["alwaysGithubItemBlocks","blocksErrorList"],"blocklyOptions":{"grid":{"spacing":40,"length":2,"colour":"#ddd"}},"blockColors":{"loops":"#58AB41","logic":"#1E5AA8","math":"#7396C8","variables":"#B40000","text":"#FCAC00","advanced":"#969696","functions":"#19325A","arrays":"#901F76"},"blockIcons":{"loops":"","logic":"","math":"","variables":"","text":"","functions":"","arrays":"","search":"","addpackage":"","advancedcollapsed":"","advancedexpanded":""},"monacoColors":{"editor.background":"#f9f9f9"},"fileNameExclusiveFilter":"[^a-zA-Z0-9]","qrCode":true,"shareFinishedTutorials":true,"nameProjectFirst":true,"enableTrace":true,"githubEditor":true,"chooseLanguageRestrictionOnNewProject":true,"openProjectNewTab":true,"python":true,"TOC":[{"name":"About","path":"/about","subitems":[]},{"name":"FAQ","path":"/faq","subitems":[]},{"name":"Projects","path":"/projects","subitems":[]},{"name":"GitHub","path":"/github","subitems":[]},{"name":"Troubleshoot","path":"/troubleshoot","subitems":[]},{"name":"EV3 Manager","path":"https://ev3manager.education.lego.com/","subitems":[]},{"name":"Bluetooth","path":"/bluetooth","subitems":[]},{"name":"Forum","path":"https://forum.makecode.com","subitems":[]},{"name":"LEGO Support","path":"https://www.lego.com/service/","subitems":[]},{"name":"FIRST LEGO League","path":"/fll","subitems":[]},{"name":"Reference","path":"/reference","subitems":[{"name":"Brick","path":"/reference/brick","subitems":[{"name":"show string","path":"/reference/brick/show-string","subitems":[]},{"name":"show number","path":"/reference/brick/show-number","subitems":[]},{"name":"show value","path":"/reference/brick/show-value","subitems":[]},{"name":"show mood","path":"/reference/brick/show-mood","subitems":[]},{"name":"show image","path":"/reference/brick/show-image","subitems":[]},{"name":"clear screen","path":"/reference/brick/clear-screen","subitems":[]},{"name":"show ports","path":"/reference/brick/show-ports","subitems":[]},{"name":"on event","path":"/reference/brick/button/on-event","subitems":[]},{"name":"is pressed","path":"/reference/brick/button/is-pressed","subitems":[]},{"name":"was pressed","path":"/reference/brick/button/was-pressed","subitems":[]},{"name":"pause until","path":"/reference/brick/button/pause-until","subitems":[]},{"name":"set light","path":"/reference/brick/set-status-light","subitems":[]},{"name":"battery level","path":"/reference/brick/battery-level","subitems":[]}]},{"name":"Motors","path":"/reference/motors","subitems":[{"name":"run","path":"/reference/motors/motor/run","subitems":[]},{"name":"stop","path":"/reference/motors/motor/stop","subitems":[]},{"name":"reset","path":"/reference/motors/motor/reset","subitems":[]},{"name":"set brake","path":"/reference/motors/motor/set-brake","subitems":[]},{"name":"set inverted","path":"/reference/motors/motor/set-inverted","subitems":[]},{"name":"set regulated","path":"/reference/motors/motor/set-regulated","subitems":[]},{"name":"tank","path":"/reference/motors/synced/tank","subitems":[]},{"name":"steer","path":"/reference/motors/synced/steer","subitems":[]},{"name":"angle","path":"/reference/motors/motor/angle","subitems":[]},{"name":"speed","path":"/reference/motors/motor/speed","subitems":[]},{"name":"clear counts","path":"/reference/motors/motor/clear-counts","subitems":[]},{"name":"stop all motors","path":"/reference/motors/stop-all","subitems":[]}]},{"name":"Sensors","path":"/reference/sensors","subitems":[{"name":"Touch","path":"/reference/sensors/touch-sensor","subitems":[{"name":"on event","path":"/reference/sensors/touch-sensor/on-event","subitems":[]},{"name":"pause until","path":"/reference/sensors/touch-sensor/pause-until","subitems":[]},{"name":"is pressed","path":"/reference/sensors/touch-sensor/is-pressed","subitems":[]},{"name":"was pressed","path":"/reference/sensors/touch-sensor/was-pressed","subitems":[]}]},{"name":"Gyro","path":"/reference/sensors/gyro","subitems":[{"name":"angle","path":"/reference/sensors/gyro/angle","subitems":[]},{"name":"rate","path":"/reference/sensors/gyro/rate","subitems":[]},{"name":"reset","path":"/reference/sensors/gyro/reset","subitems":[]}]},{"name":"Ultrasonic","path":"/reference/sensors/ultrasonic","subitems":[{"name":"on event","path":"/reference/sensors/ultrasonic/on-event","subitems":[]},{"name":"distance","path":"/reference/sensors/ultrasonic/distance","subitems":[]},{"name":"pause until","path":"/reference/sensors/ultrasonic/pause-until","subitems":[]}]},{"name":"Infrared","path":"/reference/sensors/infrared","subitems":[{"name":"on event","path":"/reference/sensors/infrared/on-event","subitems":[]},{"name":"distance","path":"/reference/sensors/infrared/proximity","subitems":[]},{"name":"pause until","path":"/reference/sensors/infrared/pause-until","subitems":[]}]},{"name":"Infrared beacon","path":"/reference/sensors/beacon","subitems":[{"name":"on event","path":"/reference/sensors/beacon/on-event","subitems":[]},{"name":"pause until","path":"/reference/sensors/beacon/pause-until","subitems":[]},{"name":"is pressed","path":"/reference/sensors/beacon/is-pressed","subitems":[]},{"name":"was pressed","path":"/reference/sensors/beacon/was-pressed","subitems":[]},{"name":"set remote channel","path":"/reference/sensors/beacon/set-remote-channel","subitems":[]}]},{"name":"Color","path":"/reference/sensors/color-sensor","subitems":[{"name":"on color detected","path":"/reference/sensors/color-sensor/on-color-detected","subitems":[]},{"name":"pause until color detected","path":"/reference/sensors/color-sensor/pause-until-color-detected","subitems":[]},{"name":"on light detected","path":"/reference/sensors/color-sensor/on-light-detected","subitems":[]},{"name":"pause until light condition detected","path":"/reference/sensors/color-sensor/pause-until-light-detected","subitems":[]},{"name":"color","path":"/reference/sensors/color-sensor/color","subitems":[]},{"name":"light","path":"/reference/sensors/color-sensor/ambient-light","subitems":[]}]}]},{"name":"Music","path":"/reference/music","subitems":[{"name":"play sound effect","path":"/reference/music/play-sound-effect","subitems":[]},{"name":"play sound effect until done","path":"/reference/music/play-sound-effect-until-done","subitems":[]},{"name":"play tone","path":"/reference/music/play-tone","subitems":[]},{"name":"ring tone","path":"/reference/music/ring-tone","subitems":[]},{"name":"stop all sounds","path":"/reference/music/stop-all-sounds","subitems":[]},{"name":"rest","path":"/reference/music/rest","subitems":[]},{"name":"change tempo by","path":"/reference/music/change-tempo-by","subitems":[]},{"name":"set tempo","path":"/reference/music/set-tempo","subitems":[]},{"name":"note frequency","path":"/reference/music/note-frequency","subitems":[]},{"name":"beat","path":"/reference/music/beat","subitems":[]},{"name":"set volume","path":"/reference/music/set-volume","subitems":[]}]},{"name":"Control","path":"/reference/control","subitems":[{"name":"Timer","path":"/reference/control/timer","subitems":[{"name":"seconds","path":"/reference/control/timer/seconds","subitems":[]},{"name":"millis","path":"/reference/control/timer/millis","subitems":[]},{"name":"reset","path":"/reference/control/timer/reset","subitems":[]},{"name":"pause until","path":"/reference/control/timer/pause-until","subitems":[]}]}]},{"name":"Console","path":"/reference/console","subitems":[{"name":"log","path":"/reference/console/log","subitems":[]},{"name":"log value","path":"/reference/console/log-value","subitems":[]},{"name":"send to screen","path":"/reference/console/send-to-screen","subitems":[]}]}]},{"name":"Blocks","path":"/blocks","subitems":[{"name":"On Start","path":"/blocks/on-start","subitems":[]},{"name":"Loops","path":"/blocks/loops","subitems":[{"name":"repeat","path":"/blocks/loops/repeat","subitems":[]},{"name":"for","path":"/blocks/loops/for","subitems":[]},{"name":"while","path":"/blocks/loops/while","subitems":[]},{"name":"for of","path":"/blocks/loops/for-of","subitems":[]}]},{"name":"Logic","path":"/blocks/logic","subitems":[{"name":"if","path":"/blocks/logic/if","subitems":[]},{"name":"Boolean","path":"/blocks/logic/boolean","subitems":[]}]},{"name":"Variables","path":"/blocks/variables","subitems":[{"name":"assign","path":"/blocks/variables/assign","subitems":[]},{"name":"change var","path":"/blocks/variables/change","subitems":[]},{"name":"var","path":"/blocks/variables/var","subitems":[]}]},{"name":"Math","path":"/blocks/math","subitems":[]},{"name":"JavaScript blocks","path":"/blocks/javascript-blocks","subitems":[]},{"name":"Custom blocks","path":"/blocks/custom","subitems":[]}]},{"name":"Python","path":"/python","subitems":[{"name":"Calling","path":"/python/call","subitems":[]},{"name":"Sequencing","path":"/python/sequence","subitems":[]},{"name":"Variables","path":"/python/variables","subitems":[]},{"name":"Operators","path":"/python/operators","subitems":[]},{"name":"Statements","path":"/python/statements","subitems":[]},{"name":"Functions","path":"/python/functions","subitems":[]},{"name":"Classes","path":"/python/classes","subitems":[]}]},{"name":"JavaScript","path":"/javascript","subitems":[{"name":"Calling","path":"/javascript/call","subitems":[]},{"name":"Sequencing","path":"/javascript/sequence","subitems":[]},{"name":"Variables","path":"/javascript/variables","subitems":[]},{"name":"Operators","path":"/javascript/operators","subitems":[]},{"name":"Statements","path":"/javascript/statements","subitems":[]},{"name":"Functions","path":"/javascript/functions","subitems":[]},{"name":"Types","path":"/javascript/types","subitems":[]},{"name":"Classes","path":"/javascript/classes","subitems":[]},{"name":"Interfaces","path":"/javascript/interfaces","subitems":[]},{"name":"Generics","path":"/javascript/generics","subitems":[]}]},{"name":"Types","path":"/types","subitems":[{"name":"Number","path":"/types/number","subitems":[]},{"name":"String","path":"/types/string","subitems":[]},{"name":"Boolean","path":"/types/boolean","subitems":[]},{"name":"Array","path":"/types/array","subitems":[]},{"name":"Function","path":"/types/function","subitems":[]}]},{"name":"Developers","path":"","subitems":[{"name":"Command Line Interface","path":"/cli","subitems":[]},{"name":"Visual Studio Code support","path":"/code","subitems":[]},{"name":"Blocks Embed","path":"/blocks-embed","subitems":[]}]},{"name":"Getting Started","path":"/getting-started","subitems":[{"name":"Try","path":"/getting-started/try","subitems":[]},{"name":"Use","path":"/getting-started/use","subitems":[]}]},{"name":"Tutorials","path":"/tutorials","subitems":[{"name":"Wake Up!","path":"/tutorials/wake-up","subitems":[]},{"name":"Make An Animation","path":"/tutorials/make-an-animation","subitems":[]},{"name":"What Animal Am I?","path":"/tutorials/what-animal-am-i","subitems":[]},{"name":"Music Brick","path":"/tutorials/music-brick","subitems":[]},{"name":"Run Motors","path":"/tutorials/run-motors","subitems":[]},{"name":"Tank ZigZag","path":"/tutorials/tank-zigzag","subitems":[]},{"name":"Touch to Run","path":"/tutorials/touch-to-run","subitems":[]},{"name":"Touch Sensor Values","path":"/tutorials/touch-sensor-values","subitems":[]},{"name":"What Color?","path":"/tutorials/what-color","subitems":[]},{"name":"Line Following","path":"/tutorials/line-following","subitems":[]},{"name":"Red Light, Green Light","path":"/tutorials/redlight-greenlight","subitems":[]},{"name":"Reflected Light Measure","path":"/tutorials/reflected-light-measure","subitems":[]},{"name":"Reflected Light Calibration","path":"/tutorials/reflected-light-calibration","subitems":[]},{"name":"Object Near?","path":"/tutorials/object-near","subitems":[]},{"name":"Security Alert","path":"/tutorials/security-alert","subitems":[]}]},{"name":"Coding","path":"/coding","subitems":[{"name":"Autonomous Parking","path":"/coding/autonomous-parking","subitems":[]},{"name":"Object Detection","path":"/coding/object-detection","subitems":[]},{"name":"Line Detection","path":"/coding/line-detection","subitems":[]}]},{"name":"Design Engineering","path":"/design-engineering","subitems":[{"name":"Make It Move Without Wheels","path":"/design-engineering/make-it-move","subitems":[]},{"name":"Make It Smarter and Faster","path":"/design-engineering/make-it-smarter","subitems":[]},{"name":"Make a System that Communicates","path":"/design-engineering/make-it-communicate","subitems":[]}]},{"name":"Maker","path":"/maker","subitems":[{"name":"Make a Sound Machine","path":"/maker/sound-machine","subitems":[]},{"name":"Make a Security Gadget","path":"/maker/security-gadget","subitems":[]}]}],"id":"ev3","title":"LEGO® MINDSTORMS® Education EV3 - Blocks / Javascript editor","name":"LEGO® MINDSTORMS® Education EV3","description":"A Blocks / JavaScript code editor for the LEGO® MINDSTORMS® Education EV3.","htmlDocIncludes":{}},"ignoreDocsErrors":true,"uploadDocs":true,"versions":{"branch":"v1.4.41","tag":"v1.4.41","commits":"https://github.com/microsoft/pxt-ev3/commits/82439e598922900ad522dff819e596ede4a11dda","target":"1.4.41","pxt":"9.3.19"},"blocksprj":{"id":"blocksprj","config":{"name":"{0}","dependencies":{"ev3":"*"},"description":"","files":["main.blocks","main.ts","README.md"],"additionalFilePaths":[]},"files":{"README.md":"","main.blocks":"<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n <variables></variables>\n <block type=\"pxt-on-start\" x=\"0\" y=\"0\"></block>\n <block type=\"forever\" x=\"176\" y=\"0\"></block>\n</xml>","main.ts":"\n"}},"tsprj":{"id":"tsprj","config":{"name":"{0}","dependencies":{"ev3":"*"},"description":"","files":["main.ts","README.md"],"additionalFilePaths":[]},"files":{"README.md":"","main.ts":"\n"}},"bundledpkgs":{"base":{"README.md":"# base\n\nThe base library, shared by all C++ targets (not only Codal-based).\n\n\n","advmath.cpp":"#include \"pxtbase.h\"\n\nusing namespace std;\n\n#define SINGLE(op) return fromDouble(::op(toDouble(x)));\n\nnamespace Math_ {\n\n//%\nTNumber log2(TNumber x){SINGLE(log2)}\n//%\nTNumber exp(TNumber x){SINGLE(exp)}\n//%\nTNumber tanh(TNumber x){SINGLE(tanh)}\n//%\nTNumber sinh(TNumber x){SINGLE(sinh)}\n//%\nTNumber cosh(TNumber x){SINGLE(cosh)}\n//%\nTNumber atanh(TNumber x){SINGLE(atanh)}\n//%\nTNumber asinh(TNumber x){SINGLE(asinh)}\n//%\nTNumber acosh(TNumber x){SINGLE(acosh)}\n\n}","buffer.cpp":"#include \"pxtbase.h\"\n#include <limits.h>\n\nusing namespace std;\n\n//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte\nnamespace BufferMethods {\n//%\nuint8_t *getBytes(Buffer buf) {\n return buf->data;\n}\n\n//%\nint getByte(Buffer buf, int off) {\n if (buf && 0 <= off && off < buf->length)\n return buf->data[off];\n return 0;\n}\n\n//%\nvoid setByte(Buffer buf, int off, int v) {\n if (buf && 0 <= off && off < buf->length)\n buf->data[off] = v;\n}\n\n/**\n * Reads an unsigned byte at a particular location\n */\n//%\nint getUint8(Buffer buf, int off) {\n return getByte(buf, off);\n}\n\n/**\n * Returns false when the buffer can be written to.\n */\n//%\nbool isReadOnly(Buffer buf) {\n return buf->isReadOnly();\n}\n\n/**\n * Writes an unsigned byte at a particular location\n */\n//%\nvoid setUint8(Buffer buf, int off, int v) {\n setByte(buf, off, v);\n}\n\nint writeBuffer(Buffer buf, int dstOffset, Buffer src, int srcOffset = 0, int length = -1) {\n if (length < 0)\n length = src->length;\n\n if (srcOffset < 0 || dstOffset < 0 || dstOffset > buf->length)\n return -1;\n\n length = pxt::min(src->length - srcOffset, buf->length - dstOffset);\n\n if (length < 0)\n return -1;\n\n if (buf == src) {\n memmove(buf->data + dstOffset, src->data + srcOffset, length);\n } else {\n memcpy(buf->data + dstOffset, src->data + srcOffset, length);\n }\n\n return 0;\n}\n\n/**\n * Write a number in specified format in the buffer.\n */\n//%\nvoid setNumber(Buffer buf, NumberFormat format, int offset, TNumber value) {\n if (offset < 0)\n return;\n setNumberCore(buf->data + offset, buf->length - offset, format, value);\n}\n\n/**\n * Read a number in specified format from the buffer.\n */\n//%\nTNumber getNumber(Buffer buf, NumberFormat format, int offset) {\n if (offset < 0)\n return fromInt(0);\n return getNumberCore(buf->data + offset, buf->length - offset, format);\n}\n\n/** Returns the length of a Buffer object. */\n//% property\nint length(Buffer s) {\n return s->length;\n}\n\n/**\n * Fill (a fragment) of the buffer with given value.\n */\n//%\nvoid fill(Buffer buf, int value, int offset = 0, int length = -1) {\n if (offset < 0 || offset > buf->length)\n return; // DEVICE_INVALID_PARAMETER;\n if (length < 0)\n length = buf->length;\n length = pxt::min(length, buf->length - offset);\n memset(buf->data + offset, value, length);\n}\n\n/**\n * Return a copy of a fragment of a buffer.\n */\n//%\nBuffer slice(Buffer buf, int offset = 0, int length = -1) {\n offset = pxt::min((int)buf->length, offset);\n if (length < 0)\n length = buf->length;\n length = pxt::min(length, buf->length - offset);\n return mkBuffer(buf->data + offset, length);\n}\n\n/**\n * Shift buffer left in place, with zero padding.\n * @param offset number of bytes to shift; use negative value to shift right\n * @param start start offset in buffer. Default is 0.\n * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n * start. eg: -1\n */\n//%\nvoid shift(Buffer buf, int offset, int start = 0, int length = -1) {\n if (length < 0)\n length = buf->length - start;\n if (start < 0 || start + length > buf->length || start + length < start || length == 0 ||\n offset == 0 || offset == INT_MIN)\n return;\n if (offset <= -length || offset >= length) {\n fill(buf, 0);\n return;\n }\n\n uint8_t *data = buf->data + start;\n if (offset < 0) {\n offset = -offset;\n memmove(data + offset, data, length - offset);\n memset(data, 0, offset);\n } else {\n length = length - offset;\n memmove(data, data + offset, length);\n memset(data + length, 0, offset);\n }\n}\n\n/**\n * Convert a buffer to string assuming UTF8 encoding\n */\n//%\nString toString(Buffer buf) {\n return mkString((char *)buf->data, buf->length);\n}\n\n/**\n * Convert a buffer to its hexadecimal representation.\n */\n//%\nString toHex(Buffer buf) {\n const char *hex = \"0123456789abcdef\";\n auto res = mkStringCore(NULL, buf->length * 2);\n for (int i = 0; i < buf->length; ++i) {\n res->ascii.data[i << 1] = hex[buf->data[i] >> 4];\n res->ascii.data[(i << 1) + 1] = hex[buf->data[i] & 0xf];\n }\n return res;\n}\n\n/**\n * Rotate buffer left in place.\n * @param offset number of bytes to shift; use negative value to shift right\n * @param start start offset in buffer. Default is 0.\n * @param length number of elements in buffer. If negative, length is set as the buffer length minus\n * start. eg: -1\n */\n//%\nvoid rotate(Buffer buf, int offset, int start = 0, int length = -1) {\n if (length < 0)\n length = buf->length - start;\n if (start < 0 || start + length > buf->length || start + length < start || length == 0 ||\n offset == 0 || offset == INT_MIN)\n return;\n\n if (offset < 0)\n offset += length << 8; // try to make it positive\n offset %= length;\n if (offset < 0)\n offset += length;\n\n uint8_t *data = buf->data + start;\n\n uint8_t *n_first = data + offset;\n uint8_t *first = data;\n uint8_t *next = n_first;\n uint8_t *last = data + length;\n\n while (first != next) {\n uint8_t tmp = *first;\n *first++ = *next;\n *next++ = tmp;\n if (next == last) {\n next = n_first;\n } else if (first == n_first) {\n n_first = next;\n }\n }\n}\n\n/**\n * Write contents of `src` at `dstOffset` in current buffer.\n */\n//%\nvoid write(Buffer buf, int dstOffset, Buffer src) {\n // srcOff and length not supported, we only do up to 4 args :/\n writeBuffer(buf, dstOffset, src, 0, -1);\n}\n\n/**\n * Compute k-bit FNV-1 non-cryptographic hash of the buffer.\n */\n//%\nuint32_t hash(Buffer buf, int bits) {\n if (bits < 1)\n return 0;\n uint32_t h = hash_fnv1(buf->data, buf->length);\n if (bits >= 32)\n return h;\n else\n return ((h ^ (h >> bits)) & ((1 << bits) - 1));\n}\n\n} // namespace BufferMethods\n\nbool BoxedBuffer::isInstance(TValue v) {\n return getAnyVTable(v) == &buffer_vt;\n}\n\n// The functions below are deprecated in control namespace, but they are referenced\n// in Buffer namespaces via explicit shim=...\nnamespace control {\n/**\n * Create a new zero-initialized buffer.\n * @param size number of bytes in the buffer\n */\n//% deprecated=1\nBuffer createBuffer(int size) {\n return mkBuffer(NULL, size);\n}\n\n/**\n * Create a new buffer with UTF8-encoded string\n * @param str the string to put in the buffer\n */\n//% deprecated=1\nBuffer createBufferFromUTF8(String str) {\n#if PXT_UTF8\n auto sz = toRealUTF8(str, NULL);\n auto r = mkBuffer(NULL, sz);\n toRealUTF8(str, r->data);\n return r;\n#else\n return mkBuffer((const uint8_t *)str->getUTF8Data(), str->getUTF8Size());\n#endif\n}\n} // namespace control\n\nnamespace pxt {\nstatic int writeBytes(uint8_t *dst, uint8_t *src, int length, bool swapBytes, int szLeft) {\n if (szLeft < length) {\n return -1;\n }\n\n if (swapBytes) {\n uint8_t *p = dst + length;\n for (int i = 0; i < length; ++i)\n *--p = src[i];\n } else {\n if (length == 4 && ((uintptr_t)dst & 3) == 0)\n *(uint32_t *)dst = *(uint32_t *)src;\n else if (length == 2 && ((uintptr_t)dst & 1) == 0)\n *(uint16_t *)dst = *(uint16_t *)src;\n else\n memcpy(dst, src, length);\n }\n\n return 0;\n}\n\nstatic int readBytes(uint8_t *src, uint8_t *dst, int length, bool swapBytes, int szLeft) {\n if (szLeft < length) {\n memset(dst, 0, length);\n return -1;\n }\n\n if (swapBytes) {\n uint8_t *p = src + length;\n for (int i = 0; i < length; ++i)\n dst[i] = *--p;\n } else {\n if (length == 4 && ((uintptr_t)src & 3) == 0)\n *(uint32_t *)dst = *(uint32_t *)src;\n else if (length == 2 && ((uintptr_t)src & 1) == 0)\n *(uint16_t *)dst = *(uint16_t *)src;\n else\n memcpy(dst, src, length);\n }\n\n return 0;\n}\n\nvoid setNumberCore(uint8_t *buf, int szLeft, NumberFormat format, TNumber value) {\n int8_t i8;\n uint8_t u8;\n int16_t i16;\n uint16_t u16;\n int32_t i32;\n uint32_t u32;\n float f32;\n double f64;\n\n// Assume little endian\n#define WRITEBYTES(isz, swap, toInt) \\\n isz = toInt(value); \\\n writeBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \\\n break\n\n switch (format) {\n case NumberFormat::Int8LE:\n WRITEBYTES(i8, false, toInt);\n case NumberFormat::UInt8LE:\n WRITEBYTES(u8, false, toInt);\n case NumberFormat::Int16LE:\n WRITEBYTES(i16, false, toInt);\n case NumberFormat::UInt16LE:\n WRITEBYTES(u16, false, toInt);\n case NumberFormat::Int32LE:\n WRITEBYTES(i32, false, toInt);\n case NumberFormat::UInt32LE:\n WRITEBYTES(u32, false, toUInt);\n\n case NumberFormat::Int8BE:\n WRITEBYTES(i8, true, toInt);\n case NumberFormat::UInt8BE:\n WRITEBYTES(u8, true, toInt);\n case NumberFormat::Int16BE:\n WRITEBYTES(i16, true, toInt);\n case NumberFormat::UInt16BE:\n WRITEBYTES(u16, true, toInt);\n case NumberFormat::Int32BE:\n WRITEBYTES(i32, true, toInt);\n case NumberFormat::UInt32BE:\n WRITEBYTES(u32, true, toUInt);\n\n case NumberFormat::Float32LE:\n WRITEBYTES(f32, false, toFloat);\n case NumberFormat::Float32BE:\n WRITEBYTES(f32, true, toFloat);\n case NumberFormat::Float64LE:\n WRITEBYTES(f64, false, toDouble);\n case NumberFormat::Float64BE:\n WRITEBYTES(f64, true, toDouble);\n }\n}\n\nTNumber getNumberCore(uint8_t *buf, int szLeft, NumberFormat format) {\n int8_t i8;\n uint8_t u8;\n int16_t i16;\n uint16_t u16;\n int32_t i32;\n uint32_t u32;\n float f32;\n double f64;\n\n// Assume little endian\n#define READBYTES(isz, swap, conv) \\\n readBytes(buf, (uint8_t *)&isz, sizeof(isz), swap, szLeft); \\\n return conv(isz)\n\n switch (format) {\n case NumberFormat::Int8LE:\n READBYTES(i8, false, fromInt);\n case NumberFormat::UInt8LE:\n READBYTES(u8, false, fromInt);\n case NumberFormat::Int16LE:\n READBYTES(i16, false, fromInt);\n case NumberFormat::UInt16LE:\n READBYTES(u16, false, fromInt);\n case NumberFormat::Int32LE:\n READBYTES(i32, false, fromInt);\n case NumberFormat::UInt32LE:\n READBYTES(u32, false, fromUInt);\n\n case NumberFormat::Int8BE:\n READBYTES(i8, true, fromInt);\n case NumberFormat::UInt8BE:\n READBYTES(u8, true, fromInt);\n case NumberFormat::Int16BE:\n READBYTES(i16, true, fromInt);\n case NumberFormat::UInt16BE:\n READBYTES(u16, true, fromInt);\n case NumberFormat::Int32BE:\n READBYTES(i32, true, fromInt);\n case NumberFormat::UInt32BE:\n READBYTES(u32, true, fromUInt);\n\n case NumberFormat::Float32LE:\n READBYTES(f32, false, fromFloat);\n case NumberFormat::Float32BE:\n READBYTES(f32, true, fromFloat);\n case NumberFormat::Float64LE:\n READBYTES(f64, false, fromDouble);\n case NumberFormat::Float64BE:\n READBYTES(f64, true, fromDouble);\n }\n\n return 0;\n}\n} // namespace pxt\n","buffer.ts":"namespace pins {\n //% deprecated=1\n export function sizeOf(format: NumberFormat) {\n return Buffer.sizeOfNumberFormat(format)\n }\n\n //% deprecated=1\n export function createBufferFromArray(bytes: number[]) {\n return Buffer.fromArray(bytes)\n }\n\n //% deprecated=1\n export function packedSize(format: string) {\n return Buffer.packedSize(format)\n }\n\n //% deprecated=1\n export function packBuffer(format: string, nums: number[]) {\n return Buffer.pack(format, nums)\n }\n\n //% deprecated=1\n export function packIntoBuffer(format: string, buf: Buffer, offset: number, nums: number[]) {\n buf.packAt(offset, format, nums)\n }\n\n //% deprecated=1\n export function unpackBuffer(format: string, buf: Buffer, offset = 0) {\n return buf.unpack(format, offset)\n }\n\n //% deprecated=1\n export function concatBuffers(bufs: Buffer[]) {\n return Buffer.concat(bufs)\n }\n}\n\n// see http://msgpack.org/ for the spec\n// it currently only implements numbers and their sequances\n// once we handle any type and typeof expressions we can do more\n\nnamespace msgpack {\n function tagFormat(tag: number) {\n switch (tag) {\n case 0xCB: return NumberFormat.Float64BE\n case 0xCC: return NumberFormat.UInt8BE\n case 0xCD: return NumberFormat.UInt16BE\n case 0xCE: return NumberFormat.UInt32BE\n case 0xD0: return NumberFormat.Int8BE\n case 0xD1: return NumberFormat.Int16BE\n case 0xD2: return NumberFormat.Int32BE\n default:\n return null\n }\n }\n\n function packNumberCore(buf: Buffer, offset: number, num: number) {\n let tag = 0xCB\n if (num == (num << 0) || num == (num >>> 0)) {\n if (-31 <= num && num <= 127) {\n if (buf) buf[offset] = num\n return 1\n } else if (0 <= num) {\n if (num <= 0xff) {\n tag = 0xCC\n } else if (num <= 0xffff) {\n tag = 0xCD\n } else {\n tag = 0xCE\n }\n } else {\n if (-0x7f <= num) {\n tag = 0xD0\n } else if (-0x7fff <= num) {\n tag = 0xD1\n } else {\n tag = 0xD2\n }\n }\n }\n let fmt = tagFormat(tag)\n if (buf) {\n buf[offset] = tag\n buf.setNumber(fmt, offset + 1, num)\n }\n return pins.sizeOf(fmt) + 1\n }\n\n /**\n * Unpacks a buffer into a number array.\n */\n export function unpackNumberArray(buf: Buffer, offset = 0): number[] {\n let res: number[] = []\n\n while (offset < buf.length) {\n let fmt = tagFormat(buf[offset++])\n if (fmt === null) {\n let v = buf.getNumber(NumberFormat.Int8BE, offset - 1)\n if (-31 <= v && v <= 127)\n res.push(v)\n else\n return null\n } else {\n res.push(buf.getNumber(fmt, offset))\n offset += pins.sizeOf(fmt)\n }\n // padding at the end\n while (buf[offset] === 0xc1) offset++;\n }\n\n return res\n }\n\n /**\n * Pack a number array into a buffer.\n * @param nums the numbers to be packed\n */\n export function packNumberArray(nums: number[]): Buffer {\n let off = 0\n for (let n of nums) {\n off += packNumberCore(null, off, n)\n }\n let buf = Buffer.create(off)\n off = 0\n for (let n of nums) {\n off += packNumberCore(buf, off, n)\n }\n return buf\n }\n}\n\nnamespace helpers {\n export function bufferConcat(a: Buffer, b: Buffer) {\n const r = Buffer.create(a.length + b.length)\n r.write(0, a)\n r.write(a.length, b)\n return r\n }\n\n export function bufferEquals(l: Buffer, r: Buffer) {\n if (!l || !r) return !!l == !!r;\n if (l.length != r.length) return false;\n for (let i = 0; i < l.length; ++i) {\n if (l[i] != r[i])\n return false;\n }\n return true;\n }\n\n export function bufferIndexOf(a: Buffer, b: Buffer) {\n for (let i = 0; i <= a.length - b.length; ++i) {\n if (a[i] == b[0]) {\n let j = 0\n while (j < b.length) {\n if (a[i + j] != b[j])\n break\n j++\n }\n if (j >= b.length)\n return i\n }\n }\n return -1\n }\n\n export function bufferUnpack(buf: Buffer, format: string, offset?: number) {\n if (!offset) offset = 0\n let res: number[] = []\n Buffer.__packUnpackCore(format, res, buf, false, offset)\n return res\n }\n\n export function bufferPackAt(buf: Buffer, offset: number, format: string, nums: number[]) {\n Buffer.__packUnpackCore(format, nums, buf, true, offset)\n }\n\n export function bufferChunked(buf: Buffer, maxBytes: number) {\n if (buf.length <= maxBytes) return [buf]\n else {\n const r: Buffer[] = []\n for (let i = 0; i < buf.length; i += maxBytes)\n r.push(buf.slice(i, maxBytes))\n return r\n }\n }\n\n export function bufferToArray(buf: Buffer, format: NumberFormat) {\n const sz = Buffer.sizeOfNumberFormat(format)\n const len = buf.length - sz\n const r: number[] = []\n for (let i = 0; i <= len; i += sz)\n r.push(buf.getNumber(format, i))\n return r\n }\n\n export const _b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"\n export function bufferToBase64(buf: Buffer) {\n const len = buf.length\n let r = \"\"\n for (let i = 0; i < len; i += 3) {\n const x0 = buf[i]\n r += _b64[x0 >> 2]\n if (i + 1 >= len) {\n r += _b64[(x0 & 3) << 4] + \"==\"\n } else {\n const x1 = buf[i + 1]\n r += _b64[(x0 & 3) << 4 | (x1 >> 4)]\n if (i + 2 >= len) {\n r += _b64[(x1 & 15) << 2] + \"=\"\n } else {\n const x2 = buf[i + 2]\n r += _b64[(x1 & 15) << 2 | (x2 >> 6)]\n r += _b64[x2 & 63]\n }\n }\n }\n return r\n }\n}\n\ninterface Buffer {\n [index: number]: number;\n\n /**\n * Return concatenation of current buffer and the given buffer\n */\n //% helper=bufferConcat\n concat(other: Buffer): Buffer;\n\n /**\n * Return position of other buffer in current buffer\n */\n //% helper=bufferIndexOf\n indexOf(other: Buffer): number;\n\n /**\n * Reads numbers from the buffer according to the format\n */\n //% helper=bufferUnpack\n unpack(format: string, offset?: number): number[];\n\n /**\n * Writes numbers to the buffer according to the format\n */\n //% helper=bufferPackAt\n packAt(offset: number, format: string, nums: number[]): void;\n\n /**\n * Returns true if this and the other buffer hold the same data\n */\n //% helper=bufferEquals\n equals(other: Buffer): boolean;\n\n /**\n * Splits buffer into parts no larger than specified\n */\n //% helper=bufferChunked\n chunked(maxSize: number): Buffer[];\n\n /**\n * Read contents of buffer as an array in specified format\n */\n //% helper=bufferToArray\n toArray(format: NumberFormat): number[];\n\n /**\n * Convert buffer to ASCII base64 encoding.\n */\n //% helper=bufferToBase64\n toBase64(): string;\n\n // rest defined in buffer.cpp\n}\n\nnamespace Buffer {\n /**\n * Allocate a new buffer.\n * @param size number of bytes in the buffer\n */\n //% shim=control::createBuffer\n export declare function create(size: number): Buffer;\n\n /**\n * Create a new buffer, decoding a hex string\n */\n export function fromHex(hex: string) {\n const hexStr = \"0123456789abcdef\"\n const res = Buffer.create(hex.length >> 1)\n hex = hex.toLowerCase()\n for (let i = 0; i < hex.length; i += 2) {\n const p0 = hexStr.indexOf(hex.charAt(i))\n const p1 = hexStr.indexOf(hex.charAt(i + 1))\n if (p0 < 0 || p1 < 0)\n throw \"Invalid hex\"\n res[i >> 1] = (p0 << 4) | p1\n }\n return res\n }\n\n function b64Idx(c: string) {\n if (c === undefined || c == \"=\") return -1\n\n // handle base64url\n if (c == \"-\") return 62\n if (c == \"_\") return 63\n\n const r = helpers._b64.indexOf(c)\n if (r < 0)\n throw \"Invalid Base64\"\n return r\n }\n\n function fromBase64Core(trg: Buffer, b64: string) {\n const len = b64.length\n let dp = 0\n for (let i = 0; i < len; i += 4) {\n const x0 = b64Idx(b64[i])\n const x1 = b64Idx(b64[i + 1])\n const x2 = b64Idx(b64[i + 2])\n const x3 = b64Idx(b64[i + 3])\n if (x0 < 0 || x1 < 0) throw \"Invalid Base64\"\n if (trg)\n trg[dp] = (x0 << 2) | (x1 >> 4)\n dp++\n if (x2 >= 0) {\n if (trg)\n trg[dp] = (x1 << 4) | (x2 >> 2)\n dp++\n if (x3 >= 0) {\n if (trg)\n trg[dp] = (x2 << 6) | x3\n dp++\n }\n } else {\n if (x3 >= 0 || i + 4 < len)\n throw \"Invalid Base64\"\n }\n }\n return dp\n }\n\n /**\n * Create a new buffer, decoding a Base64 string\n */\n export function fromBase64(b64: string) {\n const sz = fromBase64Core(null, b64)\n const res = create(sz)\n fromBase64Core(res, b64)\n return res\n }\n\n /**\n * Create a new buffer from an UTF8-encoded string\n * @param str the string to put in the buffer\n */\n //% shim=control::createBufferFromUTF8\n export declare function fromUTF8(str: string): Buffer;\n\n function chunkLen(s: string, off: number, maxlen: number) {\n let L = Math.idiv(maxlen, 3)\n let R = maxlen\n\n if (fromUTF8(s.slice(off, off + R)).length <= maxlen)\n return R\n\n while (L < R) {\n const m = (L + R) >> 1\n if (m == L)\n break\n const ll = fromUTF8(s.slice(off, off + m)).length\n if (ll <= maxlen)\n L = m\n else\n R = m\n }\n\n return L\n }\n\n export function chunkedFromUTF8(str: string, maxBytes: number) {\n if (maxBytes < 3)\n throw \"Oops\"\n const chunks: Buffer[] = []\n let pos = 0\n while (pos < str.length) {\n const len = chunkLen(str, pos, maxBytes)\n chunks.push(fromUTF8(str.slice(pos, pos + len)))\n pos += len\n }\n return chunks\n }\n\n /**\n * Create a new buffer initialized to bytes from given array.\n * @param bytes data to initialize with\n */\n export function fromArray(bytes: number[]) {\n let buf = Buffer.create(bytes.length)\n for (let i = 0; i < bytes.length; ++i)\n buf[i] = bytes[i]\n return buf\n }\n\n /**\n * Concatenates all buffers in the list\n */\n export function concat(buffers: Buffer[]) {\n let len = 0\n for (let b of buffers)\n len += b.length\n const r = Buffer.create(len)\n len = 0\n for (let b of buffers) {\n r.write(len, b)\n len += b.length\n }\n return r\n }\n\n // Python-like packing, see https://docs.python.org/3/library/struct.html\n\n export function packedSize(format: string) {\n return __packUnpackCore(format, null, null, true)\n }\n\n export function pack(format: string, nums: number[]) {\n let buf = Buffer.create(packedSize(format))\n __packUnpackCore(format, nums, buf, true)\n return buf\n }\n\n function getFormat(pychar: string, isBig: boolean) {\n switch (pychar) {\n case 'B':\n return NumberFormat.UInt8LE\n case 'b':\n return NumberFormat.Int8LE\n case 'H':\n return isBig ? NumberFormat.UInt16BE : NumberFormat.UInt16LE\n case 'h':\n return isBig ? NumberFormat.Int16BE : NumberFormat.Int16LE\n case 'I':\n case 'L':\n return isBig ? NumberFormat.UInt32BE : NumberFormat.UInt32LE\n case 'i':\n case 'l':\n return isBig ? NumberFormat.Int32BE : NumberFormat.Int32LE\n case 'f':\n return isBig ? NumberFormat.Float32BE : NumberFormat.Float32LE\n case 'd':\n return isBig ? NumberFormat.Float64BE : NumberFormat.Float64LE\n default:\n return null as NumberFormat\n }\n }\n\n function isDigit(ch: string) {\n const code = ch.charCodeAt(0)\n return 0x30 <= code && code <= 0x39\n }\n\n export function __packUnpackCore(format: string, nums: number[], buf: Buffer, isPack: boolean, off = 0) {\n let isBig = false\n let idx = 0\n for (let i = 0; i < format.length; ++i) {\n switch (format[i]) {\n case ' ':\n case '<':\n case '=':\n isBig = false\n break\n case '>':\n case '!':\n isBig = true\n break\n default:\n const i0 = i\n while (isDigit(format[i])) i++\n let reps = 1\n if (i0 != i)\n reps = parseInt(format.slice(i0, i))\n if (format[i] == 'x')\n off += reps\n else\n while (reps--) {\n let fmt = getFormat(format[i], isBig)\n if (fmt === null) {\n control.fail(\"Unsupported format character: \" + format[i])\n } else {\n if (buf) {\n if (isPack)\n buf.setNumber(fmt, off, nums[idx++])\n else\n nums.push(buf.getNumber(fmt, off))\n }\n\n off += sizeOfNumberFormat(fmt)\n }\n }\n break\n }\n }\n return off\n }\n\n /**\n * Get the size in bytes of specified number format.\n */\n export function sizeOfNumberFormat(format: NumberFormat) {\n switch (format) {\n case NumberFormat.Int8LE:\n case NumberFormat.UInt8LE:\n case NumberFormat.Int8BE:\n case NumberFormat.UInt8BE:\n return 1;\n case NumberFormat.Int16LE:\n case NumberFormat.UInt16LE:\n case NumberFormat.Int16BE:\n case NumberFormat.UInt16BE:\n return 2;\n case NumberFormat.Int32LE:\n case NumberFormat.Int32BE:\n case NumberFormat.UInt32BE:\n case NumberFormat.UInt32LE:\n case NumberFormat.Float32BE:\n case NumberFormat.Float32LE:\n return 4;\n case NumberFormat.Float64BE:\n case NumberFormat.Float64LE:\n return 8;\n }\n return 0;\n }\n}\n","configkeys.h":"#ifndef __PXT_CONFIGKEYS_H\n#define __PXT_CONFIGKEYS_H\n\n// used by pins.cpp to mask off the pin name from any config\n// lower 16 pins of value are the pin name\n#define CFG_PIN_NAME_MSK 0x0000ffff\n// upper 16 bits of value is any configuration of the pin.\n#define CFG_PIN_CONFIG_MSK 0xffff0000\n\n// begin optional pin configurations\n#define CFG_PIN_CONFIG_ACTIVE_LO 0x10000\n\n\n#define CFG_MAGIC0 0x1e9e10f1\n#define CFG_MAGIC1 0x20227a79\n\n// these define keys for getConfig() function\n#define CFG_PIN_ACCELEROMETER_INT 1\n#define CFG_PIN_ACCELEROMETER_SCL 2\n#define CFG_PIN_ACCELEROMETER_SDA 3\n#define CFG_PIN_BTN_A 4\n#define CFG_PIN_BTN_B 5\n#define CFG_PIN_BTN_SLIDE 6\n#define CFG_PIN_DOTSTAR_CLOCK 7\n#define CFG_PIN_DOTSTAR_DATA 8\n#define CFG_PIN_FLASH_CS 9\n#define CFG_PIN_FLASH_MISO 10\n#define CFG_PIN_FLASH_MOSI 11\n#define CFG_PIN_FLASH_SCK 12\n#define CFG_PIN_LED 13\n#define CFG_PIN_LIGHT 14\n#define CFG_PIN_MICROPHONE 15\n#define CFG_PIN_MIC_CLOCK 16\n#define CFG_PIN_MIC_DATA 17\n#define CFG_PIN_MISO 18\n#define CFG_PIN_MOSI 19\n// the preferred pin to drive an external neopixel strip\n#define CFG_PIN_NEOPIXEL 20\n#define CFG_PIN_RX 21\n#define CFG_PIN_RXLED 22\n#define CFG_PIN_SCK 23\n#define CFG_PIN_SCL 24\n#define CFG_PIN_SDA 25\n#define CFG_PIN_SPEAKER_AMP 26\n#define CFG_PIN_TEMPERATURE 27\n#define CFG_PIN_TX 28\n#define CFG_PIN_TXLED 29\n#define CFG_PIN_IR_OUT 30\n#define CFG_PIN_IR_IN 31\n#define CFG_PIN_DISPLAY_SCK 32\n#define CFG_PIN_DISPLAY_MISO 33\n#define CFG_PIN_DISPLAY_MOSI 34\n#define CFG_PIN_DISPLAY_CS 35\n#define CFG_PIN_DISPLAY_DC 36\n#define CFG_DISPLAY_WIDTH 37\n#define CFG_DISPLAY_HEIGHT 38\n#define CFG_DISPLAY_CFG0 39\n#define CFG_DISPLAY_CFG1 40\n#define CFG_DISPLAY_CFG2 41\n#define CFG_DISPLAY_CFG3 42\n#define CFG_PIN_DISPLAY_RST 43\n#define CFG_PIN_DISPLAY_BL 44\n#define CFG_PIN_SERVO_1 45\n#define CFG_PIN_SERVO_2 46\n#define CFG_PIN_BTN_LEFT 47\n#define CFG_PIN_BTN_RIGHT 48\n#define CFG_PIN_BTN_UP 49\n#define CFG_PIN_BTN_DOWN 50\n#define CFG_PIN_BTN_MENU 51\n#define CFG_PIN_LED_R 52\n#define CFG_PIN_LED_G 53\n#define CFG_PIN_LED_B 54\n#define CFG_PIN_LED1 55\n#define CFG_PIN_LED2 56\n#define CFG_PIN_LED3 57\n#define CFG_PIN_LED4 58\n#define CFG_SPEAKER_VOLUME 59\n\n#define CFG_PIN_JACK_TX 60\n#define CFG_PIN_JACK_SENSE 61\n#define CFG_PIN_JACK_HPEN 62\n#define CFG_PIN_JACK_BZEN 63\n#define CFG_PIN_JACK_PWREN 64\n#define CFG_PIN_JACK_SND 65\n#define CFG_PIN_JACK_BUSLED 66\n#define CFG_PIN_JACK_COMMLED 67\n\n#define CFG_PIN_BTN_SOFT_RESET 69\n#define CFG_ACCELEROMETER_TYPE 70\n#define CFG_PIN_BTNMX_LATCH 71\n#define CFG_PIN_BTNMX_CLOCK 72\n#define CFG_PIN_BTNMX_DATA 73\n#define CFG_PIN_BTN_MENU2 74\n#define CFG_PIN_BATTSENSE 75\n#define CFG_PIN_VIBRATION 76\n#define CFG_PIN_PWREN 77\n#define CFG_DISPLAY_TYPE 78\n\n#define CFG_PIN_ROTARY_ENCODER_A 79\n#define CFG_PIN_ROTARY_ENCODER_B 80\n\n#define CFG_ACCELEROMETER_SPACE 81\n\n#define CFG_PIN_WIFI_MOSI 82\n#define CFG_PIN_WIFI_MISO 83\n#define CFG_PIN_WIFI_SCK 84\n#define CFG_PIN_WIFI_TX 85\n#define CFG_PIN_WIFI_RX 86\n#define CFG_PIN_WIFI_CS 87\n#define CFG_PIN_WIFI_BUSY 88\n#define CFG_PIN_WIFI_RESET 89\n#define CFG_PIN_WIFI_GPIO0 90\n#define CFG_PIN_WIFI_AT_TX 91\n#define CFG_PIN_WIFI_AT_RX 92\n\n#define CFG_PIN_USB_POWER 93\n\n// default I2C address\n#define ACCELEROMETER_TYPE_LIS3DH 0x32\n#define ACCELEROMETER_TYPE_LIS3DH_ALT 0x30\n#define ACCELEROMETER_TYPE_MMA