// // fmtb_pic.c - This file is the pic code for fmtb_parse.c // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // #ifndef PIC_CSIM #define PIC_CSIM 0 #endif #define ALLOW_GAPS_IN_STRONG_CIRCLES 1 #define FIX_CIRCLE_OCT_COMPARE 1 #define MAX_TOKEN_CNT 256 #define USE_LEDSCAN 1 // // See wand.asm MEMORY MAP for details // picEqu(RAMBUF_MTOKENS, 0xc00) picEqu(RAMBUF_MTOKENS_LEN, 0x100) picEqu(RAMBUF_M2LIST, 0x300) picEqu(RAMBUF_M2LIST_LEN, 0x500) picEqu(RAMBUF_M3LIST, 0x800) picEqu(RAMBUF_M3LIST_LEN, 0x500) picEqu(RAMBUF_ACC, 0x500) picEqu(RAMBUF_ACC_LEN, 0xa00) picEqu(RAMBUF_STOKENS, 0xb00) picEqu(RAMBUF_STOKENS_LEN, 0x100) picEqu(RAMBUF_SPELLDATA, 0x900) picEqu(RAMBUF_SPELLDATA_LEN, 0x100) picEqu(RAMBUF_SD_SPELL_IGNORE, 0x900) picEqu(RAMBUF_SD_MOTION_IGNORE, 0x908) #if !USE_LEDSCAN picEqu(RAMBUF_SD_LED, 0x910) #endif picEqu(RAMBUF_MMATRIX, 0xa00) picEqu(RAMBUF_MMATRIX_LEN, 0x100) picEqu(RAMBUF_STBL1, 0x800) picEqu(RAMBUF_STBL1_LEN, 0x100) picEqu(RAMBUF_STBL2, 0x700) picEqu(RAMBUF_STBL2_LEN, 0x100) //=========================================================================== // declare global registers //=========================================================================== #if PIC_CSIM static void init_pic_globals(void) #endif { // // common variables // picRegGlobal(v_mo_angle, "fmtb"); picRegGlobal(v_mo_oct, "fmtb"); picRegGlobal(v_mo_impl, "fmtb"); picRegGlobal(v_mo_imph, "fmtb"); picRegGlobal(v_mo_maxmag, "fmtb"); picRegGlobal(v_mo_shape, "fmtb"); picRegGlobal(v_mo_save_fsr0l, "fmtb"); picRegGlobal(v_mo_save_fsr0h, "fmtb"); picRegGlobal(v_mo_save_fsr1l, "fmtb"); picRegGlobal(v_mo_save_fsr1h, "fmtb"); picRegGlobal(v_mo_save_fsr2l, "fmtb"); picRegGlobal(v_mo_save_fsr2h, "fmtb"); // // local variables for mo1 // picRegGlobal(v_mo1_mo_angle, "mo1"); picRegGlobal(v_mo1_mo_maxmag, "mo1"); picRegGlobal(v_mo1_mo_minmag, "mo1"); picRegGlobal(v_mo1_mo_impl, "mo1"); picRegGlobal(v_mo1_mo_imph, "mo1"); picRegGlobal(v_mo1_mo_flags, "mo1"); // // locals for mo2 // picRegGlobal(v_mo2_next_mh, "mo2"); picRegGlobal(v_mo2_next_ml, "mo2"); picRegGlobal(v_mo2_next_mdh, "mo2"); picRegGlobal(v_mo2_next_mdl, "mo2"); picRegGlobal(v_mo2_bits, "mo2"); #define PICDST_BITb_MSHF_PLUS PICDST_BIT0 #define PICDST_BITb_MSHF_ZERO PICDST_BIT0 #define PICDST_BITb_MSHF_DIR PICDST_BIT3 #define PICDST_BITb_MSHF_CIRCLE PICDST_BIT5 #define PICDST_BITb_MSHF_MONO PICDST_BIT6 #define PICDST_BITb_MSHF_PREV_PAUSE PICDST_BIT7 ASSERT(MSHF_ZERO == (1<<(PICDST_BITb_MSHF_ZERO-PICDST_BIT0))); ASSERT(MSHF_PLUS == (1<<(PICDST_BITb_MSHF_PLUS-PICDST_BIT0))); ASSERT(MSHF_DIR == (1<<(PICDST_BITb_MSHF_DIR-PICDST_BIT0))); ASSERT(MSHF_CIRCLE == (1<<(PICDST_BITb_MSHF_CIRCLE-PICDST_BIT0))); ASSERT(MSHF_PREV_PAUSE == (1<<(PICDST_BITb_MSHF_PREV_PAUSE-PICDST_BIT0))); ASSERT(MSHF_MONO == (1<<(PICDST_BITb_MSHF_MONO-PICDST_BIT0))); #define PICDST_BITb_TOK_DIR PICDST_BIT7 ASSERT(TOK_DIR == (1<<(PICDST_BITb_TOK_DIR-PICDST_BIT0))); #define PICDST_BITb_AFLG_END PICDST_BIT6 #define PICDST_BITb_AFLG_START PICDST_BIT5 ASSERT(AFLG_END == (1<<(PICDST_BITb_AFLG_END-PICDST_BIT0))); ASSERT(AFLG_START == (1<<(PICDST_BITb_AFLG_START-PICDST_BIT0))); #define PICDST_BITb_MWN_PULSE PICDST_BIT7 #define PICDST_BITb_MWN_DIR PICDST_BIT6 #define PICDST_BITb_MWN_MORE PICDST_BIT5 ASSERT(MWN_PULSE == (1<<(PICDST_BITb_MWN_PULSE-PICDST_BIT0))); ASSERT(MWN_DIR == (1<<(PICDST_BITb_MWN_DIR-PICDST_BIT0))); ASSERT(MWN_MORE == (1<<(PICDST_BITb_MWN_MORE-PICDST_BIT0))); } //=========================================================================== // w_a2oct: convert angle (in W) to octant (in W) //=========================================================================== static void w_a2oct(void) { addlw(2); rrncf(WREG,w); rrncf(WREG,w); andlw(7); picReturn(); } //=========================================================================== // w_oct2a: convert octant (in W) to angle (in W) //=========================================================================== static void w_oct2a(void) { rlncf(WREG,w); rlncf(WREG,w); andlw(0x1f); picReturn(); } //=========================================================================== // w_adiff: convert angle a1-a0 (in W) to range -16 ... 15 //=========================================================================== static void w_adiff(void) { andlw(0x1f); btfsc(WREG,4); addlw(-0x20); picReturn(); } //=========================================================================== // w_odiff: convert octant o1-o0 (in W) to range -4 ... 3 //=========================================================================== static void w_odiff(void) { andlw(0x07); btfsc(WREG,2); addlw(-0x08); picReturn(); } #if 0 //=========================================================================== // w_a2quad: convert angle (in W) to quad (in W) //=========================================================================== static void w_a2quad(void) { addlw(4); rrncf(WREG,w); rrncf(WREG,w); rrncf(WREG,w); andlw(3); picReturn(); } #endif //=========================================================================== // w_mo_read: //=========================================================================== static void w_mo_read(void) { // // Fills in these registers: // v_mo1_mo_angle // v_mo1_mo_maxmag // v_mo1_mo_minmag // v_mo1_mo_impl // v_mo1_mo_imph // v_mo1_mo_flags // // Read as follows from FSR2: // // Pause: // 0 - time (h) // 1 - time (l) // 2 - unused (set to 0xff) // 3 - angle (0xff indicates pause) // // Angle: // 0 - time (h) // 1 - time (l) // 2 - max mag // 3 - angle (0-31) // 4 - imp (h) // 5 - imp (l) // 6 - min mag // 7 - flags // movf(POSTINC2,w); // timeh movf(POSTINC2,w); // timel movf(POSTINC2,w); movwf(v_mo1_mo_maxmag); movf(POSTINC2,w); movwf(v_mo1_mo_angle); btfsc(v_mo1_mo_angle,7); picReturn(); movf(POSTINC2,w); movwf(v_mo1_mo_imph); // imph movf(POSTINC2,w); movwf(v_mo1_mo_impl); // impl movf(POSTINC2,w); movwf(v_mo1_mo_minmag); // minmag movf(POSTINC2,w); movwf(v_mo1_mo_flags); // flags (only bit0 counts) picReturn(); } //=========================================================================== // w_shp_read: read from FSR2 //=========================================================================== static void w_shp_read(void) { // // read Motion2 from FSR2 // movf(POSTINC2,w); movwf(v_mo_angle); movf(POSTINC2,w); movwf(v_mo_impl); movf(POSTINC2,w); movwf(v_mo_imph); movf(POSTINC2,w); movwf(v_mo_maxmag); movf(POSTINC2,w); movwf(v_mo_shape); picReturn(); ASSERT(0); } //=========================================================================== // w_shp_write: write to FSR0 //=========================================================================== static void w_shp_write(void) { // // write Motion2 to FSR0 // movf(v_mo_angle,w); movwf(POSTINC0); movf(v_mo_impl,w); movwf(POSTINC0); movf(v_mo_imph,w); movwf(POSTINC0); movf(v_mo_maxmag,w); movwf(POSTINC0); movf(v_mo_shape,w); movwf(POSTINC0); picReturn(); ASSERT(0); } //=========================================================================== // w_shp_prev: - back up to previous motion2 record //=========================================================================== static void w_shp_prev(void) { // // back up to previous motion2 record // movlw(5); subwf(FSR2L,f); movlw(0); subwfb(FSR2H,f); picReturn(); ASSERT(0); } //=========================================================================== // w_mo1_parse1: //=========================================================================== static void w_mo1_parse1(void) { #if PIC_CSIM int dbg = DBG_PARSE1_MINIMAL; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif // // local variables // int picRegLocal(v_mo1_bits); #define PICDST_BITb_mo1_was_pause PICDST_BIT0 #define PICDST_BITb_mo1_got_angle PICDST_BIT1 #define PICDST_BITb_mo1_got_dir PICDST_BIT2 int picRegLocal(v_mo1_dir); int picRegLocal(v_mo1_shape_flags); int picRegLocal(v_mo1_prev_angle); int picRegLocal(v_mo1_prev_oct); int picRegLocal(v_mo1_step); int picRegLocal(v_mo1_maxdmag); int picRegLocal(v_mo1_maxstep); int picRegLocal(v_mo1_asum); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif lfsr(FSR2,RAMBUF_ACC); lfsr(FSR0,RAMBUF_M2LIST); // // first motion is STARTT // movlw(ANGLE_START); movwf(v_mo1_mo_angle); movwf(POSTINC0); // angle clrf(POSTINC0); // impl clrf(POSTINC0); // imph clrf(POSTINC0); // maxmag clrf(POSTINC0); // shape clrf(v_mo1_dir); clrf(v_mo1_bits); bsf(v_mo1_bits,b_mo1_was_pause); // // these probably do not need to be cleared // clrf(v_mo1_shape_flags); picLabel(w_mo1_outer_loop); movf(v_mo1_mo_angle,w); movwf(v_mo1_prev_angle); movf(v_mo_oct,w); movwf(v_mo1_prev_oct); clrf(v_mo1_step); rcall(w_mo_read); #if PIC_CSIM if (dbg) { Motion m; memset(&m,0,sizeof(m)); m.b_angle = picRV(v_mo1_mo_angle); m.b_maxmag = picRV(v_mo1_mo_maxmag); m.b_imp = picRV(v_mo1_mo_impl) + (picRV(v_mo1_mo_imph) << 8); m.b_minmag = picRV(v_mo1_mo_minmag); m.b_flags = picRV(v_mo1_mo_flags); printMotion("READ1 ",&m,&m,2); breakpt(); } #endif movf(v_mo1_mo_angle,w); rcall(w_a2oct); movwf(v_mo_oct); // // is it pause or end of buffer? // btfss(v_mo1_mo_angle,7); bra(w_mo1_top_checkpause); // // restart new shape if this is a new pause // btfss(v_mo1_bits,b_mo1_was_pause); bra(w_mo1_restart); // // repeated pause? (not end of buffer?) - loop // btfsc(v_mo1_mo_angle,0); bra(w_mo1_outer_loop); // // end of buffer - DONE // bra(w_mo1_done); picLabel(w_mo1_top_checkpause); btfss(v_mo1_bits,b_mo1_was_pause); bra(w_mo1_top_checkangle); bcf(v_mo1_bits,b_mo1_got_angle); bra(w_mo1_restart); picLabel(w_mo1_top_checkangle); // // calc v_mo1_step & v_mo1_dir // clrf(v_mo1_dir); movf(v_mo1_prev_angle,w); subwf(v_mo1_mo_angle,w); andlw(0x1f); btfss(WREG,4); // check for negative bra(w_mo1_top_checkangle2); addlw(-0x20); negf(WREG); bsf(v_mo1_dir,b_MSHF_DIR); picLabel(w_mo1_top_checkangle2); movwf(v_mo1_step); movf(v_mo_oct,w); subwf(v_mo1_prev_oct,w); bz(w_mo1_bottom); // fall through to restart picLabel(w_mo1_restart); btfss(v_mo1_bits,b_mo1_got_angle); bra(w_mo1_restart2); // // got a motion angle - send a shape // movf(v_mo1_step,w); addwf(v_mo1_asum,f); cpfsgt(v_mo1_maxstep); movwf(v_mo1_maxstep); movlw(MSHP_PULSE); movwf(v_mo_shape); // // clear MONO if no dir was found // btfss(v_mo1_bits,b_mo1_got_dir); bcf(v_mo1_shape_flags,b_MSHF_MONO); // // clear MONO if direction changed // movf(v_mo1_dir,w); xorwf(v_mo1_shape_flags,w); btfsc(WREG,b_MSHF_DIR); bcf(v_mo1_shape_flags,b_MSHF_MONO); // // if !MONO send pulse // btfss(v_mo1_shape_flags,b_MSHF_MONO); bra(w_mo1_send_shape); // // if MSHF_PREV_PAUSE send pulse // if new angle is a pause (or end of buffer) then send pulse // btfss(v_mo1_shape_flags,b_MSHF_PREV_PAUSE); btfsc(v_mo1_mo_angle,7); bra(w_mo1_send_shape); // // if asum < 4 send pulse // movf(v_mo1_asum,w); addlw(-4); bnc(w_mo1_send_shape); // // if maxstep >= 6 send pulse // movf(v_mo1_maxstep,w); addlw(-6); bc(w_mo1_send_shape); // // Not a pulse! dirty circle? // ASSERT(MSHP_DIRTY_CIRCLE == 0x00); ASSERT(MSHP_PULSE == (1<<2)); ASSERT(picRV(v_mo_shape) == MSHP_PULSE); bcf(v_mo_shape,2); ASSERT(picRV(v_mo_shape) == MSHP_DIRTY_CIRCLE); // // if maxstep >= 4 send dirty circle // movf(v_mo1_maxstep,w); addlw(-4); bc(w_mo1_send_shape); // // if maxdmag >= 8 send dirty circle // movf(v_mo1_maxdmag,w); addlw(-8); bc(w_mo1_send_shape); // // if ZERO then send dirty circle // btfsc(v_mo1_shape_flags,b_MSHF_ZERO); bra(w_mo1_send_shape); // // send clean circle // ASSERT(MSHP_CLEAN_CIRCLE == (1<<1)); ASSERT(picRV(v_mo_shape) == 0); bsf(v_mo_shape,1); ASSERT(picRV(v_mo_shape) == MSHP_CLEAN_CIRCLE); // // SEND THE SHAPE // picLabel(w_mo1_send_shape); movf(v_mo1_shape_flags,w); andlw(MSHF_FLG_MASK); iorwf(v_mo_shape,f); // // clear dir flag if !MONO // btfss(v_mo_shape,b_MSHF_MONO); bcf(v_mo_shape,b_MSHF_DIR); #if PIC_CSIM if (dbg) { Motion2 m; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("WRITE ",&m,&m,4); breakpt(); } #endif rcall(w_shp_write); picLabel(w_mo1_restart2); // // are we at the end? // movf(v_mo1_mo_angle,w); addlw(-0xfe); bz(w_mo1_done); clrf(v_mo1_asum); clrf(v_mo_impl); clrf(v_mo_imph); clrf(v_mo1_maxstep); clrf(v_mo1_maxdmag); clrf(v_mo_maxmag); bcf(v_mo1_bits,b_mo1_got_angle); movlw(MSHF_DIR); andwf(v_mo1_shape_flags,f); bsf(v_mo1_shape_flags,b_MSHF_MONO); // // bottom - after restart // picLabel(w_mo1_bottom); btfss(v_mo1_mo_angle,7); bra(w_mo1_bottom_notpause); // // pause // bsf(v_mo1_bits,b_mo1_was_pause); bra(w_mo1_outer_loop); picLabel(w_mo1_bottom_notpause); btfss(v_mo1_bits,b_mo1_was_pause); bra(w_mo1_bottom_angle); // // was pause last time // bcf(v_mo1_bits,b_mo1_was_pause); bcf(v_mo1_bits,b_mo1_got_dir); bsf(v_mo1_shape_flags,b_MSHF_PREV_PAUSE); if (OPT_use_classic) { bcf(v_mo1_shape_flags,b_MSHF_MONO); } bra(w_mo1_getangle); // // angle (not the first one) // picLabel(w_mo1_bottom_angle); // // if !got_dir // copy DIR bit frim mo_dir // btfsc(v_mo1_bits,b_mo1_got_dir); bra(w_mo1_checkdir); bcf(v_mo1_shape_flags,b_MSHF_DIR); movf(v_mo1_dir,w); andlw(MSHF_DIR); iorwf(v_mo1_shape_flags,f); picLabel(w_mo1_checkdir); bsf(v_mo1_bits,b_mo1_got_dir); movf(v_mo1_dir,w); xorwf(v_mo1_shape_flags,w); andlw(MSHF_DIR); bz(w_mo1_getangle); // // change in direction detected // xorwf(v_mo1_shape_flags,f); bcf(v_mo1_shape_flags,b_MSHF_MONO); picLabel(w_mo1_getangle); // // got an angle - record info from it // bsf(v_mo1_bits,b_mo1_got_angle); movf(v_mo1_mo_impl,w); addwf(v_mo_impl,f); movf(v_mo1_mo_imph,w); addwfc(v_mo_imph,f); bnc(w_mo1_impwrap); setf(v_mo_impl); setf(v_mo_imph); picLabel(w_mo1_impwrap); movf(v_mo1_mo_maxmag,w); subwf(v_mo_maxmag,w); bc(w_mo1_notmax); movf(v_mo1_mo_maxmag,w); movwf(v_mo_maxmag); movf(v_mo1_mo_angle,w); movwf(v_mo_angle); picLabel(w_mo1_notmax); ASSERT(MSHF_ZERO == MFLG_ZERO); movf(v_mo1_mo_flags, w); andlw(MSHF_ZERO); iorwf(v_mo1_shape_flags,f); // // calc dmag & save max // movf(v_mo1_mo_minmag,w); subwf(v_mo1_mo_maxmag,w); btfsc(v_mo1_mo_flags,b_MSHF_ZERO); movf(v_mo1_mo_maxmag,w); cpfsgt(v_mo1_maxdmag); movwf(v_mo1_maxdmag); movf(v_mo1_step,w); addwf(v_mo1_asum,f); cpfsgt(v_mo1_maxstep); movwf(v_mo1_maxstep); bra(w_mo1_outer_loop); // // End of loop // picLabel(w_mo1_done); movlw(ANGLE_END); movwf(v_mo_angle); rcall(w_shp_write); // // write END to last legal buffer slot too, in case we overflowed // ASSERT((MAX_TOKEN_CNT*5)<=RAMBUF_M2LIST_LEN); lfsr(FSR2,RAMBUF_M2LIST+((MAX_TOKEN_CNT-1)*5)); ASSERT(picRV(v_mo_angle) == ANGLE_END); rcall(w_shp_write); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif // // done // picReturn(); ASSERT(0); } //=========================================================================== // w_mo2_savenext: //=========================================================================== static void w_mo2_savenext(void) { int picRegInOutParam(v_mo2_bits); #define PICDST_BITb_mo2_cnt1b PICDST_BIT0 #define PICDST_BITb_mo2_added PICDST_BIT1 #define PICDST_BITb_mo2_savenext PICDST_BIT2 int picRegInOutParam(v_mo2_next_mh); int picRegInOutParam(v_mo2_next_ml); int picRegInOutParam(v_mo2_next_mdh); int picRegInOutParam(v_mo2_next_mdl); btfss(v_mo2_bits,b_mo2_savenext); picReturn(); bcf(v_mo2_bits,b_mo2_savenext); movf(FSR2H,w); movwf(v_mo2_next_mh); movf(FSR2L,w); movwf(v_mo2_next_ml); movf(FSR0H,w); movwf(v_mo2_next_mdh); movf(FSR0L,w); movwf(v_mo2_next_mdl); picReturn(); ASSERT(0); } //=========================================================================== // w_mo2_fill_circle_gaps: //=========================================================================== static void w_mo2_fill_circle_gaps(void) { #if PIC_CSIM int dbg = DBG_FILLGAP_MINIMAL; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif // // local variables // int picRegLocal(v_mo2_next_mh); int picRegLocal(v_mo2_next_ml); int picRegLocal(v_mo2_next_mdh); int picRegLocal(v_mo2_next_mdl); int picRegLocal(v_mo2_shape0); int picRegLocal(v_mo2_cnt0); int picRegLocal(v_mo2_cnt1); int picRegLocal(v_mo2_delta_oct); int picRegLocal(v_mo2_gap_oct); int picRegLocal(v_mo2_total_cnt); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif picLabel(w_mo2_outer_loop); #if PIC_CSIM if (!OPT_silent) { printf("start fillCircleGaps_picsim\n"); } #endif clrf(v_mo2_bits); clrf(v_mo2_total_cnt); // // copy motions to M3LIST // lfsr(FSR2,RAMBUF_M2LIST); lfsr(FSR0,RAMBUF_M3LIST); picLabel(w_mo2_copy_loop); rcall(w_shp_read); rcall(w_shp_write); incf(v_mo2_total_cnt,f); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M3LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("COPY ",(&m)-idx+2,&m,6); } #endif btfss(v_mo_angle,b_AFLG_END); bra(w_mo2_copy_loop); // // look for gaps as we copy it back // lfsr(FSR2,RAMBUF_M3LIST+5); lfsr(FSR0,RAMBUF_M2LIST+5); picLabel(w_mo2_look_loop); rcall(w_shp_read); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M3LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("READ1 ",&m-idx+2,&m,2); breakpt(); } #endif picLabel(w_mo2_look_loop2); btfsc(v_mo_angle,b_AFLG_END); bra(w_mo2_look_done); movff(v_mo_shape,v_mo2_shape0); movlw(1-2-1); movwf(v_mo2_cnt0); movwf(v_mo2_cnt1); movf(v_mo_angle,w); rcall(w_a2oct); movwf(v_mo_oct); #if PIC_CSIM if (dbg) { printf("START: shape0=%02x oct=%d\n", picRV(v_mo2_shape0), picRV(v_mo_oct)); } #endif bsf(v_mo2_bits,b_mo2_savenext); picLabel(w_mo2_top_loop); incf(v_mo2_cnt0,f); rcall(w_shp_write); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR0H)<<8) + picRV(FSR0L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("WRITE2",&m-idx+2,&m,4); breakpt(); } #endif rcall(w_mo2_savenext); movff(v_mo_oct,v_mo2_delta_oct); negf(v_mo2_delta_oct); rcall(w_shp_read); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M3LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("READ3 ",&m-idx+2,&m,2); breakpt(); } #endif btfsc(v_mo_angle,b_AFLG_END); bra(w_mo2_look_done); btfsc(v_mo_shape,b_MSHF_PREV_PAUSE); bra(w_mo2_look_loop2); // // calc delta oct // movf(v_mo_angle,w); rcall(w_a2oct); movwf(v_mo_oct); addwf(v_mo2_delta_oct,f); // // Do we know what direction this circle is going? // btfsc(v_mo2_shape0,b_MSHF_MONO); bra(w_mo2_top_check_dir); // // do not know direction - figure it out // movlw(MSHF_MONO); movwf(v_mo2_shape0); btfsc(v_mo2_delta_oct,2); bsf(v_mo2_shape0,b_MSHF_DIR); picLabel(w_mo2_top_check_dir); // // delta oct direction // btfsc(v_mo2_shape0,b_MSHF_DIR); negf(v_mo2_delta_oct); movlw(7); andwf(v_mo2_delta_oct,f); // // change of direction? // if MONO is set and dir bit is different then break // btfss(v_mo_shape,b_MSHF_MONO); bra(w_mo2_top_checked_dir); movf(v_mo_shape,w); xorwf(v_mo2_shape0,w); btfsc(WREG,b_MSHF_DIR); bra(w_mo2_look_next); picLabel(w_mo2_top_checked_dir); ASSERT(picRV(v_mo2_delta_oct)!=0); // // is delta_oct ==1? // dcfsnz(v_mo2_delta_oct,f); bra(w_mo2_top_loop); //picLabel(w_mo2_top_done); // // optimization - skip to next if only 1 found // movf(v_mo2_cnt0,f); bn(w_mo2_look_next); // // was delta_oct ==2? // decfsz(v_mo2_delta_oct,f); bra(w_mo2_look_next); // // gap_oct = dir ? current_oct+1 current_oct-1 // incf(v_mo_oct,w); btfss(v_mo2_shape0,b_MSHF_DIR); addlw(-2); andlw(7); movwf(v_mo2_gap_oct); bcf(v_mo2_bits,b_mo2_cnt1b); bsf(v_mo2_bits,b_mo2_savenext); rcall(w_mo2_savenext); #if PIC_CSIM if (dbg) { printf("gap? cnt0=%d cnt1=%d gap_oct=%d\n", picRV(v_mo2_cnt0)+2, picRV(v_mo2_cnt1)+2+1, picRV(v_mo2_gap_oct)); } #endif picLabel(w_mo2_bot_loop); incf(v_mo2_cnt1,f); rcall(w_shp_write); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR0H)<<8) + picRV(FSR0L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("WRITE4",&m-idx+2,&m,4); breakpt(); } #endif movff(v_mo_oct,v_mo2_delta_oct); negf(v_mo2_delta_oct); rcall(w_shp_read); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M3LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("READ5 ",&m-idx+2,&m,2); breakpt(); } #endif btfsc(v_mo_angle,b_AFLG_END); bra(w_mo2_bot_done); btfsc(v_mo_shape,b_MSHF_PREV_PAUSE); bra(w_mo2_bot_done); // // change of direction? // if MONO is set and dir bit is different then break // btfss(v_mo_shape,b_MSHF_MONO); bra(w_mo2_bot_checked_dir); movf(v_mo_shape,w); xorwf(v_mo2_shape0,w); btfsc(WREG,b_MSHF_DIR); bra(w_mo2_bot_done); picLabel(w_mo2_bot_checked_dir); // // find delta oct // movf(v_mo_angle,w); rcall(w_a2oct); movwf(v_mo_oct); addwf(v_mo2_delta_oct,f); // // delta oct direction // btfsc(v_mo2_shape0,b_MSHF_DIR); negf(v_mo2_delta_oct); movlw(7); andwf(v_mo2_delta_oct,f); ASSERT(picRV(v_mo2_delta_oct)!=0); // // is delta_oct ==1? // dcfsnz(v_mo2_delta_oct,f); bra(w_mo2_bot_loop); // is 1 - loop // // is delta oct == 2? // decfsz(v_mo2_delta_oct,f); bra(w_mo2_bot_done); // not 2 - done // // delta_oct==2 - keep going if first time // btg(v_mo2_bits,b_mo2_cnt1b); btfsc(v_mo2_bits,b_mo2_cnt1b); bra(w_mo2_bot_loop); // first time - loop picLabel(w_mo2_bot_done); #if PIC_CSIM if (dbg) { printf("check: cnt0=%d cnt1=%d gap_oct=%d\n", picRV(v_mo2_cnt0)+2, picRV(v_mo2_cnt1)+2, picRV(v_mo2_gap_oct)); } #endif // // place pointers at gap // movlw(5); subwf(v_mo2_next_ml,w); movwf(FSR2L); movlw(0); subwfb(v_mo2_next_mh,w); movwf(FSR2H); movf(v_mo2_next_mdh,w); movwf(FSR0H); movf(v_mo2_next_mdl,w); movwf(FSR0L); // // check for valid Gap-fill condition // (cnt0>=2-2 && cnt1>=2-2 && (cnt0+cnt1 >= 6-2-2)) // movf(v_mo2_cnt0,w); bn(w_mo2_look_loop); movf(v_mo2_cnt1,w); bn(w_mo2_look_loop); addwf(v_mo2_cnt0,w); addlw(-(6-2-2)); bnc(w_mo2_look_loop); // no gap - loop // // make sure we do not already have 256 motion entries. // If we do then do not add a gap. // movf(v_mo2_total_cnt,f); bz(w_mo2_look_loop); // // Found a Gap!! // movf(v_mo2_shape0,w); andlw(MSHF_DIR); iorlw(MSHP_CIRCLE_GAP|MSHF_MONO); movwf(v_mo_shape); clrf(v_mo_maxmag); clrf(v_mo_impl); clrf(v_mo_imph); movf(v_mo2_gap_oct,w); rcall(w_oct2a); movwf(v_mo_angle); incf(v_mo2_total_cnt,f); // total # of motion entries rcall(w_shp_write); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR0H)<<8) + picRV(FSR0L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("WRITEG",&m-idx+2,&m,4); breakpt(); } #endif bsf(v_mo2_bits,b_mo2_added); bra(w_mo2_look_loop); // // check starting at next motion // picLabel(w_mo2_look_next); movf(v_mo2_next_mh,w); movwf(FSR2H); movf(v_mo2_next_ml,w); movwf(FSR2L); movf(v_mo2_next_mdh,w); movwf(FSR0H); movf(v_mo2_next_mdl,w); movwf(FSR0L); bra(w_mo2_look_loop); // // finished with this iteration // picLabel(w_mo2_look_done); movlw(ANGLE_END); movwf(v_mo_angle); rcall(w_shp_write); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR0H)<<8) + picRV(FSR0L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("WRITEE",&m-idx+2,&m,4); breakpt(); } #endif btfsc(v_mo2_bits,b_mo2_added); bra(w_mo2_outer_loop); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif // // done // picReturn(); ASSERT(0); } //=========================================================================== // w_mo3_find_weak_circles: //=========================================================================== static void w_mo3_find_weak_circles(void) { #if PIC_CSIM int dbg = DBG_FINDWEAK; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif // // local variables // int picRegLocal(v_mo3_dcnt); int picRegLocal(v_mo3_ccnt); int picRegLocal(v_mo3_msl); int picRegLocal(v_mo3_msh); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif // // loop through all motions // lfsr(FSR2,RAMBUF_M2LIST+5); picLabel(w_mo3_loop1); clrf(v_mo3_dcnt); clrf(v_mo3_ccnt); clrf(v_tmp); movff(FSR2L,v_mo3_msl); movff(FSR2H,v_mo3_msh); #if PIC_CSIM if (dbg) { printf("m[%2d] Restart\n",(picFSR2()-RAMBUF_M2LIST)/5); } #endif // // loop through all motions in circle // picLabel(w_mo3_loop2); incf(v_tmp,f); #if PIC_CSIM if (dbg) { printf("m[%2d] cc=%-2d dc%-2d v_tmp=%d\n", (picFSR2()-0x500)/5, picRV(v_mo3_ccnt), picRV(v_mo3_dcnt), picRV(v_tmp)); } #endif rcall(w_shp_read); ASSERT(AFLG_END == (1<<6)); btfsc(v_mo_angle,6); bra(w_mo3_loop2_done); #if 1 #if PIC_CSIM // // check for pause is unneccesary - will never be a circle if // preceded by pause // { int shape = picRV(v_mo_shape); ASSERT((shape & MSHF_PLUS) == 0); if (shape & MSHF_PREV_PAUSE) { shape &= MSHF_SHP_MASK; ASSERT(shape != MSHP_DIRTY_CIRCLE); ASSERT(shape != MSHP_CLEAN_CIRCLE); ASSERT(shape != MSHP_CIRCLE_GAP); } } #endif #else // // stop if we hit a pause // ASSERT(MSHF_PREV_PAUSE == (1<<7)); btfsc(v_mo_shape,7); bra(w_mo3_loop2_done); #endif // // what shape is this? // movf(v_mo_shape,w); andlw(MSHF_SHP_MASK); #if ALLOW_GAPS_IN_STRONG_CIRCLES // // CIRCLE GAPS do not count, but keep going // addlw(LOW(-MSHP_CIRCLE_GAP)); bz(w_mo3_loop2); #endif // // clean circle? // incf(v_mo3_ccnt,f); addlw(LOW(MSHP_CIRCLE_GAP-MSHP_CLEAN_CIRCLE)); bz(w_mo3_loop2); // // dirty circle? // decf(v_mo3_ccnt,f); incf(v_mo3_dcnt,f); addlw(LOW(MSHP_CLEAN_CIRCLE-MSHP_DIRTY_CIRCLE)); bz(w_mo3_loop2); decf(v_mo3_dcnt,f); picLabel(w_mo3_loop2_done); #if PIC_CSIM if (dbg) { printf("m[%2d] cc=%-2d dc%-2d v_tmp=%d CHECK\n", (picFSR2()-RAMBUF_M2LIST)/5, picRV(v_mo3_ccnt), picRV(v_mo3_dcnt), picRV(v_tmp)); } #endif // // if only 1 then it must not be a circle // dcfsnz(v_tmp,f); bra(w_mo3_non_circle); // // should not be more than 128 // ASSERT(picRV(v_tmp) < 128); // // if (ccnt >= 5 || (ccnt>0 && ccnt+dcnt >= 6)) then STRONG CIRCLE // if (ccnt > 0) then WEAK CIRCLE // else not a circle at all // movf(v_mo3_ccnt,w); bz(w_mo3_non_circle); movff(v_mo3_msl,FSR2L); movff(v_mo3_msh,FSR2H); addlw(LOW(-5)); bnn(w_mo3_strong_circle); addwf(v_mo3_dcnt,w); addlw(LOW(5-6)); bnn(w_mo3_strong_circle); // // weak circle - make the whole thing be a dirty circle // picLabel(w_mo3_weak_circle); rcall(w_shp_read); movf(POSTDEC2,f); // back up to shape #if PIC_CSIM if (dbg) { printf("m[%2d] v_tmp=%d FIX: Make dirty %02x\n", (picFSR2()-RAMBUF_M2LIST-4)/5, picRV(v_tmp), picRV(INDF2)); } #endif ASSERT(MSHP_DIRTY_CIRCLE == 0); ASSERT(MSHP_CLEAN_CIRCLE == 2); movlw(2); subwf(INDF2,f); // turn clean circle into dirty movf(POSTINC2,w); andlw(MSHF_SHP_MASK); bz(w_mo3_weak_next); // // oops - it was not a clean circle. Put it back // movlw(2); movf(POSTDEC2,f); // back up to shape addwf(POSTINC2,f); // putit back the way it was #if PIC_CSIM if (dbg) { printf("m[%2d] v_tmp=%d UNFIX:\n", (picFSR2()-RAMBUF_M2LIST-4)/5, picRV(v_tmp)); } #endif picLabel(w_mo3_weak_next); decfsz(v_tmp,f); bra(w_mo3_weak_circle); bra(w_mo3_loop1); // // strong circle - set MFLG_CIRCLE // picLabel(w_mo3_strong_circle); rcall(w_shp_read); movf(POSTDEC2,f); // back up to shape #if PIC_CSIM if (dbg) { printf("m[%2d] v_tmp=%d FIX: MFLG_CIRCL %02x\n", (picFSR2()-RAMBUF_M2LIST-4)/5, picRV(v_tmp), picRV(INDF2)); } #endif ASSERT(MSHF_CIRCLE == (1<<5)); bsf(POSTINC2,5); // shape - set MFLG_CIRCLE decfsz(v_tmp,f); bra(w_mo3_strong_circle); bra(w_mo3_loop1); // // not a circle // picLabel(w_mo3_non_circle); // // loop until done // btfss(v_mo_angle,b_AFLG_END); bra(w_mo3_loop1); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif // // done // picReturn(); ASSERT(0); } //=========================================================================== // w_mo4_find_best_pulses: //=========================================================================== static void w_mo4_find_best_pulses(void) { #if PIC_CSIM int dbg = DBG_FINDPULSE; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif // // local variables // int picRegLocal(v_mo4_best_imp_mh); int picRegLocal(v_mo4_best_imp_ml); int picRegLocal(v_mo4_best_imph); int picRegLocal(v_mo4_best_impl); int picRegLocal(v_mo4_best_mag); int picRegLocal(v_mo4_best_mag_mh); int picRegLocal(v_mo4_best_mag_ml); int picRegLocal(v_mo4_next_mh); int picRegLocal(v_mo4_next_ml); int picRegLocal(v_mo4_prev_angle); int picRegLocal(v_mo4_prev_shape); int picRegLocal(v_mo4_sum_imph); int picRegLocal(v_mo4_sum_impl); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } if (!OPT_silent) { printf("start w_mo4_find_best_pulses\n"); } #endif lfsr(FSR2,RAMBUF_M2LIST+5); ASSERT(MSHP_CLEAN_CIRCLE != (0xff & MSHF_SHP_MASK)); setf(v_mo_shape); picLabel(w_mo4_outer_loop); movf(v_mo_shape,w); movwf(v_mo4_prev_shape); rcall(w_shp_read); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("READ1 ",&m-idx+2,&m,2); breakpt(); } #endif btfsc(v_mo_angle,b_AFLG_END); bra(w_mo4_done); // // keep going if PULSE or (DIRTY_CIRCLE && was not CLEAN_CIRCLE before) // movf(v_mo_shape,w); andlw(MSHF_SHP_MASK); ASSERT(MSHP_DIRTY_CIRCLE == 0); bnz(w_mo4_ocheck_pulse); // // its a DIRTY_CIRCLE - check if previous was a CLEAN_CIRCLE // movf(v_mo4_prev_shape,w); andlw(MSHF_SHP_MASK); addlw(-MSHP_CLEAN_CIRCLE); bz(w_mo4_outer_loop); bra(w_mo4_start_inner); picLabel(w_mo4_ocheck_pulse); addlw(-MSHP_PULSE); bnz(w_mo4_outer_loop); picLabel(w_mo4_start_inner); movf(v_mo_maxmag,w); movwf(v_mo4_best_mag); movf(v_mo_impl,w); movwf(v_mo4_best_impl); movwf(v_mo4_sum_impl); movf(v_mo_imph,w); movwf(v_mo4_best_imph); movwf(v_mo4_sum_imph); movf(FSR2L,w); movwf(v_mo4_best_imp_ml); movwf(v_mo4_best_mag_ml); movf(FSR2H,w); movwf(v_mo4_best_imp_mh); movwf(v_mo4_best_mag_mh); picLabel(w_mo4_inner_loop); movf(v_mo_angle,w); movwf(v_mo4_prev_angle); movf(FSR2L,w); movwf(v_mo4_next_ml); movf(FSR2H,w); movwf(v_mo4_next_mh); rcall(w_shp_read); #if PIC_CSIM if (dbg) { Motion2 m; int idx = (picRV(FSR2H)<<8) + picRV(FSR2L); idx -= RAMBUF_M2LIST; idx /= 5; memset(&m,0,sizeof(m)); m.shape = picRV(v_mo_shape); m.maxmag = picRV(v_mo_maxmag); m.imp = picRV(v_mo_impl) + (picRV(v_mo_imph) << 8); m.angle = picRV(v_mo_angle); printMotion2("READ2 ",&m-idx+2,&m,2); breakpt(); } #endif btfsc(v_mo_angle,b_AFLG_END); bra(w_mo4_inner_done); // // stop if pause detected // btfsc(v_mo_shape,b_MSHF_PREV_PAUSE); bra(w_mo4_inner_done); // // keep going if PULSE or (DIRTY_CIRCLE && not MSHF_CIRCLE) // movf(v_mo_shape,w); andlw(MSHF_SHP_MASK); ASSERT(MSHP_DIRTY_CIRCLE == 0); bnz(w_mo4_icheck_pulse); // // its a DIRTY_CIRCLE - check if MSHF_CIRCLE is set // btfsc(v_mo_shape,b_MSHF_CIRCLE); bra(w_mo4_inner_done); bra(w_mo4_check_angle); picLabel(w_mo4_icheck_pulse); addlw(-MSHP_PULSE); bnz(w_mo4_inner_done); picLabel(w_mo4_check_angle); // // check delta angle < 6 // movf(v_mo4_prev_angle,w); subwf(v_mo_angle,w); rcall(w_adiff); btfsc(WREG,7); negf(WREG); addlw(-6); bc(w_mo4_inner_done); // // check delta oct < 2 // movf(v_mo4_prev_angle,w); rcall(w_a2oct); movwf(v_mo4_prev_angle); movf(v_mo_angle,w); rcall(w_a2oct); subwf(v_mo4_prev_angle,w); rcall(w_odiff); btfsc(WREG,7); negf(WREG); ASSERT(picRV(WREG) != 0); decfsz(WREG,w); bra(w_mo4_inner_done); // // check for max magnitude // movf(v_mo_maxmag,w); cpfslt(v_mo4_best_mag); bra(w_mo4_check_imp); // // this is the best magnitude // movwf(v_mo4_best_mag); movf(FSR2L,w); movwf(v_mo4_best_mag_ml); movf(FSR2H,w); movwf(v_mo4_best_mag_mh); picLabel(w_mo4_check_imp); // // sum impulse // movf(v_mo_impl,w); addwf(v_mo4_sum_impl,f); movf(v_mo_imph,w); addwfc(v_mo4_sum_imph,f); btfsc(STATUS,C); setf(v_mo4_sum_imph); // // check for max impulse // movf(v_mo_impl,w); subwf(v_mo4_best_impl,w); movf(v_mo_imph,w); subwfb(v_mo4_best_imph,w); bc(w_mo4_inner_loop); // // this is the best impulse // movf(v_mo_impl,w); movwf(v_mo4_best_impl); movf(v_mo_imph,w); movwf(v_mo4_best_imph); movf(FSR2L,w); movwf(v_mo4_best_imp_ml); movf(FSR2H,w); movwf(v_mo4_best_imp_mh); bra(w_mo4_inner_loop); // // decide whether to set PLUS // picLabel(w_mo4_inner_done); // // sum of impulse >= 0x500 // movf(v_mo4_sum_imph,w); addlw(-5); bnc(w_mo4_next); // // best_impulse and best_magnitude should be the same // movf(v_mo4_best_imp_ml,w); movwf(FSR0L); subwf(v_mo4_best_mag_ml,w); bnz(w_mo4_next); movf(v_mo4_best_imp_mh,w); movwf(FSR0H); subwf(v_mo4_best_mag_mh,w); bnz(w_mo4_next); // // All conditions met - make it a PLUS // movf(POSTDEC0,w); // back up to preceding shape bsf(INDF0,b_MSHF_PLUS); picLabel(w_mo4_next); movf(v_mo4_next_ml,w); movwf(FSR2L); movf(v_mo4_next_mh,w); movwf(FSR2H); bra(w_mo4_outer_loop); picLabel(w_mo4_done); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif // // done // picReturn(); ASSERT(0); } //=========================================================================== // w_mo5_marklast: //=========================================================================== static void w_mo5_marklast(void) { #if PIC_CSIM int dbg = DBG_MARKLAST; int oldSilent = setSilent(OPT_silent); int oldTrace; if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif // // find end of motions // lfsr(FSR2,RAMBUF_M2LIST+5); picLabel(w_mo5_loop1); rcall(w_shp_read); btfss(v_mo_angle,6); bra(w_mo5_loop1); // // mark last 4 entries as non-plus (includes the END entry, so we are // really only marking 3) // movlw(4); movf(POSTDEC2,f); // point to shape of last entry picLabel(w_mo5_loop2); ASSERT(MSHF_PLUS==1); bcf(POSTDEC2,0); // turn off MSHF_PLUS bit in shape movf(POSTDEC2,f); // maxmag movf(POSTDEC2,f); // imph movf(POSTDEC2,f); // impl ASSERT(AFLG_START == (1<<5)); btfsc(POSTDEC2,5); // return if we hit start bra(w_mo5_done); decfsz(WREG,w); // loop until we have done 3 bra(w_mo5_loop2); picLabel(w_mo5_done); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); ASSERT(0); } //=========================================================================== // w_mo6_tokenize: //=========================================================================== static void w_mo6_tokenize(void) { #if PIC_CSIM int dbg = DBG_TOKENIZE; int oldSilent = setSilent(OPT_silent); int oldTrace; if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif // // read each motion and convert to token // FSR2 points to motions // FSR2 points to tokens // lfsr(FSR2,RAMBUF_M2LIST+5); lfsr(FSR0,RAMBUF_MTOKENS); picLabel(w_mo6_loop); rcall(w_shp_read); #if 1 // // for sanity, clear dir bit for pulses - NOT NECESSARY!?!?!? // ASSERT(MSHP_PULSE == 4); ASSERT(MSHP_PULSE_PLUS == 5); ASSERT(MSHF_PLUS == 1); ASSERT(MSHF_SHP_MASK == 7); movf(v_mo_shape,w); xorlw(0x04); andlw(0x06); btfsc(STATUS,Z); // pulse? bcf(v_mo_shape,3); // yes - clear DIR bit #endif rrncf(v_mo_angle,w); andlw(0x0f); movwf(INDF0); swapf(v_mo_shape,w); andlw(0xf0); iorwf(POSTINC0,f); btfss(v_mo_angle,6); bra(w_mo6_loop); movf(POSTDEC0,w); setf(INDF0); bcf(INDF0,0); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); ASSERT(0); } //=========================================================================== // w_mo7_one_circle: add circle or ocircle token. //=========================================================================== static void w_mo7_one_circle(void) { // // add a circle token (optional or not) // oct is calculated from v_mo7_circle_oct // v_mo7_circle_oct is incremented by dir and stored into v_mo7_circle_oct // int picRegInOutParam(v_mo7_circle_oct); // // Note: PICDST_BITb_mo7_endspells is global (end of spells) // Note: PICDST_BITb_mo7_prev_dir must match PICDST_BITb_MWN_DIR // int picRegInOutParam(v_mo7_bits); #define PICDST_BITb_mo7_was_23circle PICDST_BIT0 #define PICDST_BITb_mo7_was_pulse PICDST_BIT1 #define PICDST_BITb_mo7_optional PICDST_BIT2 #define PICDST_BITb_mo7_endspells PICDST_BIT3 #define PICDST_BITb_mo7_prev_dir PICDST_BIT6 movf(v_mo7_circle_oct,w); btfsc(TABLAT,b_MWN_DIR); bra(w_mo7_one_circle_cw); ASSERT(SSHP_OCIRCLE>SSHP_CIRCLE); addlw(1); andlw(7); movwf(v_mo7_circle_oct); addlw(1); andlw(7); rlncf(WREG,w); iorlw((SSHP_CIRCLE&7)<<4); btfsc(v_mo7_bits,b_mo7_optional); addlw(((SSHP_OCIRCLE-SSHP_CIRCLE)&7)<<4); movwf(POSTINC0); ASSERT(picRV16(FSR0L,FSR0H)<RAMBUF_STOKENS+RAMBUF_STOKENS_LEN); #if PIC_CSIM && DBG_LOADSPELL { int val = picRV(WREG); printf("%sWRITE circle %02x = %s %s\n", colorStr(4), val, spellTokenStr(val), colorStr(-1)); } #endif picReturn(); picLabel(w_mo7_one_circle_cw); ASSERT(SSHP_OCIRCLE>SSHP_CIRCLE); addlw(-1); andlw(7); movwf(v_mo7_circle_oct); addlw(-1); andlw(7); rlncf(WREG,w); iorlw((SSHP_CIRCLE&7)<<4); btfsc(v_mo7_bits,b_mo7_optional); addlw(((SSHP_OCIRCLE-SSHP_CIRCLE)&7)<<4); bsf(WREG,b_TOK_DIR); movwf(POSTINC0); ASSERT(picRV16(FSR0L,FSR0H)<RAMBUF_STOKENS+RAMBUF_STOKENS_LEN); #if PIC_CSIM && DBG_LOADSPELL { int val = picRV(WREG); printf("%sWRITE circle %02x = %s %s\n", colorStr(4), val, spellTokenStr(val), colorStr(-1)); } #endif picReturn(); } //=========================================================================== // w_mo7_one_pulse: add pulse or opulse token. W=oct //=========================================================================== static void w_mo7_one_pulse(void) { // // add pulse in direction of oct // int picRegInOutParam(v_mo7_bits); andlw(7); rlncf(WREG,w); iorlw((SSHP_OPULSE&7)<<4); ASSERT(SSHP_PULSE > SSHP_OPULSE); btfss(v_mo7_bits,b_mo7_optional); addlw(((SSHP_PULSE-SSHP_OPULSE)&7)<<4); movwf(POSTINC0); ASSERT(picRV16(FSR0L,FSR0H)<RAMBUF_STOKENS+RAMBUF_STOKENS_LEN); #if PIC_CSIM && DBG_LOADSPELL { int val = picRV(WREG); printf("%sWRITE pulse %02x = %s %s\n", colorStr(4), val, spellTokenStr(val), colorStr(-1)); } #endif picReturn(); } #if PIC_CSIM static void spell_read_byte(void); #endif //=========================================================================== // w_mo7_load_spell: load the next spell's tokens //=========================================================================== // // Input values // TBLPTR - ptr to next spell // Output values // WREG - 0=end-of-spells, 0xff=got spell // TBLPTR - ptr to next spell // w_mo_spellinfol,h - ptr to spellinfo for spell // w_mo_spell_len - # of tokens in spell // RAMBUF_STOKENS - contains spell tokens // static void w_mo7_load_spell(void) { #if PIC_CSIM int dbg = DBG_LOADSPELL; int oldSilent = setSilent(OPT_silent); int dbg_cnt; int oldTrace; if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #define SPELL_READ_BYTE() \ spell_read_byte() #else #define SPELL_READ_BYTE() \ tblrd*+ #endif // // parameters & return values // int picRegReturn(v_mo_spellinfoh); int picRegReturn(v_mo_spellinfol); int picRegReturn(v_mo_maxscore); int picRegReturn(v_mo_holdoff); int picRegReturn(v_mo_id); // // locals // #if PIC_CSIM int picRegLocal(v_tmp); #endif int picRegReturn(v_mo7_bits); int picRegLocal(v_mo7_circle_oct); int picRegLocal(v_mo7_cnt0); int picRegLocal(v_mo7_cnt1); // // START // clrf(v_mo7_bits); SPELL_READ_BYTE(); // spellinfol movf(TABLAT,w); movwf(v_mo_spellinfol); SPELL_READ_BYTE(); // spellinfoh movf(TABLAT,w); movwf(v_mo_spellinfoh); // // check for end of spells (spellinfo = 0xffff) // ASSERT(PIC_MWN_END_SPELLS == 0xffff); andwf(v_mo_spellinfol,w); infsnz(WREG,w); bra(w_mo7_end_spells); SPELL_READ_BYTE(); // maxscore movf(TABLAT,w); movwf(v_mo_maxscore); SPELL_READ_BYTE(); // holdoff movf(TABLAT,w); movwf(v_mo_holdoff); SPELL_READ_BYTE(); // id movf(TABLAT,w); movwf(v_mo_id); SPELL_READ_BYTE(); // starting octant movf(TABLAT,w); movwf(v_mo_oct); lfsr(FSR0,RAMBUF_STOKENS); // // always start with optional pulse in initial direction // bsf(v_mo7_bits,b_mo7_optional); rcall(w_mo7_one_pulse); // // first one is special since it follows a pause // SPELL_READ_BYTE(); // first spell token btfss(TABLAT,7); bra(w_mo7_add_first_circle); ASSERT(PIC_MWN_MORE(picRV(WREG))); //picLabel(w_mo7_add_first_pulse); bcf(v_mo7_bits,b_mo7_optional); bra(w_mo7_pulse_common); picLabel(w_mo7_add_first_circle); decf(v_mo_oct,w); btfsc(TABLAT,b_MWN_DIR); addlw(2); movwf(v_mo7_circle_oct); // initial direction movlw(1); movwf(v_mo7_cnt0); // optional circles (leading) movf(TABLAT,w); andlw(MWN_CNT_MASK); addlw(2+8-1-2); movwf(v_mo7_cnt1); // required circles bra(w_mo7_circle_common); ASSERT(picRV(TABLAT) & (1<<PICDST_BITb_MWN_MORE)); picLabel(w_mo7_outer_loop); #if !PIC_CSIM #if 0 movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); COUTL 'J' COUTL ' ' movf(v_mo_save_fsr0h,w); call(kk_outbyte); movf(v_mo_save_fsr0l,w); call(kk_outbyte); COUTL ' ' movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movf(POSTDEC0,w); movf(POSTINC0,w); call(kk_outbyte); call(kk_outcr); DB_FLUSH movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); #endif #endif bcf(v_mo7_bits,b_mo7_optional); SPELL_READ_BYTE(); // next spell token btfss(TABLAT,7); bra(w_mo7_circle); // // ADDING PULSE // //picLabel(w_mo7_pulse); btfss(v_mo7_bits,b_mo7_was_pulse); bra(w_mo7_pulse_was_circle); // // was pulse or opulse // // opposite oct as prev? (same as current oct) // movf(TABLAT,w); subwf(v_mo_oct,w); // v_mo_oct is curent oct andlw(7); bz(w_mo7_pulse_common); // // same oct as prev? (opposite of current oct) // andlw(3); bnz(w_mo7_pulse_angle); bsf(v_mo7_bits,b_mo7_optional); movf(TABLAT,w); rcall(w_mo7_one_pulse); bra(w_mo7_pulse_common); // // some other angle - add circle segments to connect pulses // picLabel(w_mo7_pulse_angle); bsf(v_mo7_bits,b_mo7_optional); movf(v_mo_oct,w); movwf(v_mo7_circle_oct); subwf(TABLAT,w); rcall(w_odiff); bcf(TABLAT,b_MWN_DIR); btfsc(WREG,7); bsf(TABLAT,b_MWN_DIR); #if PIC_CSIM dbg_cnt = 0; #endif picLabel(w_mo7_pulse_angle_loop); #if PIC_CSIM dbg_cnt++; #endif rcall(w_mo7_one_circle); movf(v_mo7_circle_oct,w); subwf(TABLAT,w); andlw(7); bnz(w_mo7_pulse_angle_loop); ASSERT(dbg_cnt>0 && dbg_cnt<4); bcf(v_mo7_bits,b_mo7_optional); bra(w_mo7_pulse_common); picLabel(w_mo7_pulse_was_circle); // // a pulse following a circle // movf(POSTDEC0,f); // back up 4 tokens movf(POSTDEC0,f); movf(POSTDEC0,f); movf(POSTDEC0,f); // // cnt = -1 // setf(v_mo7_cnt0); // // use prev dir for circles // bcf(TABLAT,b_MWN_DIR); btfsc(v_mo7_bits,b_mo7_prev_dir); bsf(TABLAT,b_MWN_DIR); // // v_tmp = -dir (dir ? 1 : -1) // setf(v_tmp); btfsc(v_mo7_bits,b_mo7_prev_dir); negf(v_tmp); // // oct = (last_oct - dir * 2) & 7; // movf(v_mo_oct,w); addwf(v_tmp,w); addwf(v_tmp,w); // // if preceded by more than 1 circle (ie 2 or 3) // btfss(v_mo7_bits,b_mo7_was_23circle); bra(w_mo7_pulse_circles1); movf(POSTDEC0,f); // back up a 5th token decf(v_mo7_cnt0,f); // cnt = -2 addwf(v_tmp,w); // oct = oct - dir picLabel(w_mo7_pulse_circles1); movwf(v_mo7_circle_oct); bra(w_mo7_pulse_circles1_loop_start); // // add circles (preceding the pulse) // picLabel(w_mo7_pulse_circles1_loop); rcall(w_mo7_one_circle); incf(v_mo7_cnt0,f); picLabel(w_mo7_pulse_circles1_loop_start); // // while((octc+prev_dir)&7) != oct) // movf(v_tmp,w); subwf(v_mo7_circle_oct,w); subwf(TABLAT,w); andlw(7); bnz(w_mo7_pulse_circles1_loop); // // if less than a full circle then add a whole optional circle // bsf(v_mo7_bits,b_mo7_optional); btfss(v_mo7_cnt0,7); bra(w_mo7_pulse_circles3); movlw(8); movwf(v_mo7_cnt0); picLabel(w_mo7_pulse_circles2_loop); rcall(w_mo7_one_circle); decfsz(v_mo7_cnt0,f); bra(w_mo7_pulse_circles2_loop); picLabel(w_mo7_pulse_circles3); rcall(w_mo7_one_circle); // 2 more optional circles rcall(w_mo7_one_circle); bcf(v_mo7_bits,b_mo7_optional); bra(w_mo7_pulse_common); picLabel(w_mo7_pulse_common); movf(TABLAT,w); addlw(4); andlw(7); movwf(v_mo_oct); rcall(w_mo7_one_pulse); bcf(v_mo7_bits,b_mo7_was_23circle); bsf(v_mo7_bits,b_mo7_was_pulse); bra(w_mo7_outer_loop); // // ADDING CIRCLE // picLabel(w_mo7_circle); btfss(TABLAT,b_MWN_MORE); bra(w_mo7_done); btfss(v_mo7_bits,b_mo7_was_pulse); bra(w_mo7_circle_was_circle); // // circle following a pulse // decf(v_mo_oct,w); btfsc(TABLAT,b_MWN_DIR); addlw(2); movwf(v_mo7_circle_oct); // initial direction movlw(3); movwf(v_mo7_cnt0); // optional circles (leading) movf(TABLAT,w); andlw(MWN_CNT_MASK); addlw(2+8-3-2); movwf(v_mo7_cnt1); // required circles bra(w_mo7_circle_common); picLabel(w_mo7_circle_was_circle); // // circle following a circle // ASSERT(PICDST_BITb_mo7_prev_dir == PICDST_BITb_MWN_DIR); movf(v_mo7_bits,w); xorwf(TABLAT,w); btfsc(WREG,b_MWN_DIR); bra(w_mo7_circle_was_opposite); // // circle following a circle in same direction // movf(POSTDEC0,f); // back up 3 tokens movf(POSTDEC0,f); movf(POSTDEC0,f); decf(v_mo_oct,w); btfsc(v_mo7_bits,b_mo7_prev_dir); addlw(2); movwf(v_mo7_circle_oct); // cnt0 = 0 movf(TABLAT,w); andlw(MWN_CNT_MASK); addlw(2+8-2); movwf(v_mo7_cnt1); // required circles bra(w_mo7_circle_common_no0); picLabel(w_mo7_circle_was_opposite); // // circle following a circle in opposite direction // bsf(v_mo7_bits,b_mo7_optional); movf(v_mo_oct,w); addlw(4); rcall(w_mo7_one_pulse); // opulse opposite of last dir movf(v_mo_oct,w); addlw(5); btfsc(v_mo7_bits,b_mo7_prev_dir); addlw(-2); rcall(w_mo7_one_pulse); // same plus prevdir movf(v_mo_oct,w); addlw(4); rcall(w_mo7_one_pulse); // opulse opposite of last dir (again) // // oct = last + 4 - dir // movf(v_mo_oct,w); addlw(3); btfsc(TABLAT,b_MWN_DIR); addlw(2); andlw(7); movwf(v_mo_oct); movwf(v_mo7_circle_oct); movlw(2); movwf(v_mo7_cnt0); // optional circles (leading) movf(TABLAT,w); andlw(MWN_CNT_MASK); addlw(2+8-2-2); movwf(v_mo7_cnt1); // required circles // fall thru to w_mo7_circle_common //bra(w_mo7_circle_common); picLabel(w_mo7_circle_common); bsf(v_mo7_bits,b_mo7_optional); picLabel(w_mo7_circle_common0); rcall(w_mo7_one_circle); decfsz(v_mo7_cnt0,f); bra(w_mo7_circle_common0); picLabel(w_mo7_circle_common_no0); bcf(v_mo7_bits,b_mo7_optional); picLabel(w_mo7_circle_common1); rcall(w_mo7_one_circle); decfsz(v_mo7_cnt1,f); bra(w_mo7_circle_common1); // // last count is always 3 // bsf(v_mo7_bits,b_mo7_optional); rcall(w_mo7_one_circle); rcall(w_mo7_one_circle); rcall(w_mo7_one_circle); // // set b_mo7_was_23circle (0=1 circle. 1=2 or 3 circles) // bcf(v_mo7_bits,b_mo7_was_23circle); movf(TABLAT,w); andlw(MWN_CNT_MASK); btfss(STATUS,Z); bsf(v_mo7_bits,b_mo7_was_23circle); // // set prev dir // bcf(v_mo7_bits,b_mo7_prev_dir); btfsc(TABLAT,b_MWN_DIR); bsf(v_mo7_bits,b_mo7_prev_dir); bcf(v_mo7_bits,b_mo7_was_pulse); bra(w_mo7_outer_loop); picLabel(w_mo7_done); // // last optional pulse to stop motion of wand // movf(v_mo_oct,w); addlw(4); bsf(v_mo7_bits,b_mo7_optional); rcall(w_mo7_one_pulse); // // end of spell marked by 0x00 // ASSERT(STOKEN_END == 0); clrf(POSTINC0); ASSERT(picRV16(FSR0L,FSR0H)<RAMBUF_STOKENS+RAMBUF_STOKENS_LEN); #if PIC_CSIM && DBG_LOADSPELL { int val = 0; printf("%sWRITE end %02x = %s %s\n", colorStr(4), val, spellTokenStr(val), colorStr(-1)); } #endif picLabel(w_mo7_done2); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); picLabel(w_mo7_end_spells); bsf(v_mo7_bits,b_mo7_endspells); bra(w_mo7_done2); ASSERT(0); } //=========================================================================== // w_moa_score_tok: //=========================================================================== static void w_moa_score_tok(void) { #if PIC_CSIM int dbg = DBG_SCORETOK; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif int picRegParam(v_moa_stok); int picRegParam(v_moa_mtok); int picRegReturn(v_moa_signore); int picRegReturn(v_moa_mignore); int picRegReturn(v_moa_match); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif #if PIC_CSIM { int stok = picRV(v_moa_stok); int mtok = picRV(v_moa_mtok); int mshape = TOKEN_SHAPE(mtok); int sshape = TOKEN_SHAPE(stok); if (dbg) { printf("%sw_moa_score_tok compare mtok= %s %02x ", colorStr(2), motionTokenStr(mtok), mtok); printf("%02x %s =stok%s\n", stok, spellTokenStr(stok), colorStr(-1)); } switch(mshape) { case MSHP_DIRTY_CIRCLE: case MSHP_DIRTY_CIRCLE_PLUS: case MSHP_CLEAN_CIRCLE_PLUS: case MSHP_CLEAN_CIRCLE: case MSHP_PULSE: case MSHP_PULSE_PLUS: case MSHP_CIRCLE_GAP: break; case MSHP_PAUSE: default: ASSERT(!"Bad motion token"); } switch(sshape) { case SSHP_CIRCLE: case SSHP_OCIRCLE: case SSHP_OPULSE: case SSHP_PULSE: break; case SSHP_PAUSE: case SSHP_WILD: default: ASSERT(!"Bad spell token"); } } #endif ASSERT(picRV16(FSR2L,FSR2H) == RAMBUF_SD_MOTION_IGNORE); // // score for ignoring spell token // ASSERT(TOK_SHAPE_MASK == 0x70); swapf(v_moa_stok,w); iorlw(0xf8); movf(PLUSW2,w); movwf(v_moa_signore); // // score for ignoring motion token // ASSERT(TOK_SHAPE_MASK == 0x70); swapf(v_moa_mtok,w); andlw(7); movf(PLUSW2,w); movwf(v_moa_mignore); #define FAST_SCORE_TOK 0 #if FAST_SCORE_TOK // // lookup token pair in RAMBUF_STBL1 // swapf(v_moa_mtok,w); andlw(0x0f); movwf(FSR2L); movf(v_moa_stok,w); andlw(0xf0); iorwf(FSR2L,f); decf(FSR2H,f); movf(INDF2,w); bnn(w_moa_done_imm); // // lookup angle difference in RAMBUF_STBL2 // movwf(FSR2L); movf(v_moa_stok,w); subwf(v_moa_mtok,w); andlw(0x0f); iorwf(FSR2L,f); decf(FSR2H,f); movf(INDF2,w); picLabel(w_moa_done_imm); movwf(v_moa_match); lfsr(FSR2,RAMBUF_SD_MOTION_IGNORE); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); #else setf(v_moa_match); ASSERT(SSHP_CIRCLE == 1); ASSERT(SSHP_OCIRCLE == 2); ASSERT(SSHP_OPULSE == 3); ASSERT(SSHP_PULSE == 4); swapf(v_moa_stok,w); addlw(-1); btfss(WREG,1); bra(w_moa_circle); // // Spell is a pulse // swapf(v_moa_mtok,w); andlw(7); addlw(-MSHP_CIRCLE_GAP); bz(w_moa_done); //addlw(MSHP_CIRCLE_GAP-MSHP_PAUSE); //bz(w_moa_done); ASSERT(TOK_ANGLE_MASK == 0x0f); movf(v_moa_stok,w); subwf(v_moa_mtok,w); btfsc(WREG,3); negf(WREG); andlw(0xf); addlw(-3); bn(w_moa_zero); // delta angle <= 45 degrees - score 0 bnz(w_moa_done); // big angle - score infinite movlw(6); // off by 67.5 deg - score 6 movwf(v_moa_match); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); // // Spell is a circle // picLabel(w_moa_circle); // // infinite score if different octant // ASSERT(TOK_ANGLE_MASK == 0x0f); ASSERT((picRV(v_moa_stok)&1) == 0); #if FIX_CIRCLE_OCT_COMPARE movf(v_moa_mtok,w); subwf(v_moa_stok,w); btfsc(WREG,3); negf(WREG); andlw(0x0e); bnz(w_moa_done); #else incf(v_moa_mtok,w); subwf(v_moa_stok,w); andlw(0x0e); bnz(w_moa_done); #endif // // does dir match? // movf(v_moa_mtok,w); xorwf(v_moa_stok,w); btfss(WREG,b_TOK_DIR); bra(w_moa_zero); // match - score 0 // // only care about dir if mshape is a circle (not a pulse) // ASSERT(MSHP_PULSE_PLUS == MSHP_PULSE+1); swapf(v_moa_mtok,w); addlw(-MSHP_PULSE); andlw(6); btfsc(STATUS,Z); // if PULSE score 0 (noskip), else score infinite picLabel(w_moa_zero); clrf(v_moa_match); picLabel(w_moa_done); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); #endif ASSERT(0); } #if PIC_CSIM //=========================================================================== // check_data_table() //=========================================================================== static void check_data_table(void) { ASSERT(RAMBUF_SD_SPELL_IGNORE == 0x900); ASSERT(picRV(0x900) == 100); ASSERT(picRV(0x901) == 15); ASSERT(picRV(0x902) == 0); ASSERT(picRV(0x903) == 1); ASSERT(picRV(0x904) == 100); ASSERT(picRV(0x905) == 255); ASSERT(picRV(0x906) == 255); ASSERT(picRV(0x907) == 255); ASSERT(RAMBUF_SD_MOTION_IGNORE == 0x908); ASSERT(picRV(0x908) == 1); ASSERT(picRV(0x909) == 20); ASSERT(picRV(0x90a) == 1); ASSERT(picRV(0x90b) == 100); ASSERT(picRV(0x90c) == 1); ASSERT(picRV(0x90d) == 100); ASSERT(picRV(0x90e) == 0); ASSERT(picRV(0x90f) == 0); } #endif //=========================================================================== // w_mo9_score_spell: //=========================================================================== static void w_mo9_score_spell(void) { #if PIC_CSIM int dbg = DBG_SCORESPELL; int oldSilent = setSilent(OPT_silent); int oldTrace; #endif //int picRegInOutParam(v_mo9_dbg_cnt); int picRegReturn(v_mo9_score); int picRegLocal(v_mo9_corner); int picRegLocal(v_moa_stok); int picRegLocal(v_moa_mtok); int picRegLocal(v_moa_signore); int picRegLocal(v_moa_mignore); int picRegLocal(v_moa_match); int picRegLocal(v_mo9_minscore); int picRegInOutParam(v_mo_best2_score); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } check_data_table(); #endif // // setup matrix // ASSERT(picRV16(FSR2L,FSR2H) == RAMBUF_SD_MOTION_IGNORE); lfsr(FSR1,RAMBUF_STOKENS); lfsr(FSR0,RAMBUF_MMATRIX); clrf(INDF0); setf(v_mo9_score); picLabel(w_mo9_setup_loop); #if !PIC_CSIM #if 0 movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); COUTL 'Z' COUTL ' ' movf(INDF1,w); call(kk_outbyte); call(kk_outcr); DB_FLUSH movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); #endif #endif // // find value for ignoring spell token // swapf(POSTINC1,w); // spell token iorlw(0xf8); movf(PLUSW2,w); // score for ignoring spell token // // add to previous val, then store in next // addwf(POSTINC0,w); btfsc(STATUS,C); setf(WREG); movwf(INDF0); movf(INDF1,w); bnz(w_mo9_setup_loop); // // Matrix is now set up // // // RAMBUF_STOKENS must be RAMBUF_MMATRIX with 0x100 bit set // ASSERT(RAMBUF_STOKENS == (RAMBUF_MMATRIX | 0x100)); ASSERT(RAMBUF_MMATRIX == (RAMBUF_STOKENS & ~0x100)); // // Loop over motions // FSR1 points to motion tokens // FSR0 points to matrix and spell tokens // lfsr(FSR1,RAMBUF_MTOKENS); // // Get first motion token // movf(POSTINC1,w); movwf(v_moa_mtok); picLabel(w_mo9_motion_loop); lfsr(FSR0,RAMBUF_MMATRIX); // start of matrix (and spell-tokens) movf(INDF0,w); movwf(v_mo9_corner); swapf(v_moa_mtok,w); // motion token shape andlw(7); movf(PLUSW2,w); // score for ignoring motion token addwf(v_mo9_corner,w); btfsc(STATUS,C); setf(WREG); movwf(v_mo9_score); movwf(v_mo9_minscore); movwf(INDF0); // store first value in ignore-motion column 0 bsf(FSR0H,0); // point to RAMBUF_STOKENS movf(POSTINC0,w); // get first spell token picLabel(w_mo9_spell_loop); movwf(v_moa_stok); bcf(FSR0H,0); // point to RAMBUF_MMATRIX rcall(w_moa_score_tok); // // value if spell is ignored // movf(v_moa_signore,w); addwf(v_mo9_score,f); btfsc(STATUS,C); setf(v_mo9_score); // keep best score in v_mo9_score // // value if matched // movf(v_mo9_corner,w); addwf(v_moa_match,w); bc(w_mo9_check_im); cpfslt(v_mo9_score); // accumulate minimum into v_mo9_score movwf(v_mo9_score); // // value if motion is ignored // picLabel(w_mo9_check_im); movf(INDF0,w); movwf(v_mo9_corner); addwf(v_moa_mignore,w); bc(w_mo9_save); cpfslt(v_mo9_score); // accumulate minimum into v_mo9_score movwf(v_mo9_score); picLabel(w_mo9_save); movf(v_mo9_score,w); movwf(INDF0); // save score into matrix cpfslt(v_mo9_minscore); movwf(v_mo9_minscore); // track min score #if 0 #if !PIC_CSIM movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); COUTL ' ' COUTL ' ' movf(v_mo9_score,w); call(kk_outbyte); call(kk_outcr); DB_FLUSH movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); #endif #endif bsf(FSR0H,0); // point to RAMBUF_STOKENS movf(POSTINC0,w); // next spell token bnz(w_mo9_spell_loop); // loop (unless end of spell) // // if min score in row is greater than best2 score then no point in // continuing. // movf(v_mo_best2_score,w); cpfslt(v_mo9_minscore); bra(w_mo9_abort); // v_mo9_minscore >= v_mo_best2_score // // done with spell loop // // Get next motion token & check for end. // movf(POSTINC1,w); // motion token movwf(v_moa_mtok); addlw(-MTOKEN_END); bnz(w_mo9_motion_loop); // // Done with scoring - v_mo9_score contains final score // picLabel(w_mo9_done); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); check_data_table(); #endif picReturn(); picLabel(w_mo9_abort); #if 0 movf(POSTINC1,w); // motion token addlw(-MTOKEN_END); bnz(w_mo9_abort); bra(w_mo9_done); #else #if PIC_CSIM #if 0 printf("Abort becasue v_mo9_minscore (%02x) >= v_mo_best2_score (%02x)\n", picRV(v_mo9_minscore), picRV(v_mo_best2_score)); #endif #endif setf(v_mo9_score); bra(w_mo9_done); #endif ASSERT(0); } //=========================================================================== // w_mo8_load_data_tables: //=========================================================================== static void w_mo8_load_data_tables(void) { #if FAST_SCORE_TOK // // RAMBUF_STBL1 - shape combos // in // bits // 7-4 stok shape & dir // 3-0 mtok shape & dir // neg = use angle table // pos = use value // lfsr(FSR2,RAMBUF_STBL1+0x10); // stok = 0 = PAUSE (UNUSED) // stok = 1 = CIRCLE // SAME DIR //0x80 // 0 MSHP_DIRTY_CIRCLE //0x80 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x80 // 2 MSHP_CLEAN_CIRCLE //0x80 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x80 // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); // OPPOSITE DIR //0x7f // 0 MSHP_DIRTY_CIRCLE //0x7f // 1 MSHP_DIRTY_CIRCLE_PLUS //0x7f // 2 MSHP_CLEAN_CIRCLE //0x7f // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 2 = OCIRCLE // SAME DIR //0x80 // 0 MSHP_DIRTY_CIRCLE //0x80 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x80 // 2 MSHP_CLEAN_CIRCLE //0x80 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x80 // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); // OPPOSITE DIR //0x7f // 0 MSHP_DIRTY_CIRCLE //0x7f // 1 MSHP_DIRTY_CIRCLE_PLUS //0x7f // 2 MSHP_CLEAN_CIRCLE //0x7f // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 3 = OPULSE // SAME DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // OPPOSITE DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 4 = PULSE // SAME DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // OPPOSITE DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 5 = NEVER // stok = 6 = NEVER // stok = 7 = NEVER lfsr(FSR2,RAMBUF_STBL1+0x90); // stok = 0 = PAUSE (UNUSED) // stok = 1 = CIRCLE // OPPOSITE DIR //0x7f // 0 MSHP_DIRTY_CIRCLE //0x7f // 1 MSHP_DIRTY_CIRCLE_PLUS //0x7f // 2 MSHP_CLEAN_CIRCLE //0x7f // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // SAME DIR //0x80 // 0 MSHP_DIRTY_CIRCLE //0x80 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x80 // 2 MSHP_CLEAN_CIRCLE //0x80 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x80 // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); // stok = 2 = OCIRCLE // OPPOSITE DIR //0x7f // 0 MSHP_DIRTY_CIRCLE //0x7f // 1 MSHP_DIRTY_CIRCLE_PLUS //0x7f // 2 MSHP_CLEAN_CIRCLE //0x7f // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // SAME DIR //0x80 // 0 MSHP_DIRTY_CIRCLE //0x80 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x80 // 2 MSHP_CLEAN_CIRCLE //0x80 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x80 // 4 MSHP_PULSE //0x80 // 5 MSHP_PULSE_PLUS //0x80 // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x80); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); // stok = 3 = OPULSE // OPPOSITE DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // SAME DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 4 = PULSE // OPPOSITE DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // SAME DIR //0x90 // 0 MSHP_DIRTY_CIRCLE //0x90 // 1 MSHP_DIRTY_CIRCLE_PLUS //0x90 // 2 MSHP_CLEAN_CIRCLE //0x90 // 3 MSHP_CLEAN_CIRCLE_PLUS //0x90 // 4 MSHP_PULSE //0x90 // 5 MSHP_PULSE_PLUS //0x7f // 6 MSHP_CIRCLE_GAP //0x7f // 7 MSHP_PAUSE (UNUSED) movlw(0x90); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); // stok = 5 = NEVER // stok = 6 = NEVER // stok = 7 = NEVER // RAMBUF_STBL2 - second table // // 0x80 = (adiff>2) ? 0x7f : 0 // 0x90 = scorePulse(adiff/2) // lfsr(FSR2,RAMBUF_STBL2+0x80); // // (adiff>2) ? 0x7f : 0 // adiff val // 0 = 0 00 // 1 = 2 00 // 2 = 4 7f // 3 = 6 7f // 4 = 8 7f // 5 = 10 7f // 6 = 12 7f // 7 = 14 7f // 8 = 16 7f // 9 = 14 7f // a = 12 7f // b = 10 7f // c = 8 7f // d = 6 7f // e = 4 7f // f = 2 00 movlw(0x7f); clrf(POSTINC2); clrf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); clrf(POSTINC2); // // scorePulse(adiff/2) // adiff val // 0 = 0 00 // 1 = 2 00 // 2 = 4 00 // 3 = 6 06 // 4 = 8 7f // 5 = 10 7f // 6 = 12 7f // 7 = 14 7f // 8 = 16 7f // 9 = 14 7f // a = 12 7f // b = 10 7f // c = 8 7f // d = 6 06 // e = 4 00 // f = 2 00 clrf(POSTINC2); clrf(POSTINC2); clrf(POSTINC2); movlw(0x06); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movwf(POSTINC2); movlw(0x06); movwf(POSTINC2); clrf(POSTINC2); clrf(POSTINC2); #endif // // RAMBUF_SD_SPELL_IGNORE table // lfsr(FSR2,RAMBUF_SD_SPELL_IGNORE); movlw(100); movwf(POSTINC2); // SSHP_PAUSE = 100 movlw(15); movwf(POSTINC2); // SSHP_CIRCLE = 15 clrf(POSTINC2); // SSHP_OCIRCLE = 0 movlw(1); movwf(POSTINC2); // SSHP_OPULSE = 1 movlw(100); movwf(POSTINC2); // SSHP_PULSE = 100 setf(POSTINC2); // SSHP_WILD (unused) setf(POSTINC2); // (unused) setf(POSTINC2); // (unused) // // RAMBUF_SD_MOTION_IGNORE table // ASSERT(picRV16(FSR2L,FSR2H) == RAMBUF_SD_MOTION_IGNORE); movlw(1); movwf(POSTINC2); // 1, = MSHP_DIRTY_CIRCLE, movlw(20); movwf(POSTINC2); // 20, = MSHP_DIRTY_CIRCLE_PLUS, movlw(1); movwf(POSTINC2); // 1, = MSHP_CLEAN_CIRCLE, movlw(100); movwf(POSTINC2); // 100, = MSHP_CLEAN_CIRCLE_PLUS, movlw(1); movwf(POSTINC2); // 1, = MSHP_PULSE, movlw(100); movwf(POSTINC2); // 100, = MSHP_PULSE_PLUS, clrf(POSTINC2); // 0, = MSHP_CIRCLE_GAP, clrf(POSTINC2); // 0, = MSHP_PAUSE, #if !USE_LEDSCAN // // RAMBUF_SD_LED table - scan back and forth while calc // ASSERT(picRV16(FSR2L,FSR2H) == RAMBUF_SD_LED); movlw(0xef); movwf(POSTINC2); movlw(0xdf); movwf(POSTINC2); movlw(0xbf); movwf(POSTINC2); movlw(0x7f); movwf(POSTINC2); movlw(0xbf); movwf(POSTINC2); movlw(0xdf); movwf(POSTINC2); movlw(0xef); movwf(POSTINC2); movlw(0xf7); movwf(POSTINC2); #endif lfsr(FSR2,RAMBUF_SD_MOTION_IGNORE); picReturn(); ASSERT(0); } //=========================================================================== // w_mo8_check_spells: //=========================================================================== static void w_mo8_check_spells(void) { #if PIC_CSIM int dbg = DBG_CHECKSPELLS; int oldSilent = setSilent(OPT_silent); int oldTrace; int w_motion_spells = 0; int w_spellinfo_default = 0; // // In wand these are different registers (the return value) // int v_spell_ptrl = picRegId(v_mo_spellinfol); int v_spell_ptrh = picRegId(v_mo_spellinfoh); // // these are equ constants // int MAX_MAXSCORE = gMaxMaxscore; int MAX_HOLDOFF = gMaxHoldoff; #endif int picRegLocal(v_mo_spellinfoh); int picRegLocal(v_mo_spellinfol); int picRegLocal(v_mo_maxscore); int picRegLocal(v_mo_holdoff); int picRegLocal(v_mo_id); int picRegLocal(v_mo9_score); int picRegLocal(v_mo9_dbg_cnt); // counter for debugging // // b_mo7_endspells bit indicates last spell was loaded // int picRegLocal(v_mo7_bits); // // 1st best spell info // int picRegLocal(v_mo_best1_infol); int picRegLocal(v_mo_best1_infoh); int picRegLocal(v_mo_best1_score); int picRegLocal(v_mo_best1_maxscore); int picRegLocal(v_mo_best1_holdoff); int picRegLocal(v_mo_best1_id); // // 2nd best spell info // int picRegLocal(v_mo_best2_infol); int picRegLocal(v_mo_best2_infoh); int picRegLocal(v_mo_best2_score); //int picRegLocal(v_mo_best2_maxscore); #if PIC_CSIM if (dbg) { oldSilent = setSilent(0); oldTrace = picTrace(1); } else { oldTrace = picTrace(0); } #endif rcall(w_mo8_load_data_tables); // // init results // movlw(0xfe); movwf(v_mo9_score); movwf(v_mo_best1_score); movlw(MAX_MAXSCORE+MAX_HOLDOFF); movwf(v_mo_best2_score); clrf(v_mo_best1_maxscore); setf(v_mo_best1_holdoff); movlw(w_spellinfo_default&0xff); movwf(v_mo_best1_infol); movwf(v_mo_best2_infol); movlw(w_spellinfo_default>>8); movwf(v_mo_best1_infoh); movwf(v_mo_best2_infoh); clrf(v_mo_best1_id); clrf(v_mo9_dbg_cnt); // // start of mwaneme spell data // movlw((w_motion_spells)&0xff); movwf(TBLPTRL); movlw((w_motion_spells)>>8); movwf(TBLPTRH); picLabel(w_mo8_outer_loop); // // get next spell // rcall(w_mo7_load_spell); // // debug counter // #if !PIC_CSIM btfss RCSTA,SPEN bra(w_mo8_skip_sp); movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); COUTL 'S' COUTL 'p' movf(v_mo9_dbg_cnt,w); call(kk_outbyte); COUTL ' ' movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); picLabel(w_mo8_skip_sp); #else if (!OPT_silent) { printf("Sp%02x ", picRV(v_mo9_dbg_cnt)); } #endif incf(v_mo9_dbg_cnt,f); #if USE_LEDSCAN #if !PIC_CSIM call(w_ledscan); #endif #else movf(v_mo9_dbg_cnt,w); andlw(0x07); addlw(RAMBUF_SD_LED-RAMBUF_SD_MOTION_IGNORE); movf(PLUSW2,w); movwf(TRISB); #endif // // done with all spells? // btfsc(v_mo7_bits,b_mo7_endspells); bra(w_mo8_done); // // get spell score // rcall(w_mo9_score_spell); #if !PIC_CSIM btfss RCSTA,SPEN bra(w_mo8_skip_sc); movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); COUTL 'S' COUTL 'c' COUTL '=' movf(v_mo9_score,w); call(kk_outbyte); call(kk_outcr); DB_FLUSH call(w_main_run) btfsc(bk_rs_halt); picReturn(); movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); picLabel(w_mo8_skip_sc); #else if (!OPT_silent) { printf("Sc=%02x\n", picRV(v_mo9_score)); } #endif // // best spell so far? // movf(v_mo9_score,w); cpfslt(v_mo_best1_score); bra(w_mo8_new_best1); // // same id as best spell? // movf(v_mo_id,w); subwf(v_mo_best1_id,w); bz(w_mo8_outer_loop); // // 2nd best spell so far? // movf(v_mo9_score,w); cpfslt(v_mo_best2_score); bra(w_mo8_new_best2); bra(w_mo8_outer_loop); picLabel(w_mo8_new_best1); movf(v_mo_id,w); subwf(v_mo_best1_id,w); bz(w_mo8_new_best1_sameid); //movff(v_mo_best1_maxscore,v_mo_best2_maxscore); movff(v_mo_best1_score,v_mo_best2_score); movff(v_mo_best1_infol,v_mo_best2_infol); movff(v_mo_best1_infoh,v_mo_best2_infoh); picLabel(w_mo8_new_best1_sameid); movff(v_mo9_score,v_mo_best1_score); movff(v_mo_spellinfol,v_mo_best1_infol); movff(v_mo_spellinfoh,v_mo_best1_infoh); movff(v_mo_maxscore,v_mo_best1_maxscore); movff(v_mo_holdoff,v_mo_best1_holdoff); movff(v_mo_id,v_mo_best1_id); bra(w_mo8_outer_loop); picLabel(w_mo8_new_best2); movwf(v_mo_best2_score); movff(v_mo_spellinfol,v_mo_best2_infol); movff(v_mo_spellinfoh,v_mo_best2_infoh); //movff(v_mo_maxscore,v_mo_best2_maxscore); bra(w_mo8_outer_loop); picLabel(w_mo8_done); // // maxscore is the threshold. score must be less than or equal to this // to count. // // holdoff is the minimum (best2_score-best1_score) // // // default: no spell // #if PIC_CSIM clrf(v_spell_ptrl); clrf(v_spell_ptrh); #endif #if !PIC_CSIM btfss RCSTA,SPEN bra(w_mo8_skip_res); movff(FSR0L,v_mo_save_fsr0l); movff(FSR0H,v_mo_save_fsr0h); movff(FSR1L,v_mo_save_fsr1l); movff(FSR1H,v_mo_save_fsr1h); movff(FSR2L,v_mo_save_fsr2l); movff(FSR2H,v_mo_save_fsr2h); call(kk_outcr); COUTL 'R' COUTL 'e' COUTL 's' COUTL ' ' movf(v_mo_best1_score,w); call(kk_outbyte); COUTL ' ' movf(v_mo_best2_score,w); call(kk_outbyte); COUTL ' ' COUTL 'x' COUTL ' ' movf(v_mo_best1_maxscore,w); call(kk_outbyte); //COUTL ' ' //movf(v_mo_best2_maxscore,w); //call(kk_outbyte); COUTL ' ' COUTL 'h' COUTL ' ' movf(v_mo_best1_holdoff,w); call(kk_outbyte); call(kk_outcr); DB_FLUSH movff(v_mo_save_fsr0l,FSR0L); movff(v_mo_save_fsr0h,FSR0H); movff(v_mo_save_fsr1l,FSR1L); movff(v_mo_save_fsr1h,FSR1H); movff(v_mo_save_fsr2l,FSR2L); movff(v_mo_save_fsr2h,FSR2H); picLabel(w_mo8_skip_res); #endif // // Do we already have a spell (rythm spell)? // #if !PIC_CSIM btfsc b_got_spell bra w_mo8_done2 #endif // // is score >= maxscore? // movf(v_mo_best1_score,w); subwf(v_mo_best1_maxscore,w); bnc(w_mo8_done2); // no, score too high #if 0 // // is score2 >= maxscore2? // movf(v_mo_best2_score,w); subwf(v_mo_best2_maxscore,w); bc(w_mo8_done2); // yes, score too low (avoid choose wrong) #endif // // is best2_score-best1_score > holdoff // movf(v_mo_best1_score,w); subwf(v_mo_best2_score,w); subwf(v_mo_best1_holdoff,w); bc(w_mo8_done2); // no - too close // // success! spell is good! // movff(v_mo_best1_infol,v_spell_ptrl); movff(v_mo_best1_infoh,v_spell_ptrh); #if !PIC_CSIM bsf b_got_spell #endif picLabel(w_mo8_done2); #if PIC_CSIM setSilent(oldSilent); picTrace(oldTrace); #endif picReturn(); ASSERT(0); } //=========================================================================== // w_check_motion_spell: convert accbuf to motions and check acc spell //=========================================================================== static void w_check_motion_spell(void) { #if PIC_CSIM if (!OPT_silent2) { printf("Using w_check_motion_spell:\n"); } #endif call(w_mo1_parse1); call(w_mo2_fill_circle_gaps); call(w_mo3_find_weak_circles); call(w_mo4_find_best_pulses); call(w_mo5_marklast); call(w_mo6_tokenize); // // check for less than 3 motion tokens // lfsr(FSR2,RAMBUF_MTOKENS); movf(POSTINC2,w); addlw(-MTOKEN_END); bz(w_cms_done); movf(POSTINC2,w); addlw(-MTOKEN_END); bz(w_cms_done); movf(POSTINC2,w); addlw(-MTOKEN_END); bz(w_cms_done); rcall(w_mo8_check_spells); picLabel(w_cms_done); picReturn(); ASSERT(0); } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:27:46 PDT 2007