#ifndef __int_c_ #define __int_c_ #include "int.h" volatile unsigned char FLAGS; volatile unsigned char FLAGS2; volatile int YEAR; volatile int MONTH; volatile int DAY; volatile int HOUR; volatile int MINUTE; volatile int SECOND; volatile int MSECOND; volatile unsigned char timer36; volatile unsigned char thismdays; volatile long il_last; //values for raw move/positions, //where 1 is representing the move //of one minimum microstepsize, which //is factorizied to 1/10 of an arcsecond. volatile long calctarget_hor; volatile long calctarget_ver; volatile long calctarget_fr; volatile long pos_hor; volatile long pos_ver; volatile long pos_fr; volatile long origin_hor; volatile long origin_ver; volatile long origin_fr; volatile long hor_360; volatile long ver_360; volatile long fr_360; //------------------------- volatile int epos_hor; volatile int epos_ver; volatile int originenc_hor; volatile int originenc_ver; volatile unsigned char spictr; volatile unsigned char spiout[22]; volatile unsigned char spiin[22]; volatile unsigned char addr_hor; volatile unsigned char addr_ver; volatile unsigned char addr_fr; //Should be called 7200 times per second. //attention, - no blank at signalnamestart, - end INTERRUPT(SIG_OVERFLOW0) { timer36++; if( timer36 == 18 ){ //this is a 1/400tel part il_last++; if( il_last >= STARDAYSEC400LASTLONG ){ il_last = 0; } } if( timer36 > 35 ){ //this is also a 1/400tel part il_last++; if( il_last >= STARDAYSEC400LASTLONG ){ il_last = 0; } //ok, we have a 1/200 second timer36 = 0; MSECOND = MSECOND + 5; if( MSECOND >= 1000 ){ //ok, we have a complete second MSECOND = 0; SECOND++; if( SECOND >= 60 ){ //dito - minute SECOND = 0; MINUTE++; if( MINUTE >= 60 ){ //hour MINUTE = 0; HOUR++; if( HOUR >= 24 ){ //day HOUR = 0; DAY++; if( DAY > thismdays ) { DAY = 1; MONTH++; if( MONTH > 12 ){ MONTH = 1; YEAR++; } } } } } } } ///////////////////////////////// //here the 1/7200 stuff //every 1/7200 a byte is send over spi, to hold a valid frequency for the driver //the most time this is a nop. //config has to be set after startup, with followings: //ISFLAGSPION has to be off //set buffer spiout with complete config-stuff for all three boards. //then set ISFLAGCFG //then set ISFLAGSPION //if all send ISFLAGSPION is automatically switched of by interrupt. //for second config you have to do the same. //For normal operations, you have after all configs only to switch //ISFLAGSPION on. //addr_hor,addr_ver,addr_fr has to be init with 0xff before config. //the addresses for the driver-boards has to be set fixed to //0x00 for az/ra //0x01 for alt/dec //0x02 for fieldrotator //this addresses has to be set also if one, or more of them not used. if( ISFLAGSPION ){ if( spictr == 0 ){ //we use double set flags, means user handles the force-flags //and interrupt the internal flags, so user has not to wait //till interrupt is ready, - the next time spictr is 0, the //next priorized force-flag will be handled. //But have a look, that user only can set different operations //in one set, because the current used flag will be cleared //at end. In case the same flag as the previous is used, user //has to wait till the last is cleared by interrupt. //Excepting the config-functions, and the FLAGSPISTEPON, //the internal flags never should be used by external functions. if( (ISFLAGSSPIFORCESEND) == 0 ){ //we send a nop spiout[0] = 0; //nop + address hor spiout[7] = 1; //nop + address ver spiout[14] = 2; //nop + address fr } else { if( ISFLAGSPICFG ){ //set stuff from config //spibuf has to contain all necessary bytes //Here we only set the right addresses. SETFLAGSPICFG; spiout[0] = spiout[0] & 0x78; spiout[7] = spiout[7] & 0x78; spiout[7] = spiout[7] + 1; spiout[14] = spiout[14] & 0x78; spiout[14] = spiout[14] + 2; } if( ISFLAGSPIFORCESTOP ){ SETFLAGSPISTOP; CLRFLAGSPISTEPON; spiout[0] = 0x20; spiout[7] = 0x21; spiout[14] = 0x22; } if( ISFLAGSPIFORCEORIGIN){ SETFLAGSPIORIGIN; spiout[0] = 0x10; spiout[7] = 0x11; spiout[14] = 0x12; *(long *)&spiout[1] = origin_hor; *(long *)&spiout[8] = origin_ver; *(long *)&spiout[15] = origin_fr; *(int *)&spiout[5] = originenc_hor; *(int *)&spiout[12] = originenc_ver; *(int *)&spiout[19] = 0; } if( ISFLAGSPIFORCETARGET ){ SETFLAGSPITARGET; spiout[0] = 0x08; spiout[7] = 0x09; spiout[14] = 0x0a; if( ISFLAGSPISTEPON ){ spiout[6] = 128; //only STEP_ON (steplp is set by config) spiout[13] = 128; //only STEP_ON (steplp is set by config) spiout[20] = 128; //only STEP_ON (steplp is set by config) } else { spiout[6] = 0; spiout[13] = 0; spiout[20] = 0; } *(long *)&spiout[1] = calctarget_hor; *(long *)&spiout[8] = calctarget_ver; *(long *)&spiout[15] = calctarget_fr; } } } // NOW WE SEND OUT PORTB = PORTB & 239;//PB4 (SS) = low NOP;NOP;NOP;NOP;NOP;NOP; //give a little bit time //first store stuff from last sended byte, and clear buffer //the first should normally a 0xff spiin[spictr] = SPDR; NOP;NOP; //sendout spiout[spictr]; SPDR = spiout[spictr]; NOP;NOP;NOP;NOP;NOP;NOP;NOP;NOP; PORTB = PORTB | 16;//PB4 (SS) = high spictr++; //Here we send the last byte of all 3 7-byte sequences if( spictr > 21 ){ spictr = 0; if( ISFLAGSPICFG ){ addr_hor = spiin[1]; addr_ver = spiin[8]; addr_fr = spiin[15]; } else { //all others contains current pos, encpos pos_hor = (long)*(long *)&spiin[1]; pos_ver = (long)*(long *)&spiin[8]; pos_fr = (long)*(long *)&spiin[15]; epos_hor = (int)*(int *)&spiin[5]; epos_ver = (int)*(int *)&spiin[12]; } if( ISFLAGSPISTOP ){ CLRFLAGSPIFORCESTOP; } if( ISFLAGSPIORIGIN ){ CLRFLAGSPIFORCEORIGIN; } if( ISFLAGSPITARGET ){ CLRFLAGSPIFORCETARGET; } if( ISFLAGSPICFG ){ CLRFLAGSPIFORCECFG; } CLRFLAGSSPISEND; if(ISFLAGSPIFORCEOFF ){ CLRFLAGSPIFORCEOFF; CLRFLAGSPION; } } } } //END Timer-Interrupt //timeing for the interrupt which is called every 1/7200 sec //Every 1/7200 second part uses 0,00013333333333... seconds //sending an spi-byte with 400kbyte/second uses 0,0000025 seconds. //So one called interrupt hase place for max: //max, 52 spi bytes send with 400kbytes/second, or //max, 2040 one tact operations //But because driver can handle all in a 1/7200 secondpart, we //have not to wait till byte is send ready. //a good timing-choice is to use not more then max. 500 operations //############################################################# //########### MOTOR ROUTINES ################################## //############################################################# //use SETFLAGSPISTEPON, or CLRFLAGSPISTEPON //before if you will that motor drives to new target. //this func is the only one which waits not till all is send //ready, because we use the processortime for the target-calculations. //(This is slow enough, because max. 220 times per second this function //will be called.) //calctarget_hor,calctarget_ver, and calctarget_fr will be set //from this at a time, it is not bothered by interrupt. void mot_target( long hor, long ver, long fr ) { if ( ISFLAGSPION ){ while( ISFLAGSPITARGET ){ NOP; } calctarget_hor = hor; calctarget_ver = ver; calctarget_fr = fr; SETFLAGSPIFORCETARGET;//this is cleared by interrupt automatically } } //sends a stop and set command to drivers, and waits till ready. //after this drivers target-positons are set to dirvers current-positions, //also the STEP_ON flags are cleared. //After this pos_hor,pos_ver,pos_fr,epos_hor,epos_ver contain the actual //current-position of drivers, which for the driver is also the targetpos. void mot_stop( void ) { if( ISFLAGSPION ){ while( ISFLAGSSPISEND ){ NOP; }//wait till all other is ready SETFLAGSPIFORCESTOP; while( ISFLAGSPIFORCESTOP ){ NOP; };//wait hard, till ready } } //first sending a mot_stop to drivers, to be sure, that //motor does not make any step furthermore. //then sends a origin command to all 3 drivers with the new values //for the drivers current-positions, and encoders. //If you will be sure, that drivers target positions are the same //as its current position, you should be send again a mot_stop //after this by yourself. In this case you should also be sure, that //pos_hor,pos_ver,pos_fr, and epos_hor,epos_ver contains the origin-position. //After this FLAGSPISTEPON is cleared, so motor does not do any step. void mot_origin( long hor, long ver, long fr, int ehor, int ever ) { mot_stop(); if( ISFLAGSPION ){ while( ISFLAGSSPISEND ){ NOP; }//wait till all other is ready origin_hor = hor; origin_ver = ver; origin_fr = fr; originenc_hor = ehor; originenc_ver = ever; SETFLAGSPIFORCEORIGIN; while( ISFLAGSPIFORCEORIGIN ){ NOP; };//wait hard, till ready } } //############################################################# //########### SPI ROUTINES #################################### //############################################################# void spi_init(void){ //initialize SPI-mode /////////////////////////// //SPI-Signals will be set to MASTER by default //MISO(SPI-MAIN) PB6 In (external 47K pullup to VCC ) //MOSI(SPI-MAOUT) PB5 Out //SCK (SPI-CLKOUT) PB7 Out //SS (SPI-CSOUT) PB4 Out //?????????????????????????? PORTB = 176; //first setting pullups PB4,5,7 to high DDRB = 176; //PB4,5,7 to output, all other unchanged PORTB = 176; //these signals also to high //clock = f/4 //master mode //enable spi //SCK high when idle SPCR = (1< 995 ){ MSECOND = 0; } thismdays = get_maxmonthdays( MONTH, YEAR ); //Timer0 counting clock / 8 complete range 0-0xff //15745600 / 8 = 1.843.200 //1.843.200 / 256 = 7200 //so we have a precision of 1/7200 tel second. //Means the interrupt will be called 7200 times per second. //Because timer counts complete 8bit-range 0-255, we //never have to reload it with a new value. TCNT0 = 0;// simple setting to 0 TCCR0 = 2;// prescaler ck/8 timer36 = 0;//our own 7200 to 100 provider //TIMSK = (1<