Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: C12832 FXOS8700CQ gfx3d mbed
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
Generated on Wed Jul 13 2022 08:59:16 by
