Fred Barnes / Mbed 2 deprecated co657_lcdplay

Dependencies:   C12832 FXOS8700CQ gfx3d mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  *  co657_lcdplay (main.cpp): playing with the MBED shield's LCD
00003  *  Copyright (C) 2015 Fred Barnes, University of Kent <frmb@kent.ac.uk>
00004  */
00005 
00006 #include "mbed.h"
00007 #include "C12832.h"
00008 #include "FXOS8700CQ.h"
00009 
00010 #include "gfx3d.h"
00011 #include "g3d_textures.h"
00012 
00013 // #define BENCHMARK
00014 
00015 /* some global objects */
00016 Serial host (USBTX, USBRX);
00017 
00018 C12832 shld_lcd (D11, D13, D12, D7, D10);                   /* LCD on the shield (128x32) */
00019 
00020 FXOS8700CQ fxos (PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1);     /* On-board accelerometer: SDA, SCL, (addr << 1) */
00021 
00022 InterruptIn sw2_int (PTC6);                                 /* SW2 (also unused interrupt for FXOS8700CQ) */
00023 InterruptIn fxos_int2 (PTC13);                              /* should just be the Data-Ready interrupt */
00024 InterruptIn sw3_int (PTA4);                                 /* switch SW3 */
00025 
00026 InterruptIn joy_up (PTB10);
00027 InterruptIn joy_down (PTB11);
00028 InterruptIn joy_left (PTC11);
00029 InterruptIn joy_right (PTC10);
00030 InterruptIn joy_fire (PTB23);
00031 
00032 #define FRAME_RATE_FPS      (40)                            /* how fast we want it to go */
00033 #define FRAME_RATE_US       (1000000 / FRAME_RATE_FPS)
00034 Ticker frametimer;                                          /* timer that will be used to update frames and whatnot */
00035 
00036 AnalogIn shld_pot1 (A0);
00037 AnalogIn shld_pot2 (A1);
00038 
00039 
00040 #ifdef BENCHMARK
00041 Timer perftimer;
00042 #endif
00043 
00044 #define PFLAG_TIMER         (0x01)                          /* next frame please */
00045 #define PFLAG_FXOS          (0x02)                          /* accel/magno data ready */
00046 #define PFLAG_JOY           (0x04)                          /* joystick activity */
00047 
00048 #define JOY_NONE            (0x00)
00049 #define JOY_UP              (0x01)
00050 #define JOY_DOWN            (0x02)
00051 #define JOY_LEFT            (0x04)
00052 #define JOY_RIGHT           (0x08)
00053 #define JOY_FIRE            (0x10)
00054 
00055 #define JOY_ANGLE_ADVANCE   (2)                             /* how many 8-bit-degrees */
00056 
00057 static volatile uint8_t pflags = 0x00;                      /* program flags */
00058 static volatile uint8_t joybits = 0x00;                     /* joystick bits */
00059 
00060 #define TXBUF_WIDTH         (256)
00061 static uint8_t ltxbuf[TXBUF_WIDTH * 4];                     /* a 256x32 buffer that holds 8 32x32 textures, organised as 4-byte strips L-to-R */
00062 
00063 
00064 /*
00065  *  assorted interrupt handlers, mostly just setting/clearing bits.
00066  *  FXOS read-ready interrupt, button triggers (pulled high but not SW2 on my board).
00067  *  Interrupt handler for frame-timeout (bang out frame, compute next).
00068  *  Interrupt handlers for joystick up/down/etc. (pulled to ground).
00069  *  Crushed up because MBED's editor doesn't fold yet.
00070  */
00071 static void trigger_fxos_int2 (void)        { pflags |= PFLAG_FXOS; }
00072 static void trigger_sw2_int (void)          { return; }
00073 static void trigger_sw3_int (void)          { return; }
00074 static void trigger_frametimer (void)       { pflags |= PFLAG_TIMER; }
00075 static void trigger_joy_up_rise (void)      { joybits |= JOY_UP;    pflags |= PFLAG_JOY; }
00076 static void trigger_joy_up_fall (void)      { joybits &= ~JOY_UP;   pflags |= PFLAG_JOY; }
00077 static void trigger_joy_down_rise (void)    { joybits |= JOY_DOWN;  pflags |= PFLAG_JOY; }
00078 static void trigger_joy_down_fall (void)    { joybits &= ~JOY_DOWN; pflags |= PFLAG_JOY; }
00079 static void trigger_joy_left_rise (void)    { joybits |= JOY_LEFT;  pflags |= PFLAG_JOY; }
00080 static void trigger_joy_left_fall (void)    { joybits &= ~JOY_LEFT; pflags |= PFLAG_JOY; }
00081 static void trigger_joy_right_rise (void)   { joybits |= JOY_RIGHT; pflags |= PFLAG_JOY; }
00082 static void trigger_joy_right_fall (void)   { joybits &= ~JOY_RIGHT;pflags |= PFLAG_JOY; }
00083 static void trigger_joy_fire_rise (void)    { joybits |= JOY_FIRE;  pflags |= PFLAG_JOY; }
00084 static void trigger_joy_fire_fall (void)    { joybits &= ~JOY_FIRE; pflags |= PFLAG_JOY; }
00085 
00086 
00087 
00088 /*
00089  *  dumps the global accelerometer/magnetomer reading to the serial-port "host"
00090  */
00091 void print_reading (FXOSData_t *p)
00092 {
00093     host.printf ("A X:%5d Y:%5d Z:%5d   M X:%5d Y:%5d Z:%5d\r\n",
00094             p->s.acc_x, p->s.acc_y, p->s.acc_z, p->s.mag_x, p->s.mag_y, p->s.mag_z);
00095 }
00096 
00097 
00098 static char *scrolly_message = "  ...  Welcome to the wonderful world of MBED and CO657 ...       ";
00099 
00100 
00101 /*
00102  *  some grot for handling scrolling text
00103  */
00104 static void scroll_text_update (int *firstch, int *xdelta, const char *str)
00105 {
00106     int xoff = *xdelta;
00107     int fch = *firstch;
00108     int hcnt, ccnt, lxoff, hxoff;
00109     
00110     /* see how many characters starting with fch will fit into the buffer (allow overrun) */
00111     for (hcnt=0; (str[fch + hcnt] != '\0') && (xoff < (TXBUF_WIDTH >> 1)); hcnt++) {
00112         xoff += gfx3d_font04b_char_dpw (str[fch + hcnt]);
00113     }
00114     hxoff = xoff;
00115     for (ccnt=hcnt; (str[fch + ccnt] != '\0') && (xoff < TXBUF_WIDTH); ccnt++) {
00116         xoff += gfx3d_font04b_char_dpw (str[fch + ccnt]);
00117     }
00118     
00119     /* clear and render */
00120     memset (ltxbuf, 0xff, TXBUF_WIDTH * 4);
00121     lxoff = *xdelta;
00122     gfx3d_font04b_tx_putstrn (ltxbuf, TXBUF_WIDTH, &lxoff, 8, str + fch, ccnt, true);
00123 
00124     if (hxoff == (TXBUF_WIDTH >> 1)) {
00125         /* hit exactly */
00126         *xdelta = 0;
00127         *firstch = fch + hcnt;
00128     } else if (hxoff > (TXBUF_WIDTH >> 1)) {
00129         /* last character overshoots middle, include it next time */
00130         *firstch = fch + (hcnt - 1);
00131         *xdelta = (TXBUF_WIDTH >> 1) - hxoff;
00132     } else {
00133         /* ran out of string, redo from start */
00134         *firstch = 0;
00135         *xdelta = 0;
00136     }
00137 }
00138 
00139 
00140 /*
00141  *  start here
00142  */
00143 int main (void)
00144 {
00145     angle_t a;
00146 #ifdef BENCHMARK
00147     int bt_start, bt_now, bt_update = 0, bt_trans = 0, bt_render = 0;
00148 #endif
00149     angle_t x_rot = 0;
00150     angle_t y_rot = 0;
00151     FXOSData_t fxos_data;
00152     uint8_t ljoybits = 0x00;            /* local joystick bits (JOY_...) */
00153     const uint8_t *std_cube_txmap[6] = {g3d_texture_face, g3d_texture_hlife, g3d_texture_ccube, g3d_texture_hlife, g3d_texture_face, g3d_texture_ccube};
00154     const uint8_t *wcube_txmap[6] = {g3d_texture_wcube, g3d_texture_wcube, g3d_texture_wcube, g3d_texture_wcube, g3d_texture_wcube, g3d_texture_wcube};
00155     int ltxoffs = 0;
00156     int sc_fch = 0;
00157     int sc_xdt = 0;
00158     
00159     uint16_t pot1val, pot2val;
00160     
00161     /* initialise */
00162     host.baud (38400);
00163     
00164     shld_lcd.set_auto_up (0);           /* we'll do it ourselves */
00165     shld_lcd.cls ();
00166     shld_lcd.copy_to_lcd ();
00167     
00168     fxos_int2.fall (trigger_fxos_int2);    /* level triggered interrupt */
00169     fxos.enable();                          /* enable device */
00170 
00171     /* Interrupt for SW2/SW3 button-down state */
00172     sw2_int.mode (PullUp);
00173     sw2_int.fall (trigger_sw2_int);
00174     
00175     sw3_int.fall (trigger_sw3_int);
00176 
00177     /* sort out joystick interrupts */
00178     joy_up.rise (trigger_joy_up_rise);
00179     joy_up.fall (trigger_joy_up_fall);
00180     joy_down.rise (trigger_joy_down_rise);
00181     joy_down.fall (trigger_joy_down_fall);
00182     joy_left.rise (trigger_joy_left_rise);
00183     joy_left.fall (trigger_joy_left_fall);
00184     joy_right.rise (trigger_joy_right_rise);
00185     joy_right.fall (trigger_joy_right_fall);
00186     joy_fire.rise (trigger_joy_fire_rise);
00187     joy_fire.fall (trigger_joy_fire_fall);
00188 
00189     /* read the two potentiometers */
00190     pot1val = shld_pot1.read_u16 ();
00191     pot2val = shld_pot2.read_u16 ();
00192 
00193     float pot1f = G3D_Z_DEPTH_MIN + (((G3D_Z_DEPTH_MAX - G3D_Z_DEPTH_MIN) * (float)pot1val) / 65535.0f);
00194 
00195     gfx3d_set_z_depth (pot1f);
00196 
00197     /* setup frame timer */
00198     frametimer.attach_us (trigger_frametimer, FRAME_RATE_US);
00199 
00200     /* Example data printing */
00201     fxos.get_data (&fxos_data);
00202 //    print_reading (&fxos_data);
00203     
00204     /* clear texture buffer */
00205     scroll_text_update (&sc_fch, &sc_xdt, scrolly_message);
00206 
00207 #ifdef BENCHMARK
00208     perftimer.reset ();
00209     perftimer.start ();
00210 #endif
00211 
00212     a = 0;
00213     for (;;) {
00214         uint8_t cflags;
00215         
00216         __disable_irq ();
00217         cflags = pflags;
00218         pflags = 0x00;
00219         __enable_irq ();
00220         
00221         if (cflags & PFLAG_TIMER) {
00222             g3d_p3_t pts1[8];                   /* points for rotates/translated cubes */
00223             g3d_2p3_t pts2[8];                  /* points for projected cube */
00224             g3d_poly_t poly[12];                /* polygons for cube */
00225             g3d_edgebuf_t pedge[12];            /* edge-buffers for polygons */
00226             int npolys = 0;                     /* number of polygons that are meaningful */
00227             int i;
00228             uint16_t n_pot1, n_pot2;
00229             const uint8_t *wrapmap[6] = {&(ltxbuf[ltxoffs + 0]), &(ltxbuf[ltxoffs + 128]), &(ltxbuf[ltxoffs + 256]), &(ltxbuf[ltxoffs + 384]), g3d_texture_check, g3d_texture_check};
00230             
00231 #ifdef BENCHMARK
00232             bt_start = perftimer.read_us ();
00233             bt_update = 0;
00234             bt_trans = 0;
00235             bt_render = 0;
00236 #endif
00237 
00238             /* push last frame first */
00239             shld_lcd.copy_to_lcd ();
00240             shld_lcd.cls ();
00241 
00242 #ifdef BENCHMARK
00243             bt_now = perftimer.read_us ();
00244             bt_update += (bt_now - bt_start);
00245             bt_start = bt_now;
00246 #endif
00247 
00248             /* read potentiometers */
00249             n_pot1 = shld_pot1.read_u16 ();
00250             n_pot2 = shld_pot2.read_u16 ();
00251             if (pot1val != n_pot1) {
00252                 /* FIXME: ... */
00253                 pot1val = n_pot1;
00254                 pot1f = G3D_Z_DEPTH_MIN + (((G3D_Z_DEPTH_MAX - G3D_Z_DEPTH_MIN) * (float)pot1val) / 65535.0f);
00255 
00256                 gfx3d_set_z_depth (pot1f);
00257             }
00258             if (pot2val != n_pot2) {
00259                 /* FIXME: ... */
00260                 pot2val = n_pot2;
00261             }
00262             gfx3d_clear_zb ();
00263 
00264 #if 0
00265             /* DEBUG: for texture mapping, simple rotating square (2 polys) */
00266             {
00267                 int j;
00268                 g3d_p3_t scale = {2.0, 2.0, 1.0};
00269                 g3d_p3_t trans = {0.0, 0.0, -10.0 + ((20.0f * (float)a) / 256.0f)};
00270                 
00271                 gfx3d_scale (g3d_xyfacepnts, pts1, 4, scale);
00272                 gfx3d_rotate_x (pts1, pts1, 4, a);
00273                 gfx3d_translate (pts1, pts1, 4, trans);
00274                 gfx3d_rotate_z (pts1, pts1, 4, a * 2);
00275                 gfx3d_project (pts1, pts2, 4);
00276                 gfx3d_squarify_points (pts2, poly, &npolys, 0);     /* hide backfaces */
00277                 for (j=0; j<npolys; j++) {
00278                     gfx3d_sort_poly (&poly[j]);
00279                 }
00280 #ifdef BENCHMARK
00281                 bt_now = perftimer.read_us ();
00282                 bt_trans += (bt_now - bt_start);
00283                 bt_start = bt_now;
00284 #endif
00285                 for (j=0; j<npolys; j++) {
00286                     gfx3d_polytxmap (&poly[j], g3d_texture_face, shld_lcd);
00287                 }
00288                 
00289 #ifdef BENCHMARK
00290                 bt_now = perftimer.read_us ();
00291                 bt_render += (bt_now - bt_start);
00292                 bt_start = bt_now;
00293 #endif
00294 
00295             }
00296 #else            
00297             for (i=0; i<4; i++) {
00298                 g3d_p3_t trans = {3.0f * gfx3d_sin (a + (i * 64)), 0.0f, 5.0f * gfx3d_cos (a + (i * 64))};
00299                 int j;
00300             
00301                 /* rotate, translate and render! */
00302                 if (i == 0) {
00303                     gfx3d_rotate_y (g3d_cubepnts, pts1, 8, x_rot);
00304                     gfx3d_rotate_x (pts1, pts1, 8, y_rot);
00305                     gfx3d_translate (pts1, pts1, 8, trans);
00306                 } else {
00307                     gfx3d_rotate_demo (g3d_cubepnts, pts1, 8, (a * i) & 0xff);
00308                     gfx3d_translate (pts1, pts1, 8, trans);
00309                 }
00310 
00311                 gfx3d_project (pts1, pts2, 8);
00312                 if (i == 0) {
00313                     gfx3d_cubify_points (pts2, poly, &npolys, 0, wrapmap);       /* hide backfaces */
00314                 } else if (i == 3) {
00315                     gfx3d_cubify_points (pts2, poly, &npolys, 0, wcube_txmap);       /* hide backfaces */
00316                 } else {
00317                     gfx3d_cubify_points (pts2, poly, &npolys, 0, std_cube_txmap);       /* hide backfaces */
00318                 }
00319                 for (j=0; j<npolys; j++) {
00320                     gfx3d_sort_poly (&poly[j]);
00321                 }
00322 
00323 #if 0
00324 if (i == 2) {
00325 if ((a & 0x0f) == 0) {
00326     host.printf ("poly[0].tx_pts[0]=%4.4x, [1]=%4.4x, [2]=%4.4x, norm=%8.8x\r\n", poly[0].tx_pts[0], poly[0].tx_pts[1], poly[0].tx_pts[2], poly[0].norm);
00327 }
00328 }
00329 #endif
00330 
00331 #ifdef BENCHMARK
00332                 bt_now = perftimer.read_us ();
00333                 bt_trans += (bt_now - bt_start);
00334                 bt_start = bt_now;
00335 #endif
00336 
00337                 for (j=0; j<npolys; j++) {
00338                     if (i == 2) {
00339                         gfx3d_polynormmap (&poly[j], shld_lcd);
00340                     } else {
00341                         gfx3d_polytxmap (&poly[j], shld_lcd);
00342                     }
00343                 }
00344                 
00345 #ifdef BENCHMARK
00346                 bt_now = perftimer.read_us ();
00347                 bt_render += (bt_now - bt_start);
00348                 bt_start = bt_now;
00349 #endif
00350 
00351             }
00352 #endif  /* (debugging what polygons to use) */
00353             
00354             /* filled up the frame-buffer, setup things for next time */
00355             a++;
00356             
00357             if (ljoybits & JOY_UP) {
00358                 y_rot += JOY_ANGLE_ADVANCE;
00359             } else if (ljoybits & JOY_DOWN) {
00360                 y_rot -= JOY_ANGLE_ADVANCE;
00361             }
00362             
00363             if (ljoybits & JOY_LEFT) {
00364                 x_rot += JOY_ANGLE_ADVANCE;
00365             } else if (ljoybits & JOY_RIGHT) {
00366                 x_rot -= JOY_ANGLE_ADVANCE;
00367             }
00368             
00369             ltxoffs += 4;
00370             if (ltxoffs >= 512) {
00371                 /* update scrolly text */
00372                 scroll_text_update (&sc_fch, &sc_xdt, scrolly_message);
00373                 ltxoffs -= 512;
00374             }
00375 
00376 #ifdef BENCHMARK
00377             /* write bt_trans and bt_render into the display */
00378             shld_lcd.locate (0, 24);
00379             shld_lcd.printf ("U:%d T:%d R:%d", bt_update, bt_trans, bt_render);
00380 #endif
00381         }
00382         if (cflags & PFLAG_FXOS) {
00383             fxos.get_data (&fxos_data);
00384         }
00385         if (cflags & PFLAG_JOY) {
00386             /* just update our local version of the variable (might not see changes in A-B-A situations) */
00387             ljoybits = joybits;
00388         }
00389 
00390         
00391         __disable_irq ();
00392         if (!pflags) {
00393             sleep ();
00394         }
00395         __enable_irq ();
00396     }
00397     
00398 }
00399