/************************************************/ /* */ /* routines this module lcd_3 - */ /* vs 07/04/2013 at 08:00 */ /* */ /* 0) void setup */ /* 1) void loop */ /* 1) begin_ram - init ram memory check */ /* 2) int freeram - return available ram space */ /* 3) get_stars - read star data from eprom */ /* 4) gettgt_1 - select a calibration star */ /* 2) dgrepos - get axis degree position */ /* 2) mresolve_1 - get axes tiks/rev menu */ /* 3) mbklash_1 - get axes backlash measurement */ /* 1) corpos - get backlash corrected position */ /* 2) menugo - operate a 4 line menu/options */ /* 3) rabl_acw - get single axis backlash parms */ /* 2) byte getkbd - read buttons w. s/w debounce*/ /* 2) byte getkbd2 - read keyboard buttons */ /* 2) getpos - return decimal cnt of a channel */ /* 1) makbin - convert 8 chars to a long int */ /* 2) suckc - wait for a char on a serial line */ /* 2) lcd_out_msg - write a string */ /* 2) mak_lcd_lut - make lcd lookup table */ /* 3) setrowcol - set DDRAM address to row,col */ /* 3) init_lcd - set up lcd */ /* 4) clrlcd - clear LCD display */ /* 4) wbytir - write byte to instruction reg */ /* 5) wnibir - write nibble to instruction reg */ /* 4) wbytdr - write byte to data reg */ /* 5) wnibdr - write nibble to data reg */ /* 6) cycle_ena_latch - cycle lcd enable latch */ /* 7) select_ireg - select lcd instruction reg */ /* 8) select dreg - select lcd data reg */ /* 9) select write - select write to lcd */ /* 0) select_read - select read from lcd */ /* */ /************************************************/ /************************************************/ /* */ /* direct Port i/o */ /* PORTB bits to arduino pin #: */ /* 0 1 2 3 4 5 6 7 BIT# */ /* 8 9 10 11 12 13 (xtl6,xtl7) -ino dig pin# */ /* */ /* PORTB to arduino digital pin masks: */ /* Pin 8 = 0x01 */ /* Pin 9 = 0x02 */ /* Pin10 = 0x04 */ /* Pin11 = 0x08 */ /* Pin12 = 0x10 */ /* Pin13 = 0x20 */ /* */ /* PORTD maps to arduino dig pins 0 to 7 */ /* PORTD masks: */ /* Pin 0 = 0x01 */ /* Pin 1 = 0x02 */ /* Pin 2 = 0x04 */ /* Pin 3 = 0x08 */ /* pin 4 = 0x10 */ /* pin 5 = 0x20 */ /* pin 6 = 0x40 */ /* pin 7 = 0x80 */ /* */ /* PORTC maps to anlogue pins A0-A5 or digital */ /* pins 14-19 */ /* Pin 14 = 0x01, analogue A0 */ /* Pin 15 = 0x02, A1 */ /* Pin 16 = 0x04, A2 */ /* */ /************************************************/ /* define bright star database in program memory */ #include /* define constellations */ prog_char cnstell_00[] PROGMEM = "Andromeda"; prog_char cnstell_01[] PROGMEM = "Aquila"; prog_char cnstell_02[] PROGMEM = "Auriga"; prog_char cnstell_03[] PROGMEM = "Bootes"; prog_char cnstell_04[] PROGMEM = "Canis Major"; prog_char cnstell_05[] PROGMEM = "Canis Minor"; prog_char cnstell_06[] PROGMEM = "Cassiopeia"; prog_char cnstell_07[] PROGMEM = "Corona Borealis"; prog_char cnstell_08[] PROGMEM = "Gemini"; prog_char cnstell_09[] PROGMEM = "Gemini"; prog_char cnstell_10[] PROGMEM = "Cygnus"; prog_char cnstell_11[] PROGMEM = "Leo"; prog_char cnstell_12[] PROGMEM = "Leo"; prog_char cnstell_13[] PROGMEM = "Lyra"; prog_char cnstell_14[] PROGMEM = "Orion"; prog_char cnstell_15[] PROGMEM = "Orion"; prog_char cnstell_16[] PROGMEM = "Perseus"; prog_char cnstell_17[] PROGMEM = "Pegasus"; prog_char cnstell_18[] PROGMEM = "Scorpio"; prog_char cnstell_19[] PROGMEM = "Taurus"; prog_char cnstell_20[] PROGMEM = "Ursa Major"; prog_char cnstell_21[] PROGMEM = "Ursa Major"; prog_char cnstell_22[] PROGMEM = "Ursa Minor"; prog_char cnstell_23[] PROGMEM = "Virgo"; /* define constellation string addresses */ PROGMEM const prog_char *cnstell_addr[] = {cnstell_00,cnstell_01,cnstell_02,cnstell_03,cnstell_04,cnstell_05, cnstell_06,cnstell_07,cnstell_08,cnstell_09,cnstell_10,cnstell_11,cnstell_12,cnstell_13,cnstell_14, cnstell_15,cnstell_16,cnstell_17,cnstell_18,cnstell_19,cnstell_20,cnstell_21,cnstell_22,cnstell_23}; /* define star names */ prog_char stname_00[] PROGMEM = "Alpheratz a And"; prog_char stname_01[] PROGMEM = "Altair a Aql"; prog_char stname_02[] PROGMEM = "Capella a Aur"; prog_char stname_03[] PROGMEM = "Arcturus a Boo"; prog_char stname_04[] PROGMEM = "Sirius a CMa"; prog_char stname_05[] PROGMEM = "Procyon a CMi"; prog_char stname_06[] PROGMEM = "Schedar a Cas"; prog_char stname_07[] PROGMEM = "Alphecca a CrB"; prog_char stname_08[] PROGMEM = "Castor a Gem"; prog_char stname_09[] PROGMEM = "Pollux b Gem"; prog_char stname_10[] PROGMEM = "Deneb a Cyg"; prog_char stname_11[] PROGMEM = "Regulus a Leo"; prog_char stname_12[] PROGMEM = "Denebola b Leo"; prog_char stname_13[] PROGMEM = "Vega a Lyr"; prog_char stname_14[] PROGMEM = "Betelgeuse a Ori"; prog_char stname_15[] PROGMEM = "Rigel b Ori"; prog_char stname_16[] PROGMEM = "Mirfak a Per"; prog_char stname_17[] PROGMEM = "Scheat b Peg"; prog_char stname_18[] PROGMEM = "Antares a Sco"; prog_char stname_19[] PROGMEM = "Aldebaran a Tau"; prog_char stname_20[] PROGMEM = "Dubhe a UMa"; prog_char stname_21[] PROGMEM = "Alkaid e UMa"; prog_char stname_22[] PROGMEM = "Polaris UMi"; prog_char stname_23[] PROGMEM = "Spica a Vir"; /* define star name string addresses */ PROGMEM const prog_char *stname_addr[] = {stname_00,stname_01,stname_02,stname_03,stname_04,stname_05, stname_06,stname_07,stname_08,stname_09,stname_10,stname_11,stname_12,stname_13,stname_14, stname_15,stname_16,stname_17,stname_18,stname_19,stname_20,stname_21,stname_22,stname_23}; /* define star J2000.0 coordinates RA hrs, mins sec, DEC degrees, mins, secs */ PROGMEM prog_int16_t stcoord_00[] = {0, 8, 23, 29, 5, 26}; /* Alpheratz*/ PROGMEM prog_int16_t stcoord_01[] = {19, 50, 47, 8, 52, 06}; /* Aquila */ PROGMEM prog_int16_t stcoord_02[] = {5, 16, 41, 45, 59, 53}; /* Capella */ PROGMEM prog_int16_t stcoord_03[] = {14, 15, 40, 19, 10, 57}; /* Arcturus */ PROGMEM prog_int16_t stcoord_04[] = {6, 45, 9, -16, 42, 58}; /* Sirius */ PROGMEM prog_int16_t stcoord_05[] = {7, 39, 18, 5, 13, 30}; /* Procyon */ PROGMEM prog_int16_t stcoord_06[] = {0, 40, 31, 56, 32, 14}; /* Schedar */ PROGMEM prog_int16_t stcoord_07[] = {15, 34, 41, 26, 42, 53}; /* Alphecca */ PROGMEM prog_int16_t stcoord_08[] = {7, 34, 36, 31, 53, 18}; /* Castor */ PROGMEM prog_int16_t stcoord_09[] = {7, 45, 19, 28, 1, 34}; /* Pollux */ PROGMEM prog_int16_t stcoord_10[] = {20, 41, 26, 45, 16, 49}; /* Deneb */ PROGMEM prog_int16_t stcoord_11[] = {10, 8, 22, 11, 58, 02}; /* Regulus */ PROGMEM prog_int16_t stcoord_12[] = {11, 49, 4, 14, 34, 19}; /* Denebola */ PROGMEM prog_int16_t stcoord_13[] = {18, 36, 56, 38, 47, 01}; /* Vega */ PROGMEM prog_int16_t stcoord_14[] = {5, 55, 10, 7, 24, 25}; /* Betelgeuse */ PROGMEM prog_int16_t stcoord_15[] = {5, 14, 32, -8, 12, 06}; /* Rigel */ PROGMEM prog_int16_t stcoord_16[] = {3, 24, 19, 49, 51, 40}; /* Mirfak */ PROGMEM prog_int16_t stcoord_17[] = {23, 3, 47, 28, 4, 58}; /* Scheat */ PROGMEM prog_int16_t stcoord_18[] = {16, 29, 24, -26, 25, 55}; /* Antares */ PROGMEM prog_int16_t stcoord_19[] = {4, 35, 55, 16, 30, 33}; /* Aldeberan */ PROGMEM prog_int16_t stcoord_20[] = {11, 3, 44, 61, 45, 3}; /* Dubhe */ PROGMEM prog_int16_t stcoord_21[] = {13, 47, 32, 49, 18, 48}; /* Alkaid */ PROGMEM prog_int16_t stcoord_22[] = {2, 31, 49, 89, 15, 51}; /* Polaris */ PROGMEM prog_int16_t stcoord_23[] = {13, 25, 12, -11, 9, 41}; /* Spica */ /* define star co-ord addresses */ PROGMEM const prog_int16_t *stcoord_addr[] = {stcoord_00,stcoord_01,stcoord_02,stcoord_03,stcoord_04,stcoord_05, stcoord_06,stcoord_07,stcoord_08,stcoord_09,stcoord_10,stcoord_11,stcoord_12,stcoord_13,stcoord_14, stcoord_15,stcoord_16,stcoord_17,stcoord_18,stcoord_19,stcoord_20,stcoord_21,stcoord_22,stcoord_23}; /* define d/base size and addresses */ #define NSTARS 24 prog_int16_t *coord_ptr; /************************************************/ /* Serial input pins to arduino */ /* */ /* Encoder chan 1 (RA) = pin 10 */ /* Encoder chan 2 (DEC) = pin 9 */ /* */ /* Assume on PORTB at 9600 baud */ /* */ /************************************************/ /* define memory free space counter */ #define RAMWRNG 0x0200 /* max space = 0x07ff */ int memchk; int startram; /* define debug event signal pin */ int sigout = 8; /*PortB */ int setsig = 0x01; int clrsig = ~0x01; /* define serial i/p lines - PortB */ #define ISRAMSK 0x04 #define ISDECMSK 0x02 int serial1 = 10; int serial2 = 9; byte serial1_msk = ISRAMSK; byte serial2_msk = ISDECMSK; /* define 9600 baud us time delays */ #define DLA9600 100 /* 104 us delay - 9600 baud = 104us bit width */ #define DLA9600_2 50 /* define maximum wait for serial start bit - us */ #define MAX_SER_WAIT 9900 /************************************************/ /* Keyboard input pins to arduino */ /* */ /* Up = Pin 14, PortC, 0x01 */ /* Down - Pin 7, PortD, 0x80 */ /* Left - Pin 6, PortD, 0x40 */ /* Right - Pin 15, PortC, 0x02 */ /* Enter - Pin 16, PortC, 0x04 */ /* */ /* */ /************************************************/ /* define keyboard lines */ int key_up = 14; byte key_up_msk = 0x01; byte ISKUP = 0x01; int key_dwn = 7; byte key_dwn_msk = 0x80; byte ISKDWN = 0x02; int key_lft = 6; byte key_lft_msk = 0x40; byte ISKLFT = 0x04; int key_rght = 15; byte key_rght_msk = 0x02; byte ISKRGHT = 0x08; int key_ntr = 16; byte key_ntr_msk = 0x04; byte ISKNTR = 0x10; /* null key */ byte ISKNULL = 0x80; /* define keyboard delays */ #define DEBOUNCE 1 /* 20 msec */ #define HUMAN 500 /* 2 seconds to read screen */ /************************************************/ /* LCD to arduino pin outs */ /* */ /* LCD RS = pin 13 */ /* LCD RW = pin 12 */ /* LCD ENA = pin 11 */ /* LCD D4 = pin 5 */ /* LCD D5 = pin 4 */ /* LCD D6 = pin 3 */ /* LCD D7 = pin 2 */ /* */ /************************************************/ /* define LCD control lines - PortB */ int lcd_rs=13; int lcd_rw=12; int lcd_ena=11; int lcd_rs_msk=0x20; int lcd_rw_msk=0x10; int lcd_ena_msk=0x08; /* define LCD data bus lines - Port D */ int lcd_d4 = 5; int lcd_d5= 4; int lcd_d6=3; int lcd_d7=2; int lcd_d4_msk=0x20; int lcd_d5_msk=0x10; int lcd_d6_msk=0x08; int lcd_d7_msk=0x04; byte lcd_xclear; /* nibble to clear lcd data bus */ /* define lcd data xlate lookup table */ byte lcd_lut[16]; /* define o/p string for LCD */ char outstr[81]; /* define working global variables */ /* RA and DEC tik counts and direction indicators */ long int rapos; long int decpos; int radir; int decdir; const char postxt[] = "POS"; const char negtxt[] = "NEG"; char *ra_dirtxt, *dec_dirtxt; /* axis backlash variables, fwd and rev */ #define RA_BL_FWD 75 /* Pos to neg direction: N(measure) > N(true), so Nt = Nm - (+ve correction) */ #define RA_BL_REV -75 /* Neg to pos direction: Nm < Nt, so Nt = Nm - (-ve correction) */ #define DEC_BL_FWD 75 #define DEC_BL_REV -75 int ra_fwdbl, ra_revbl; int dec_fwdbl, dec_revbl; /* backlash corrected counts and flags */ long int cor_rapos, sav_rapos; long int cor_decpos, sav_decpos; int cor_radir; int cor_decdir; /* define ticks per resolution */ #define EDGES 4 #define TEETH 48 #define RATIO 64 #define SECND 40 #define PRIMR 58 long int RA_RES; long int DEC_RES; long int ra_resolve; long int dec_resolve; double ra_degrees; double dec_degrees; int ra_hrs; int ra_mins; int ra_secs; int dec_deg; int dec_mins; int dec_secs; /* define float o/p string length */ #define DEGLEN 10 char ra_degtxt[DEGLEN+1]; char dec_degtxt[DEGLEN+1]; /* define calibration values */ int align_is_set; /* value >0 if align procedure completed */ int align_star_index; /* index to database of ref stars */ /* save system time at alignment */ unsigned long int align_systime; /* save aligned axis offsets - degrees */ double align_ra_offst; double align_dec_offst; int dec_is_2ndhs; /* flag if DEC in primary hemisphere */ /************************************************/ /* */ /************************************************/ void setup() { /************************************************/ /* */ /* setup - initialize pins as outputs etc */ /* */ /************************************************/ /* define autos */ /* set up debug signal line */ pinMode(sigout,OUTPUT); digitalWrite(sigout,HIGH); /* setup keyboard lines as input */ pinMode(key_up, INPUT); pinMode(key_dwn, INPUT); pinMode(key_lft, INPUT); pinMode(key_rght, INPUT); pinMode(key_ntr, INPUT); /* setup serial lines as input */ pinMode(serial1, INPUT); pinMode(serial2, INPUT); /* set LCDd control lin as o/p */ pinMode(lcd_rs,OUTPUT); digitalWrite(lcd_rs,LOW); pinMode(lcd_rw,OUTPUT); digitalWrite(lcd_rw,LOW); pinMode(lcd_ena,OUTPUT); digitalWrite(lcd_ena,LOW); /* set LCD data bus lines as o/p */ pinMode(lcd_d4,OUTPUT); digitalWrite(lcd_d4,LOW); pinMode(lcd_d5,OUTPUT); digitalWrite(lcd_d5,LOW); pinMode(lcd_d6,OUTPUT); digitalWrite(lcd_d6,LOW); pinMode(lcd_d7,OUTPUT); digitalWrite(lcd_d7,LOW); /*now create lcd LUT to convert data nibble to lcd bus pattern */ mak_lcd_lut(lcd_lut); /* now initialise the lcd */ init_lcd(); /* write string to lcd */ clrlcd(); lcd_out_msg(0,0,"hello Vivienne!"); /* init rotation indicators */ radir = 1; decdir = 1; cor_radir=1; cor_decdir=1; ra_dirtxt = (char *) postxt; dec_dirtxt = (char *) postxt; cor_rapos=0; sav_rapos=0; cor_decpos=0; cor_decpos=0; /* load default backlash settings */ ra_fwdbl = RA_BL_FWD; ra_revbl = RA_BL_REV; dec_fwdbl = DEC_BL_FWD; dec_revbl = DEC_BL_REV; /* load default axis resolution settings */ RA_RES = (long) EDGES; RA_RES *= (long) TEETH; RA_RES *= (long) RATIO; RA_RES *= (long) PRIMR; RA_RES /= (long) SECND; DEC_RES=RA_RES; ra_resolve = RA_RES; dec_resolve = DEC_RES; ra_degrees=0; dec_degrees=0; /* signal align is not set */ align_is_set = -1; dec_is_2ndhs = -1; /* wait a bit */ delay(1000); } /************************************************/ /* */ /************************************************/ void loop() { /************************************************/ /* */ /* loop - loop */ /* */ /************************************************/ /* declare autos */ int retc; /* mem check init */ begin_ram(); /* clear the lcd */ clrlcd(); /* loop forever */ for(;;) { /* run backlash menu */ mbklash_1(&retc); /* get number of ticks per revolution */ mresolve_1(&retc); /* report position */ clrlcd(); delay(HUMAN); for (;;) { /* get RA position */ dgrpos(serial1_msk,&rapos,&radir,&ra_dirtxt, &cor_rapos,&sav_rapos,&cor_radir, ra_fwdbl,ra_revbl,&ra_degrees, ra_resolve,ra_degtxt,&retc); sprintf(outstr,"RA = %s %s",ra_degtxt,ra_dirtxt); lcd_out_msg(0,0,outstr); sprintf(outstr,"RA = %2.1ihr %2.1imn %2.1is",ra_hrs,ra_mins,ra_secs); lcd_out_msg(2,0,outstr); setrowcol(0,0); /* get DEC position */ //getpos(serial2_msk,&decpos,&decdir,&dec_dirtxt,&retc); //corpos(serial2_msk,&decpos,&decdir,&dec_dirtxt, //&cor_decpos,&sav_decpos,&cor_decdir, //dec_fwdbl,dec_revbl,&retc); //sprintf(outstr,"DEC = %-10.1li %s",cor_decpos,dec_dirtxt); /* get DEC position */ dgrpos(serial2_msk,&decpos,&decdir,&dec_dirtxt, &cor_decpos,&sav_decpos,&cor_decdir, dec_fwdbl,dec_revbl,&dec_degrees, dec_resolve,dec_degtxt,&retc); sprintf(outstr,"DEC = %s %s",dec_degtxt,dec_dirtxt); lcd_out_msg(1,0,outstr); sprintf(outstr,"DEC = %2.1idg %2.1imn %2.1is",dec_deg,abs(dec_mins),abs(dec_secs)); lcd_out_msg(3,0,outstr); setrowcol(0,0); /* read keyboard */ retc = (int) getkbd(); /* skip out on a key */ if(retc != 0) break; } /* end inner loop forever */ /* get a calibration star */ gettgt_1(&retc); /* report stack ptr */ clrlcd(); sprintf(outstr,"RAM free = 0x%04x",memchk); lcd_out_msg(3,0,outstr); setrowcol(3,0); delay(HUMAN); /* wait for a key */ for (;;) { /* read keyboard */ retc = (int) getkbd(); /* skip out on a key */ if(retc != 0) break; } /* end inner loop forever */ } /* end loop forever */ } /* end main */ /************************************************/ /* */ /************************************************/ int begin_ram () { /********************************************************/ /* */ /* routine inits amount of free ram */ /* */ /* heap grows up from static variable storeage area */ /* */ /********************************************************/ /* init gobal memchk */ memchk=0x07ff; memchk=freeram(); startram=memchk; } /* end begin_ram */ /************************************************/ /* */ /************************************************/ int freeram () { /********************************************************/ /* */ /* routine returns amount of free ram */ /* */ /* heap grows up from static variable storeage area */ /* stack grows down from top of memory to the heap */ /* stack ptr == address of last defined auto variable */ /* */ /* __brkval = has value equal to top of the heap */ /* __heap_start = located at bottom of heap == */ /* address of top of statics */ /* */ /* ATM328 chip has 2K of SRAm = 0x00 to 0x07ff */ /* */ /********************************************************/ /* declare external variables */ extern int __heap_start, *__brkval; /* define autos */ int v; /* check if top of heap is zero */ if(__brkval == 0) { /* compute bottom of stack to top of statics */ v = (int) &v - (int) &__heap_start; } else { /* compute bottom of stack to top of heap */ v = (int) &v - (int) __brkval; } /* save free space if smallest so far */ if(v < memchk) { /* debug break here */ memchk=v; } /* debug */ if (v< RAMWRNG) { memchk=v; } /* end if < 5% left */ /* pass value back */ return v; } /* end freeram */ /************************************************/ /* */ /************************************************/ void get_stars(int istar,char *st_const, char *st_name,int *rah,int *ram,int *ras, int *decd,int *decm,int *decs, int *retc) { /************************************************/ /* */ /* routine returns star details from eprom */ /* */ /************************************************/ /* define autos */ /* check search index in range*/ *retc = 1; if(istar < 0 || istar >= NSTARS) { *retc = -1; return; } /* end errr return */ /* write a constellation legend - copy string text to ram buffer */ strcpy_P(st_const, (prog_char *) pgm_read_word(&(cnstell_addr[istar]))); /* write a star legend - copy string text to ram buffer */ strcpy_P(st_name, (prog_char *) pgm_read_word(&(stname_addr[istar]))); /* get star coords */ coord_ptr = (prog_int16_t *) pgm_read_word(&(stcoord_addr[istar])); *rah= pgm_read_word(coord_ptr+0); *ram= pgm_read_word(coord_ptr+1); *ras= pgm_read_word(coord_ptr+2); *decd= pgm_read_word(coord_ptr+3); *decm= pgm_read_word(coord_ptr+4); *decs= pgm_read_word(coord_ptr+5); /* if a -v1 DEC angle, make sure mins and secs are too */ if(*decd<0) *decm = -1*abs(*decm); if(*decm<0) *decs = -1*abs(*decs); } /*end get_stars */ /************************************************/ /* */ /************************************************/ void gettgt_1(int *endcode) { /************************************************/ /* */ /* routine returns chosen target star */ /* */ /************************************************/ /* define autos */ int istar,istar_sav; int rah,ram,ras,decd,decm,decs; int retc,retc2; char st_const[21],st_name[21],st_ax1[21],st_ax2[21]; /* poll keyboard */ retc =1; istar = 0; istar_sav=-1; for (;;) { /* get hold of star data for display */ if(istar != istar_sav) { get_stars(istar,st_const, st_name,&rah,&ram,&ras,&decd,&decm,&decs,&retc); istar_sav=istar; } /* write scroll/select star data menu */ menugo(st_const,st_name,"Scroll^v LFT/RGHT","OK->ENTER Quit->UP", ISKLFT,ISKRGHT,ISKNTR,ISKUP,ISKNULL,&retc); /* calibrate backlash */ switch(retc) { case 1: /* scroll up */ istar--; if(istar<0) istar = NSTARS-1; break; case 2: /* scroll down */ istar++; if(istar >= NSTARS) istar = 0; break; case 3: /* select star */ sprintf(st_ax1,"RA=%2.1ihr %2.1imn %2.1is",rah,ram,ras); sprintf(st_ax2,"DEC=%2.1idg %2.1imn %2.1is",decd,abs(decm),abs(decs)); menugo(st_name,st_ax1,st_ax2,"Align->ENTR Quit->UP", ISKUP,ISKNTR,ISKNULL,ISKNULL,ISKNULL,&retc2); istar_sav=-1; /* force a screen update */ retc=1; /*signal continue */ /* align axes */ if(retc2==2) { /* signal break */ retc = -1; /* signal align is not set for duration of measurement */ align_is_set = -1; /* save index of target star and co-ords*/ align_star_index = istar; /* save system time of alignement */ align_systime = millis(); /* update - unaligned - current position */ dgrpos(serial1_msk,&rapos,&radir,&ra_dirtxt, &cor_rapos,&sav_rapos,&cor_radir, ra_fwdbl,ra_revbl,&ra_degrees, ra_resolve,ra_degtxt,&retc); dgrpos(serial2_msk,&decpos,&decdir,&dec_dirtxt, &cor_decpos,&sav_decpos,&cor_decdir, dec_fwdbl,dec_revbl,&dec_degrees, dec_resolve,dec_degtxt,&retc); /* compute the dec offset = Ref Star DEC - system DEC */ align_dec_offst = (float) decd + ((float) decm)/60.0 + ((float) decs)/3600.0; /*convert -ve dec to a 360 clock */ if(align_dec_offst < 0.0) align_dec_offst = 360.0 + align_dec_offst; /* compute offset */ align_dec_offst -= dec_degrees; /* compute the RA offset - for time now */ align_ra_offst = (float) rah + ((float) ram)/60.0 + ((float) ras)/3600.0; align_ra_offst *= 360.0/24.0; align_ra_offst -= ra_degrees; /* signal system is now aligned */ align_is_set = 1; /* signal exit */ retc =-1; } /* end aligned */ break; case 4: /* quit */ retc = -1; /* skip out*/ break; case 5: default: break; } /* end switch retc */ /* see if leave forever loop */ if(retc<0) break; } /* end loop forever */ /* pick up return code */ *endcode = retc; } /* end gettgt */ /************************************************/ /* */ /************************************************/ void dgrpos(byte chanmsk, long int *chanpos, int *chandir, char **a_chandir, long int *cor_chanpos,long int *savpos,int *cor_chandir, int postoneg, int negtopos, double *axdegr, int resolve, char *degtxt, int *retc) { /************************************************/ /* */ /* routine returns axis position in degrees */ /* */ /************************************************/ /* define autos */ long unsigned int delta_t; double mins_axis,fdelta_t; float dsign; int iturns; corpos(chanmsk,chanpos,chandir,a_chandir, cor_chanpos,savpos,cor_chandir, postoneg,negtopos,retc); /* now convert ticks to degrees */ *axdegr = (double) *cor_chanpos; *axdegr = *axdegr/(double) resolve; iturns = (int) *axdegr; *axdegr = *axdegr - (double) iturns; *axdegr *= 360.0; if(*axdegr < 0) *axdegr = 360.0 + *axdegr; /* if ra axis, divide into hrs/mins/secs */ if(chanmsk == ISRAMSK) { /* if axis is aligned -apply any correction */ if(align_is_set >0) { *axdegr += align_ra_offst; /* add on any time passed */ delta_t =(millis()-align_systime)/1000; fdelta_t =delta_t; /* convert seconds of time to degrees of arc: 1 sec time = 15 secs of arc */ fdelta_t *= (15.0/3600.00); /* add on RA time correction - a fixed axis advances 15 sec of RA in 1 sec of time */ *axdegr += fdelta_t; /* recondition modulo 360 again */ if(*axdegr > 360.0) *axdegr = *axdegr - 360.0; if(*axdegr < 0) *axdegr = 360.0 + *axdegr; /* if DEC in 2nd hemisphere rotate RA 180 degrees */ if(dec_is_2ndhs > 0) { if(*axdegr >= 180.0) {*axdegr -= 180.0;} else { *axdegr += 180.0;} } /* end switch dec hemispheres */ } /* end apply RA align offset */ mins_axis = *axdegr * (24.0 * 60.0)/360.0; ra_hrs = (int) (mins_axis/60.0); ra_mins = (int) (mins_axis - 60.0 * (float) ra_hrs); ra_secs = (int) (60.0 * (mins_axis - 60.0 * (float) ra_hrs - (float) ra_mins)); } /* end if ra axis */ /* if dec axis, divide into deg/mins/secs */ else { /* make dec axis +ve rotation sense */ *axdegr = 360.0 - *axdegr; /* if axis is aligned -apply any correction */ if(align_is_set >0) { *axdegr += align_dec_offst; if(*axdegr < 0.0) *axdegr = 360.0 + *axdegr; if(*axdegr > 360.0) *axdegr -= 360.0; /* aligned dec axis - sort out quadrants */ dec_is_2ndhs = -1; if(*axdegr >90.0 && *axdegr <= 270.0) { *axdegr = 180.0 - *axdegr; /* set flag for dec in second hemisphere */ dec_is_2ndhs = 1; } else if(*axdegr >270.0 && *axdegr <= 360.0) { *axdegr = *axdegr - 360.0; } } /* end apply align correction */ /* obtain fractional degrees - beware sign */ mins_axis = *axdegr * 60; dsign = 1; if(mins_axis < 0.0) dsign = -1.0; mins_axis = abs(mins_axis); /* get mins and secs of absolute value */ dec_deg = (int) (mins_axis/60.0); dec_mins = (int) (mins_axis - 60.0 * (float) dec_deg); dec_secs = (int) (60.0 * (mins_axis - 60.0 * (float) dec_deg - (float) dec_mins)); /* restore sign and sign components */ mins_axis *= dsign; dec_deg *= dsign; dec_mins *= dsign; dec_secs *= dsign; } /* end if dec axis */ /* convert float value */ dtostrf(*axdegr,DEGLEN,3, degtxt); } /* end dgrpos */ /************************************************/ /* */ /************************************************/ void mresolve_1(int *endcode) { /************************************************/ /* */ /* routine returns runs backlash #1 menu */ /* */ /************************************************/ /* define autos */ int retc,retc2; /* poll keyboard */ for (;;) { /* write resolution menu */ menugo("Cal RA tks/rv-> UP","Std RA tks/rv-> DWN","Cal DEC tks/rv-> LFT","Std DEC tks/rv-> RHT", ISKUP,ISKDWN,ISKLFT,ISKRGHT,ISKNTR,&retc); /* calibrate backlash */ switch(retc) { case 1: /* calibrate RA */ ra_resolve = RA_RES; break; case 2: /* standard RA */ ra_resolve = RA_RES; sprintf(outstr,"RA tiks/rev=%li",ra_resolve); menugo(outstr,"Values OK-> ENTER","Select again-> UP","\0", ISKUP,ISKNTR,ISKNULL,ISKNULL,ISKNULL,&retc2); retc=1; /*signal continue */ if(retc2==2) retc=-1; /*signal break */ break; case 3: /* calibrate DEC */ dec_resolve = DEC_RES; break; case 4: dec_resolve = DEC_RES; sprintf(outstr,"DEC tiks/rev=%li",dec_resolve); menugo(outstr,"Values OK-> ENTER","Select again-> UP","\0", ISKUP,ISKNTR,ISKNULL,ISKNULL,ISKNULL,&retc2); retc=1; /*signal continue */ if(retc2==2) retc=-1; /*signal break */ break; case 5: retc = -1; /* skip out*/ default: break; } /* end switch retc */ /* see if leave forever loop */ if(retc<0) break; } /* end loop forever */ /* pick up return code */ *endcode = retc; } /* end mresolve_1 */ /************************************************/ /* */ /************************************************/ void mbklash_1(int *endcode) { /************************************************/ /* */ /* routine returns runs backlash #1 menu */ /* */ /************************************************/ /* define autos */ int retc,retc2; /* loop pooling options */ for (;;) { /* write backlash menu */ menugo("Cal backlash-> UP","Zero b/lash-> DWN","View current-> LFT","Deflt b/lash-> RHT", ISKUP,ISKDWN,ISKLFT,ISKRGHT,ISKNTR,&retc); /* calibrate backlash */ switch(retc) { case 1: /* get RA AC/W backlash */ rabl_acw(serial1_msk,&rapos,&radir,ra_dirtxt,"RA",1,&ra_fwdbl,&retc); //if(retc<0) break; rabl_acw(serial1_msk,&rapos,&radir,ra_dirtxt,"RA",-1,&ra_revbl,&retc); //if(retc<0) break; /* get DEC AC/W backlash */ rabl_acw(serial2_msk,&decpos,&decdir,dec_dirtxt,"DEC",1,&dec_fwdbl,&retc); //if(retc<0) break; rabl_acw(serial2_msk,&decpos,&decdir,dec_dirtxt,"DEC",-1,&dec_revbl,&retc); //if(retc<0) break; /* signal break */ retc=-1; break; case 2: /* zero backlash parms */ ra_fwdbl =0; ra_revbl = 0; dec_fwdbl = 0; dec_revbl = 0; sprintf(outstr,"%4i %4i %4i %4i",ra_fwdbl, ra_revbl, dec_fwdbl, dec_revbl); menugo("RA Fw-Rev DC Fw-Rev",outstr,"Values OK-> ENTER","Select again-> UP", ISKNULL,ISKNULL,ISKNTR,ISKUP,ISKNULL, &retc2); retc=1; /*signal continue */ if(retc2==3) retc=-1; /*signal break */ break; case 3: /* view current parms */ sprintf(outstr,"%4i %4i %4i %4i",ra_fwdbl, ra_revbl, dec_fwdbl, dec_revbl); menugo("RA Fw-Rev DC Fw-Rev",outstr,"Values OK-> ENTER","Select again-> UP", ISKNULL,ISKNULL,ISKNTR,ISKUP,ISKNULL, &retc2); retc=1; /*signal continue */ if(retc2==3) retc=-1; /*signal break */ break; case 4: /* load default backlash parms */ ra_fwdbl = RA_BL_FWD; ra_revbl = RA_BL_REV; dec_fwdbl = DEC_BL_FWD; dec_revbl = DEC_BL_REV; sprintf(outstr,"%4i %4i %4i %4i",ra_fwdbl, ra_revbl, dec_fwdbl, dec_revbl); menugo("RA Fw-Rev DC Fw-Rev",outstr,"Values OK-> ENTER","Select again-> UP", ISKNULL,ISKNULL,ISKNTR,ISKUP,ISKNULL, &retc2); retc=1; /*signal continue */ if(retc2==3) retc=-1; /*signal break */ break; case 5: default: retc = -1; break; } /* end switch retc */ /* see if leave forever loop */ if(retc<0) break; } /* end loop forever */ /* pick up return code */ *endcode = retc; } /* end mbklash_1 */ /************************************************/ /* */ /************************************************/ void corpos(byte chanmsk, long int *chanpos, int *chandir, char **a_chandir, long int *cor_chanpos,long int *savpos,int *cor_chandir, int postoneg, int negtopos,int *retc) { /************************************************/ /* */ /* routine returns position of selected channel */ /* */ /************************************************/ /* define autos */ /*get latest chanel tik count and direction */ getpos(chanmsk,chanpos,chandir,a_chandir,retc); /* get pos change */ *cor_chanpos += (*chanpos-*savpos); *savpos = *chanpos; /* see if direction change - correct count */ if(*cor_chandir != *chandir) { /* if pos to neg */ if(*cor_chandir >0) { *cor_chanpos -= (long int) postoneg; } /* end if pos to neg */ else { *cor_chanpos -= (long int) negtopos; } /* end if neg to pos */ /* save new direction */ *cor_chandir = *chandir; } /* end if direction change */ } /* end corpos */ /************************************************/ /* */ /************************************************/ void menugo(char *s1, char *s2, char *s3, char *s4, byte kmask1, byte kmask2, byte kmask3,byte kmask4,byte kmask5,int *retc) { /************************************************/ /* */ /* routine runs N option menu and returns */ /* choice */ /* */ /************************************************/ /* define autos */ int ipk, test; /* clear lcd and write msgs */ clrlcd(); lcd_out_msg(0,0,s1); lcd_out_msg(1,0,s2); lcd_out_msg(2,0,s3); lcd_out_msg(3,0,s4); setrowcol(0,0); delay(HUMAN); /* wait for a valid key */ for (;;) { /* read keyboard for enter key */ ipk = (int) getkbd(); test = ipk & kmask1; if(test >0) { *retc = 1; return; } /* key 1 */ test = ipk & kmask2; if(test > 0) { *retc = 2; return; } /* key 2 */ test = ipk & kmask3; if(test > 0) { *retc = 3; return; } /* key 3 */ test = ipk & kmask4; if(test > 0) { *retc = 4; return; } /* key 4 */ test = ipk & kmask5; if(test > 0) { *retc = 5; return; } /* key 5 */ } /* end wait for a valid key */ } /* end menugo */ /************************************************/ /* */ /************************************************/ void rabl_acw(byte imask, long int *axis_pos, int *axis_dir, char *dir_txt, char *axis_legend, int fwd, int *backlash, int *ecode) { /************************************************/ /* */ /* routine prompts for axis backlash */ /* */ /************************************************/ /* define autos */ long int axis_sav; int retc, blsav,blmean,bln,test; char *fwd_txt, *rev_txt; /* zero backlash counts */ bln=0; blmean=0; *ecode=1; /* set desired direction legend */ fwd_txt = (char *) postxt; rev_txt = (char *) negtxt; if(fwd < 0) { fwd_txt = (char *) negtxt; rev_txt = (char *) postxt; } /* loop measuring backlash */ for (;;) { /* write messages */ clrlcd(); sprintf(outstr,"Go %s %s to target",axis_legend, fwd_txt); lcd_out_msg(0,0,outstr); lcd_out_msg(2,0,"Ready -> ENTER"); lcd_out_msg(3,0,"Leave -> UP"); getpos(imask,axis_pos,axis_dir,&dir_txt, &retc); sprintf(outstr,"%s= %-10.1li %s",axis_legend,*axis_pos,dir_txt); lcd_out_msg(1,0,outstr); /* pause */ delay(HUMAN); /* loop printing axis value */ for (;;) { getpos(imask,axis_pos,axis_dir,&dir_txt,&retc); sprintf(outstr,"%s= %-10.1li %s",axis_legend,*axis_pos,dir_txt); lcd_out_msg(1,0,outstr); /* read keyboard for enter key */ retc = (int) getkbd(); test = retc & ISKNTR; if(test > 0) { /* make sure movement in right direction direction */ if(*axis_dir == fwd) break; /* write err msg */ lcd_out_msg(2,0,"Err-wrong direction "); delay(HUMAN); /* continue */ lcd_out_msg(2,0,"Ready -> ENTER "); } /* end test valid enter */ /* test leave */ test = retc & ISKUP; if(test > 0) { *ecode=-1; return; } } /* end wait for enter/leave */ /* reposition target from other side */ axis_sav=*axis_pos; clrlcd(); /* write messages */ sprintf(outstr,"%s %s= %-10.1li",fwd_txt,axis_legend,axis_sav); lcd_out_msg(0,0,outstr); sprintf(outstr,"Go %s to target",rev_txt); lcd_out_msg(1,0,outstr); lcd_out_msg(3,0,"Ready-ENTER Leave-UP"); sprintf(outstr,"%s= %-10.1li %s",axis_legend,*axis_pos,dir_txt); lcd_out_msg(2,0,outstr); /* pause */ delay(HUMAN); /* loop printing axis value */ for (;;) { getpos(imask,axis_pos,axis_dir,&dir_txt,&retc); sprintf(outstr,"%s= %-10.1li %s",axis_legend,*axis_pos, dir_txt); lcd_out_msg(2,0,outstr); /* read keyboard for enter key */ retc = (int) getkbd(); test = retc & ISKNTR; if(test > 0) { /* make sure move in reverse direction */ if(*axis_dir != fwd) break; /* write err msg */ lcd_out_msg(3,0,"Err-wrong direction "); delay(HUMAN); /* continue */ lcd_out_msg(3,0,"Ready-ENTER Leave-UP"); } /* end test valid enter */ /* test leave */ test = retc & ISKUP; if(test > 0) { *ecode=-1; return; } } /* end wait for enter */ /* get backlash value and new mean value */ blsav= (int) (*axis_pos-axis_sav); blmean = blmean * bln + blsav; bln++; blmean=blmean/bln; *backlash=blmean; /* ask again */ clrlcd(); /* write messages */ sprintf(outstr,"%s B/L %s = %i",fwd_txt,axis_legend,blsav); lcd_out_msg(0,0,outstr); sprintf(outstr,"Mean B/L = %i",blmean); lcd_out_msg(1,0,outstr); lcd_out_msg(2,0,"Exit -> ENTER"); lcd_out_msg(3,0,"Repeat -> UP"); /* pause */ delay(HUMAN); /* read keyboard for enter key */ for (;;) { retc = (int) getkbd(); retc &= ISKUP; if(retc > 0) break; retc = (int) getkbd(); retc &= ISKNTR; if(retc > 0) break; } /* if repeat */ retc &= ISKUP; if (retc >0) continue; /* must be enter key - leave */ break; } /* end loop measuring backlash */ } /* end rabl_acw */ /************************************************/ /* */ /************************************************/ byte getkbd() { /************************************************/ /* */ /* routine debounces keyboard switches */ /* */ /************************************************/ /* define autos */ byte key1,key2; /* loop until same answer twice */ for (;;) { key1=getkbd2(); delay(DEBOUNCE); key2=getkbd2(); if(key1 == key2) break; } /* end read same answer twice */ } /* end getkbd */ /************************************************/ /* */ /************************************************/ byte getkbd2() { /************************************************/ /* */ /* routine reads keyboard switches */ /* */ /************************************************/ /* define autos */ byte bitin, keypad; /* read up key */ keypad = 0; bitin = PINC & key_up_msk; if(bitin < 1) keypad += ISKUP; /* down */ bitin = PIND & key_dwn_msk; if(bitin < 1) keypad += ISKDWN; /* left */ bitin = PIND & key_lft_msk; if(bitin < 1) keypad += ISKLFT; /* right */ bitin = PINC & key_rght_msk; if(bitin < 1) keypad += ISKRGHT; /* enter */ bitin = PINC & key_ntr_msk; if(bitin < 1) keypad += ISKNTR; return(keypad); } /* end getkbd2 */ /************************************************/ /* */ /************************************************/ void getpos(byte chanmsk, long int *chanpos, int *chandir, char **a_chandir, int *retc) { /************************************************/ /* */ /* routine returns position of selected channel */ /* */ /************************************************/ /* define autos */ long int poscnt; int i; byte tchar[11], *tptr; /* poll serial */ for (i=0; ;) { /* poll serial in */ tptr=tchar+i; suckc(chanmsk,tptr,retc); if (*retc > 0) { /* valid char - test conversion if eof */ if(*tptr == ',') { /* convert position string to a long int */ makbin((char *) tchar,i+1,&poscnt,retc); /* return binary count if an OK conversion */ if(*retc>0) { /* update direction - compare with last version */ if(poscnt < *chanpos) *chandir = -1; if(poscnt > *chanpos) *chandir = 1; /* save return value */ *chanpos = poscnt; *a_chandir = (char *) postxt; if(*chandir < 0) *a_chandir = (char *) negtxt; return; } /* end valid conversion */ /* start assembling next string if error conversion */ i=0; continue; } /* end if new sequence */ /* inc char count */ i++; if(i>10) i=0; /* safety catch if formatting lost */ /* write char to lcd */ /*wbytdr(*tptr); */ } /* end if a char in */ } /* end poll serial forever */ } /* end getpos */ /************************************************/ /* */ /************************************************/ void makbin(char *instr, int len, long int *outi, int *retc) { /************************************************/ /* */ /* routine converts an encoder input string to */ /* long int position count. */ /* */ /************************************************/ /* define autos */ int i, xint; char xchar; /* test if string valid format "0xhhhhhhhh," */ *retc = 1; *outi = 0; if (len < 11) { *retc = -1; return; } /* end string too short */ /* test string begins '0x' */ if(*instr == '0' && *(instr+1) == 'x') { /* now stuff digits into long integer */ for (i = 2; i < 10; i++) { xchar=*(instr+i); xint = (int) xchar - 0x30; /* convert a to f */ if(xint > 9) xint -= 0x27; /* multiply u the digit */ *outi = *outi * (long int) 0x10 + (long int) xint; } /* end swap chars to digits */ } /* end extract digits */ else { *retc = -2; return; } /* missing precursor "0x" */ } /* end makbin */ /************************************************/ /* */ /************************************************/ void suckc(byte smask, byte *msg, int *retc) { /************************************************/ /* */ /* routine reads a byte from serial port */ /* */ /************************************************/ /* define autos */ unsigned long int mus, mus2, dift; int i; byte bitin; /* check memory */ freeram(); /* loop waiting for a low - hopefully a start bit */ mus=micros(); *retc = 1; *msg = 0x0; for (;;) { /* get elapsed time */ mus2 = micros(); if(mus2 < mus) mus = mus2; /* check if clock rolled over */ /* test if polling time expired */ dift = mus2 - mus; if(dift > (unsigned long int) MAX_SER_WAIT) { *retc=-1; return; } /* end if wait time expired and no data */ /* test input pin */ bitin = PINB & smask; /* if start bit found - leave loop */ if(bitin < 1) break; } /* end polling loop */ /* got a start bit - wait till middle of it */ delayMicroseconds(DLA9600_2); /* now loop reading in bits - we hope */ for (i = 0; i< 8; i++) { /* signal debug */ PORTB &= clrsig; /* put line lo */ /* wait a bit time */ delayMicroseconds(DLA9600_2); /* signal debug */ PORTB |= setsig; /* put line hi */ /* wait a bit time */ delayMicroseconds(DLA9600_2); /* get bit, move into position and save it */ bitin = 0; if(PINB & smask) bitin=1; bitin = bitin << i; *msg |= bitin; } /* end loop over 8 bit times */ /* wait out 1 stop bits and finish */ delayMicroseconds(DLA9600); } /* end suckc */ /************************************************/ /* */ /************************************************/ void lcd_out_msg (int row, int col,char *msg) { /************************************************/ /* */ /* routine lcd_out_msg - write a string to lcd */ /* */ /************************************************/ /* define autos */ char *mptr; int i, mlen; /* position lcd write pt */ setrowcol(row,col); /* check length of string */ mlen=strlen(msg); /* loop writing chars */ if(mlen >0) { /* print string */ for (mptr=msg, i=0; i< mlen; mptr++, i++) { wbytdr(byte(*mptr)); } /* end loop over msg len */ /*now blank rest of line */ //for (i=mlen; i< 20; i++) //{ //wbytdr(byte(0x20)); //} /* end loop over msg len to end of line */ } else { /* null string -=> write a blank line */ for (i=0; i< 20; i++) { wbytdr(byte(0x20)); } /* end loop over msg len */ } } /* end lcd_out_msg */ /************************************************/ /* */ /************************************************/ void setrowcol(int row,int col) { /************************************************/ /* */ /* routine positions DDRAM address at row (0-3) */ /* and col (0-19) */ /* */ /************************************************/ /* define autos */ byte pos; /* convert row,col to barmy lcd address */ switch (row) { case 0: pos=0x0; break; case 1: pos = 0x40; break; case 2: pos = 0x14; break; case 3: pos = 0x54; break; default: pos = 0x0; break; } /* end switch row */ /* convert column */ if (col >19) { col = 19; } /* end check column */ if (col <0) { col = 0; } /* end check column */ /* add on the column number */ pos += (byte) col; /* Instr reg byte: set DDRAM address 0x80 + address */ pos += 0x80; wbytir(pos); } /* end setrowcol */ /************************************************/ /* */ /************************************************/ void mak_lcd_lut(byte *lcd_lut_ptr) { /************************************************/ /* */ /* routine creates look up table to convert an */ /* i/p nibble to an output nibble on LCD data */ /* lines */ /* */ /************************************************/ /* define autos */ int i; byte j, mask,sum; for (i = 0; i<16; i++) { j = i; /* test each of lowest 4 bits */ sum=0; mask = 0x01; if(j & mask) { sum +=lcd_d4_msk; } /* end set ls bit */ mask <<=1; if(j & mask) { sum +=lcd_d5_msk; } /* end set d5 bit */ mask <<=1; if(j & mask) { sum +=lcd_d6_msk; } /* end set d6 bit */ mask <<=1; if(j & mask) { sum +=lcd_d7_msk; } /* end set d7 bit */ /* save translated code */ *(lcd_lut_ptr +i)=sum; } /* end loop over lookup tables */ /* now make nibble to clear down lcd data bus - PORT & lcd_clear = cleared bits */ lcd_xclear = lcd_d4_msk+lcd_d5_msk+lcd_d6_msk + lcd_d7_msk; lcd_xclear = ~lcd_xclear; } /* end mak_lcd_lut */ /************************************************/ /* */ /************************************************/ void init_lcd() { /************************************************/ /* */ /* routine initialises lcd module for 4 bit ops */ /* */ /************************************************/ /* define autos */ byte tchar; /* wait > 40 msec after start up */ delay(50); /* kick off 1 nibble to Instruction Reg: fn set cmd, 8 bits */ tchar=0x02+0x01; wnibir(tchar); /* wait > 39 us */ delayMicroseconds(50); /* Instr reg byte: fn set cmd, 4bit bus, 4 lines, 5x8 font */ tchar=0x20+0x08; wbytir(tchar); /* do it again */ tchar=0x20+0x08; wbytir(tchar); /* Instr reg byte: display set: Display ON, Cursor ON, Blink ON */ tchar=0x08 + 0x04 + 0x02 + 0x01; wbytir(tchar); /* Instr reg byte: clear display */ tchar=0x01; wbytir(tchar); delay(2); /* wait more than 1.53 msec */ /* Instr reg byte: set entry mode: cursor direction, shift display */ tchar = 0x04; wbytir(tchar); /* clear Data ram and return cursor to home */ tchar=0x02; wbytir(tchar); delay(2); /* wait more than 1.53 msec */ } /* end init lcd */ /************************************************/ /* */ /************************************************/ void clrlcd() { /************************************************/ /* */ /* routine Clears Display - DDRAM and DDRAM add */ /* */ /************************************************/ /* define autos */ /* Instr reg byte: clear display */ wbytir(0x01); delay(2); /* wait more than 1.53 msec */ } /* end clear display */ /************************************************/ /* */ /************************************************/ void wbytir(byte s) { /************************************************/ /* */ /* routine writes a byte to lcd instruction */ /* register IR */ /* */ /************************************************/ /* define autos */ byte hinib, lonib; /* get high order nibble */ hinib = s >> 4; lonib = s & 0x0f; wnibir(hinib); wnibir(lonib); /* default 50 us */ delayMicroseconds(50); } /* end wbytir */ /************************************************/ /* */ /************************************************/ void wnibir(byte s) { /************************************************/ /* */ /* routine writes a nibble to lcd instruction */ /* register IR */ /* */ /************************************************/ /* define autos */ byte hinib, lonib, xlate; /* select instruction register */ select_ireg(); /* select write mode */ select_write(); /* translate the nibble */ xlate = *(lcd_lut+(int) s); /* write to Port D - lcd data bits */ PORTD &= lcd_xclear; /* clear data bus bits */ PORTD |= xlate; /* set any desired lcd data bits */ /* now cycle the lcd enable latch */ cycle_ena_latch(); } /* end wnibir */ /************************************************/ /* */ /************************************************/ void wbytdr(byte s) { /************************************************/ /* */ /* routine writes a byte to lcd data */ /* register DR */ /* */ /************************************************/ /* define autos */ byte hinib, lonib; /* test memory */ freeram(); /* get high order nibble */ hinib = s >> 4; lonib = s & 0x0f; wnibdr(hinib); wnibdr(lonib); /* default 50 us */ delayMicroseconds(50); } /* end wbytdr */ /************************************************/ /* */ /************************************************/ void wnibdr(byte s) { /************************************************/ /* */ /* routine writes a nibble to lcd data */ /* register IR */ /* */ /************************************************/ /* define autos */ byte hinib, lonib, xlate; /* select instruction register */ select_dreg(); /* select write mode */ select_write(); /* translate the nibble */ xlate = *(lcd_lut+(int) s); /* write to Port D - lcd data bits */ PORTD &= lcd_xclear; /* clear data bus bits */ PORTD |= xlate; /* set any desired lcd data bits */ /* now cycle the lcd enable latch */ cycle_ena_latch(); } /* end wnibdr */ /************************************************/ /* */ /************************************************/ void cycle_ena_latch() { /************************************************/ /* */ /* routine cycles the LCD Enable latch from */ /* low to high to low. */ /* */ /************************************************/ /* assume PORT B - put mask bit low */ PORTB &= ~(lcd_ena_msk); /* put mask bit high */ PORTB |= lcd_ena_msk; /* high pulse for 40 nsec */ /* put mask bit low */ PORTB &= ~(lcd_ena_msk); /* data still valid for 10 nsec */ } /* end cycle_ena_latch */ /************************************************/ /* */ /************************************************/ void select_ireg() { /************************************************/ /* */ /* routine selects lcd Instruction Register */ /* Register Select line pulled low */ /* */ /************************************************/ /* assume PORT B - put mask bit low */ PORTB &= ~(lcd_rs_msk); } /* end select_ireg */ /************************************************/ /* */ /************************************************/ void select_dreg() { /************************************************/ /* */ /* routine selects lcd Data Register */ /* Register Select line pulled high */ /* */ /************************************************/ /* assume PORT B - put mask bit high */ PORTB |= lcd_rs_msk; } /* end select_dreg */ /************************************************/ /* */ /************************************************/ void select_write() { /************************************************/ /* */ /* routine selects write mode to LCD */ /* R/W line pulled low */ /* */ /************************************************/ /* assume PORT B - put mask bit low */ PORTB &= ~(lcd_rw_msk); } /* end select_write */ /************************************************/ /* */ /************************************************/ void select_read() { /************************************************/ /* */ /* routine selects read mode from LCD */ /* R/W line pulled high */ /* */ /************************************************/ /* assume PORT B - put mask bit high */ PORTB |= lcd_rw_msk; } /* end select_read */ /************************************************/ /* */ /************************************************/