|
| 1 | +// This file provides a crude way to "drop in" user code to the eyes, |
| 2 | +// allowing concurrent operations without having to maintain a bunch of |
| 3 | +// special derivatives of the eye code (which is still undergoing a lot |
| 4 | +// of development). Just replace the source code contents of THIS TAB ONLY, |
| 5 | +// compile and upload to board. Shouldn't need to modify other eye code. |
| 6 | + |
| 7 | +// User globals can go here, recommend declaring as static, e.g.: |
| 8 | +// static int foo = 42; |
| 9 | + |
| 10 | +// Called once near the end of the setup() function. If your code requires |
| 11 | +// a lot of time to initialize, make periodic calls to yield() to keep the |
| 12 | +// USB mass storage filesystem alive. |
| 13 | +void user_setup(void) { |
| 14 | +} |
| 15 | + |
| 16 | +// Called periodically during eye animation. This is invoked in the |
| 17 | +// interval before starting drawing on the last eye (left eye on MONSTER |
| 18 | +// M4SK, sole eye on HalloWing M0) so it won't exacerbate visible tearing |
| 19 | +// in eye rendering. This is also SPI "quiet time" on the MONSTER M4SK so |
| 20 | +// it's OK to do I2C or other communication across the bridge. |
| 21 | +// This function BLOCKS, it does NOT multitask with the eye animation code, |
| 22 | +// and performance here will have a direct impact on overall refresh rates, |
| 23 | +// so keep it simple. Avoid loops (e.g. if animating something like a servo |
| 24 | +// or NeoPixels in response to some trigger) and instead rely on state |
| 25 | +// machines or similar. Additionally, calls to this function are NOT time- |
| 26 | +// constant -- eye rendering time can vary frame to frame, so animation or |
| 27 | +// other over-time operations won't look very good using simple +/- |
| 28 | +// increments, it's better to use millis() or micros() and work |
| 29 | +// algebraically with elapsed times instead. |
| 30 | +void user_loop(void) { |
| 31 | +/* |
| 32 | + Suppose we have a global bool "animating" (meaning something is in |
| 33 | + motion) and global uint32_t's "startTime" (the initial time at which |
| 34 | + something triggered movement) and "transitionTime" (the total time |
| 35 | + over which movement should occur, expressed in microseconds). |
| 36 | + Maybe it's servos, maybe NeoPixels, or something different altogether. |
| 37 | + This function might resemble something like (pseudocode): |
| 38 | +
|
| 39 | + if(!animating) { |
| 40 | + Not in motion, check sensor for trigger... |
| 41 | + if(read some sensor) { |
| 42 | + Motion is triggered! Record startTime, set transition |
| 43 | + to 1.5 seconds and set animating flag: |
| 44 | + startTime = micros(); |
| 45 | + transitionTime = 1500000; |
| 46 | + animating = true; |
| 47 | + No motion actually takes place yet, that will begin on |
| 48 | + the next pass through this function. |
| 49 | + } |
| 50 | + } else { |
| 51 | + Currently in motion, ignore trigger and move things instead... |
| 52 | + uint32_t elapsed = millis() - startTime; |
| 53 | + if(elapsed < transitionTime) { |
| 54 | + Part way through motion...how far along? |
| 55 | + float ratio = (float)elapsed / (float)transitionTime; |
| 56 | + Do something here based on ratio, 0.0 = start, 1.0 = end |
| 57 | + } else { |
| 58 | + End of motion reached. |
| 59 | + Take whatever steps here to move into final position (1.0), |
| 60 | + and then clear the "animating" flag: |
| 61 | + animating = false; |
| 62 | + } |
| 63 | + } |
| 64 | +*/ |
| 65 | +} |
0 commit comments