Paints a rotating FabLab Munich logo on an oscilloscope screen

Dependencies:   FastPWM mbed

main.cpp

Committer:
drayde
Date:
2015-06-23
Revision:
0:5276f16d6ac8

File content as of revision 0:5276f16d6ac8:

#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]);
            }
       }
    }
}