Andreas Kahler
/
OsciPaint
Paints a rotating FabLab Munich logo on an oscilloscope screen
Diff: main.cpp
- Revision:
- 0:5276f16d6ac8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jun 23 08:32:04 2015 +0000 @@ -0,0 +1,367 @@ +#include "mbed.h" +#include "FastPWM.h" + +#define min(x,y) ((x > y) ? y : x) +#define max(x,y) ((x > y) ? x : y) + +FastPWM pwmout1(p21); +FastPWM pwmout2(p22); +DigitalOut gnd(p23); +DigitalOut zout(p30); + + +const float waitTime = 0.000005f; +const float waitTimeOnOff = waitTime * 5; + +const uint16_t linesCount = 3; +uint16_t lines[3] = { 50, 58, 59 }; + +const uint16_t count = 50 + 58 + 59; +float tline[count*2] = { +48.369133f, 28.8248990f, +48.368286f, 39.8623760f, +48.351325f, 46.3102450f, +48.334335f, 52.7581170f, +49.475196f, 53.4183200f, +50.616059f, 54.0785220f, +53.243757f, 55.5576550f, +54.606233f, 56.1411410f, +57.114615f, 56.6511700f, +59.375927f, 56.5156330f, +60.874326f, 55.9204990f, +62.091060f, 55.0463890f, +63.381650f, 52.9297760f, +64.112835f, 49.9910160f, +64.245790f, 32.3980810f, +64.135779f, 15.2194990f, +61.394651f, 8.323464f, +56.287969f, 3.161953f, +53.549629f, 1.670959f, +50.809912f, 0.864901f, +48.551553f, 0.663871f, +46.319378f, 0.703653f, +46.319384f, 0.703653f, +41.771884f, 1.630293f, +37.661210f, 3.244895f, +25.652307f, 10.270239f, +10.447255f, 19.245676f, +6.857494f, 21.672420f, +4.501644f, 24.214656f, +2.165276f, 28.217320f, +1.003558f, 32.887381f, +0.753147f, 36.341157f, +0.721389f, 42.459346f, +0.739268f, 44.880336f, +0.757146f, 47.301322f, +0.937623f, 46.759876f, +1.118101f, 46.218430f, +2.914027f, 42.413677f, +5.642516f, 39.020793f, +7.916307f, 37.067662f, +12.748684f, 34.2152480f, +22.498228f, 28.6411190f, +32.483871f, 22.8936240f, +36.322240f, 20.7285960f, +38.208913f, 19.9188070f, +41.846881f, 19.3307290f, +44.771649f, 20.3007020f, +46.961058f, 22.6148930f, +48.222403f, 26.0716500f, +48.369133f, 28.8248990f, + +31.218976f, 43.621458f, +28.831117f, 44.931821f, +26.009916f, 46.631259f, +23.556446f, 49.026798f, +22.262607f, 51.745174f, +22.384654f, 54.559435f, +24.067583f, 57.178886f, +25.752292f, 58.675306f, +28.113957f, 60.172644f, +40.067016f, 67.088425f, +51.982667f, 74.028337f, +54.866337f, 75.620116f, +56.919580f, 76.396709f, +59.404296f, 76.966447f, +62.191090f, 77.081175f, +64.275877f, 77.036236f, +65.584705f, 76.841860f, +70.340268f, 75.182687f, +74.042962f, 72.548870f, +76.787694f, 68.775052f, +78.626446f, 63.868977f, +79.264536f, 60.552604f, +79.381633f, 56.203943f, +79.252152f, 38.311577f, +79.104273f, 25.613174f, +78.591456f, 22.154913f, +77.214888f, 18.660728f, +76.492625f, 17.328795f, +75.812292f, 16.259090f, +72.476318f, 12.892882f, +67.620877f, 9.627348f, +65.809337f, 8.594852f, +63.213505f, 7.108777f, +60.964386f, 5.831115f, +59.986438f, 5.299696f, +59.980032f, 5.353375f, +60.066736f, 5.482429f, +60.066708f, 5.482429f, +60.306470f, 5.764849f, +60.668044f, 6.187257f, +61.959456f, 7.984005f, +63.130244f, 10.042883f, +63.985197f, 12.073989f, +64.609554f, 14.235729f, +64.757758f, 14.858139f, +64.905961f, 15.480547f, +64.890439f, 23.990692f, +64.874916f, 32.500838f, +64.824032f, 45.300649f, +64.736554f, 50.304271f, +63.087355f, 54.874838f, +59.623785f, 57.154567f, +57.634136f, 57.346340f, +55.508274f, 57.100453f, +51.885523f, 55.531368f, +35.685767f, 46.165152f, +32.571639f, 44.368667f, +31.218976f, 43.621458f, + +42.495038f, 36.333182f, +47.729039f, 33.339953f, +47.729039f, 31.792619f, +47.729039f, 30.245284f, +47.625985f, 26.717286f, +47.164493f, 24.643814f, +46.478075f, 23.109990f, +45.520018f, 21.850785f, +43.226395f, 20.277306f, +40.550203f, 20.025078f, +37.608442f, 20.881826f, +32.431660f, 23.694032f, +22.173406f, 29.600607f, +12.539847f, 35.112122f, +8.374712f, 37.564272f, +6.497140f, 39.076506f, +2.228777f, 45.204719f, +1.118711f, 48.737560f, +0.740503f, 52.468628f, +1.260493f, 55.998071f, +2.775410f, 59.505567f, +8.519716f, 65.985043f, +10.531177f, 67.378454f, +15.567997f, 70.274288f, +21.383807f, 73.564774f, +28.254901f, 77.453774f, +39.292928f, 83.643126f, +42.354181f, 84.917021f, +46.105708f, 85.540547f, +49.712607f, 85.446400f, +54.147520f, 84.133871f, +59.058497f, 81.676193f, +60.921011f, 80.589179f, +63.492770f, 79.108980f, +65.646859f, 77.865843f, +66.505190f, 77.348785f, +66.096247f, 77.412454f, +65.203488f, 77.565531f, +62.315773f, 77.788296f, +59.386050f, 77.614347f, +56.239433f, 76.880110f, +53.680922f, 75.794481f, +51.913305f, 74.763871f, +48.616599f, 72.838788f, +38.314969f, 66.847449f, +28.321931f, 61.061033f, +26.512461f, 59.978255f, +25.293782f, 59.179132f, +23.881259f, 57.943434f, +22.714720f, 56.673829f, +22.121329f, 55.670882f, +21.667488f, 54.594427f, +21.527371f, 53.052012f, +21.682559f, 51.350046f, +23.171367f, 48.408091f, +25.935771f, 45.874712f, +29.616191f, 43.719389f, +37.261038f, 39.326411f, +42.495038f, 36.333182f, +}; + +uint16_t line[count*2]; + +uint16_t xPos, yPos; +int32_t offsetx; +int32_t offsety; + +void lineFromTo(int32_t tx1, int32_t ty1, int32_t tx2, int32_t ty2) +{ + int32_t yd = (ty2 - ty1); + int32_t xd = (tx2 - tx1); + + if (abs(xd) > abs(yd)) + { + int32_t yinc = yd / ((tx2-tx1) >> 16); + int32_t y = ty1; + uint16_t x = tx1 >> 16; + uint16_t x2 = tx2 >> 16; + + if (xd == 0) + return; + + while (1) + { + pwmout1.pulsewidth_ticks(x); + pwmout2.pulsewidth_ticks((uint16_t)(y >> 16)); + wait(waitTime); + if (x == x2) + break; + if (xd > 0) { + y += yinc; + x++; + } else { + y -= yinc; + x--; + } + } + } + else + { + int32_t xinc = xd / ((ty2-ty1) >> 16); + int32_t x = tx1; + uint16_t y = ty1 >> 16; + uint16_t y2 = ty2 >> 16; + + if (yd == 0) + return; + + while (1) + { + pwmout1.pulsewidth_ticks((uint16_t)(x >> 16)); + pwmout2.pulsewidth_ticks(y); + wait(waitTime); + if (y == y2) + break; + if (yd > 0) { + x += xinc; + y++; + } else { + x -= xinc; + y--; + } + } + } +} + + +void lineWithRotation(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) +{ + // calculate with 32 bits to have the necessary precision + int32_t tx1 = x1 << 16; + int32_t ty1 = y1 << 16; + int32_t tx2 = x2 << 16; + int32_t ty2 = y2 << 16; + + const int32_t horizon = 100; + ty1 += (tx1 - (127 << 16)) * offsety / 127 * (y1 - horizon) / 127; + ty2 += (tx2 - (127 << 16)) * offsety / 127 * (y2 - horizon) / 127; + + tx1 = (127 << 16) + (tx1 - (127 << 16)) * offsetx / 127; + tx2 = (127 << 16) + (tx2 - (127 << 16)) * offsetx / 127; + + lineFromTo(tx1, ty1, tx2, ty2); +} + + +void setRotation(float rotation) +{ + offsetx = (int32_t)(127 * sin(rotation)); + offsety = (int32_t)(30 * cos(rotation)); +} + +void moveTo(uint16_t x, uint16_t y) +{ + lineWithRotation(xPos, yPos, x, y); + xPos = x; + yPos = y; +} + + +int main() +{ + gnd = 0; + zout = 1; + pwmout1.period_ticks(256); + pwmout2.period_ticks(256); + + + /* + // test signal + while (1) + { + pwmout1 = 0.5f; + pwmout2 = 0.5f; + zout = zout ? 0 : 1; + } + */ + + float minx = 999999; + float maxx = -999999; + float miny = 999999; + float maxy = -999999; + + for (uint16_t i = 0; i<count; i++) + { + float x = tline[i*2]; + float y = tline[i*2+1]; + minx = min(minx, x); + miny = min(miny, y); + maxx = max(maxx, x); + maxy = max(maxy, y); + } + + float dx = maxx - minx; + float dy = maxy - miny; + + float margin = 8.0f; // do not use full range (needed for perspective correction) + float multy = 254.9f - 2 * margin; + float offy = 0.01f + margin; + float multx = multy; + float offx = offy; + + for (uint16_t i = 0; i<count; i++) + { + float x = tline[i*2]; + float y = tline[i*2+1]; + uint16_t xint = (uint16_t)((x - minx) / dx * multx + offx); + uint16_t yint = (uint16_t)((y - miny) / dy * multy + offy); + line[i*2] = xint; + line[i*2+1] = yint; + } + + float rotation = 0; + + while(1) + { + setRotation(rotation); + rotation += 0.025f; + + uint16_t pos = 0; + for (uint16_t index=0; index<linesCount; index++) + { + wait(waitTimeOnOff); + zout = 1; //off + wait(waitTime); + moveTo(line[pos*2], line[pos*2+1]); + wait(waitTime); + zout = 0; // on! + wait(waitTimeOnOff); + pos++; + for (uint16_t i = 1; i<lines[index]; i++,pos++) + { + moveTo(line[pos*2], line[pos*2+1]); + } + } + } +} \ No newline at end of file