/* CT60 programmable clock module */ /* Didier MEQUIGNON - March 2005 */ #include #include #include #include #include "ct60ctcm.h" #ifndef NO_GEM unsigned long step_frequency=125; #endif extern int ct60_read_info_clock(unsigned char *buffer); extern long ct60_rw_clock(int mode,int address,int data); long ct60_read_clock(void); int ct60_configure_clock(unsigned long frequency,int mode); void tempo_20ms(void); long ct60_read_clock(void) { int dac,offset; long val,offset_def; long stack,fos; unsigned long p,q,pb,frequency; static unsigned char buffer[128]; stack=Super(0L); if((val=ct60_rw_clock(CT60_CLOCK_READ|DALLAS,OFFSET,0))>=0) /* Dallas DS1085 */ { /* frequency = (DEF_FREQ + (OFFSET_STEP * (offset-offset_def))) */ /* - ((DAC_DEF-dac) * DAC_STEP) */ #ifndef NO_GEM step_frequency=DAC_STEP; /* global for slider */ #endif offset=(int)(val&0x1F); if((val=ct60_rw_clock(CT60_CLOCK_READ|DALLAS,DACWORD,0))>=0) { dac=(int)(val>>6); if((val=ct60_rw_clock(CT60_CLOCK_READ|DALLAS,RANGEWORD,0))>=0) { offset_def=(long)(val>>11); fos=DEF_FREQ+(OFFSET_STEP*((long)offset-offset_def)); frequency=(unsigned long)(fos-((DAC_DEF-(long)dac)*DAC_STEP)); } } } else if((val=ct60_rw_clock(CT60_CLOCK_READ|CYPRESS,CLKOE,0))>=0) /* Cypress CY27EE16 */ { /* frequency (KHz) = (REF (KHz) * p) / q) / post divider */ val=ct60_read_info_clock(buffer); if(val>=0) { q=(unsigned long)(buffer[QCOUNTER] & 127)+2; p=(unsigned long)buffer[QCOUNTER]>>7; /* P0 */ pb=((unsigned long)(buffer[CHARGEP]&3)<<8); pb|=(unsigned long)buffer[PBCOUNTER]; p+=((pb+4)<<1); frequency=(REF*p)/q; if(p==8 && q==2 && buffer[CLKOE]==0 && buffer[DIV1N]==0 && buffer[PINCTRL]==0 && buffer[WPREG]==0 && buffer[OSCDRV]==0 && buffer[INLOAD]==0 && buffer[ADCREG]==0 && buffer[MATRIX1]==0 && buffer[MATRIX2]==0 && buffer[MATRIX3]==0 && buffer[DIV2N]==0) val=CT60_NULL_CLOCK_ERROR; if((buffer[DIV1N]&0x7F)<4) buffer[DIV1N]+=4; if((buffer[DIV2N]&0x7F)<4) buffer[DIV2N]+=4; switch((buffer[MATRIX2]&0x70)>>4) /* clock 4 */ { case 0: frequency=REF; break; case 1: if(buffer[DIV1N]&0x80) frequency=REF/(buffer[DIV1N]&0x7F); else frequency/=(buffer[DIV1N]&0x7F); break; case 2: if(buffer[DIV1N]&0x80) frequency=REF>>1; else frequency>>=1; break; case 3: if(buffer[DIV1N]&0x80) frequency=REF/3; else frequency/=3; break; case 4: if(buffer[DIV2N]&0x80) frequency=REF/(buffer[DIV2N]&0x7F); else frequency/=(buffer[DIV2N]&0x7F); break; case 5: if(buffer[DIV2N]&0x80) frequency=REF>>1; else frequency>>=1; break; case 6: if(buffer[DIV2N]&0x80) frequency=REF>>2; else frequency>>=2; break; } #ifdef DEBUG for(val=0;val<0x48;val++) { if((val&7)==0) printf("\r\n"); printf("%02x ",buffer[val]); } #endif } } Super((void *)stack); if(val<0) return(val); return((long)frequency); } int ct60_configure_clock(unsigned long frequency,int mode) { int i,adr,mux,dac,offset; unsigned char matrix2,matrix3,chargep; long error,stack,fos,offset_def; unsigned long p,q,pll; static unsigned char tab_cy_reg[] = { /* Cypress CY27EE16 */ CLKOE,0x69, /* clocks 1, 4, 5, 6 */ DIV1N,0x06, /* post divider /6 */ PINCTRL,0x50, /* output enable pin */ OSCDRV,0x28, /* clock REF */ INLOAD,0x6B, /* capacity load */ ADCREG,0x00, MATRIX1,0xB6, /* clocks 1 to 4 DIV2CLK/2 */ DIV2N,0x08, /* post divider /8 */ WPREG,0x1C, /* write protect soft on, in last position */ 0,0 }; stack=Super(0L); /* supervisor mode */ if((error=ct60_rw_clock(CT60_CLOCK_READ|DALLAS,ADR,0))>=0) /* Dallas DS1085 */ { /* frequency = (DEF_FREQ + (OFFSET_STEP * (offset-offset_def))) */ /* - ((DAC_DEF-dac) * DAC_STEP) */ adr=(int)error; if((error=ct60_rw_clock(CT60_CLOCK_READ|DALLAS,RANGEWORD,0))>=0) { offset_def=(long)(error>>11); Super((void *)stack); /* user mode */ if(frequency<(MIN_FREQ_DALLAS+300UL)) /* strap on CLK/2 */ frequency<<=1; if(frequencyMAX_FREQ_DALLAS) return(CT60_CALC_CLOCK_ERROR); /* MUX : PDN0/1 = 0, SEL0 = 1, EN0 = 0, 0M = 1, 1M = 0, DIV1 = 1 */ mux=0x1240; if(frequency>51000) mux|=0x80; /* 1M = 1 => /2 */ dac=(int)((((long)frequency-DEF_FREQ)/DAC_STEP)+DAC_DEF); if(dac<0 || dac>1023) { offset=(int)(((long)frequency-DEF_FREQ)/OFFSET_STEP); if(offset<-6 || offset>6) return(CT60_CALC_CLOCK_ERROR); offset+=offset_def; if(offset<0 || offset>31) return(CT60_CALC_CLOCK_ERROR); fos=DEF_FREQ+(OFFSET_STEP*((long)offset-offset_def)); dac=(int)((((long)frequency-fos)/DAC_STEP)+DAC_DEF); if(dac<0 || dac>1023) return(CT60_CALC_CLOCK_ERROR); } else offset=(int)offset_def; #ifndef NO_GEM graf_mouse(BUSYBEE,(MFORM*)0); #endif stack=Super(0L); /* supervisor mode */ if((adr&0x08)==0) /* WC = 0 */ { adr=0x08; /* WC = 1 => use WRITEE2 command for the EEPROM */ error=ct60_rw_clock(CT60_CLOCK_WRITE_RAM|DALLAS,ADR,adr); tempo_20ms(); } if(error>=0) { if((error=ct60_rw_clock(CT60_CLOCK_WRITE_RAM|DALLAS,MUXWORD,mux))>=0) { if((error=ct60_rw_clock(CT60_CLOCK_WRITE_RAM|DALLAS,DACWORD,dac<<6))>=0) error=ct60_rw_clock(CT60_CLOCK_WRITE_RAM|DALLAS,OFFSET,offset); } } if(error>=0 && mode==CT60_CLOCK_WRITE_EEPROM) { error=ct60_rw_clock(CT60_CLOCK_WRITE_EEPROM|DALLAS,WRITEE2,0); /* transfer in EEPROM */ tempo_20ms(); } } } else if((error=ct60_rw_clock(CT60_CLOCK_READ|CYPRESS,CLKOE,0))>=0) /* Cypress CY27EE16 */ { Super((void *)stack); /* user mode */ if(frequencyMAX_FREQ_REV6) return(CT60_CALC_CLOCK_ERROR); /* frequency (KHz) = (REF (KHz) * p) / q) / post divider */ /* => p/q = (frequency * post divider) / REF (KHz) */ /* p = (2 * (PB + 4)) + P0 q = Q + 2 */ /* 8 <= p <= 2055 2 <= q <= 129 */ p=(frequency*2000)/REF; q=REF/250; /* 250 KHz mini => max value for q */ while((p*q)>2055000 && q>=2) q--; if(q<2 || q>129) return(CT60_CALC_CLOCK_ERROR); pll=(p/1000)*REF; if(pll<100000 || pll>400000) /* PLL between 100 and 400 MHz */ return(CT60_CALC_CLOCK_ERROR); p*=q; p/=1000; if(p<8 || p>2055) return(CT60_CALC_CLOCK_ERROR); chargep=(unsigned char)((((p>>1)-4)>>8) & 0xFF); chargep|=0xC0; if(p>=45 && p<=479) chargep|=0x04; else if(p>=480 && p<=639) chargep|=0x08; else if(p>=640 && p<=799) chargep|=0x0C; else if(p>=800) chargep|=0x10; if(frequency>77000) { matrix2=0xDF; matrix3=0xB7; /* clocks 5 & 6 DIV2CLK/4 */ } else if(frequency>51000 && frequency<=77000) { matrix2=0xDE; matrix3=0xDF; /* clocks 5 & 6 DIV1CLK/3 */ } else { matrix2=0xDF; matrix3=0x6F; /* clocks 5 & 6 DIV2CLK/2 */ } #ifndef NO_GEM graf_mouse(BUSYBEE,(MFORM*)0); #endif stack=Super(0L); /* supervisor mode */ if(mode==CT60_CLOCK_WRITE_EEPROM) { ct60_rw_clock(CT60_CLOCK_WRITE_RAM|CYPRESS,WPREG,0x0C); /* enable EEPROM writing */ tempo_20ms(); error=ct60_rw_clock(CT60_CLOCK_WRITE_RAM|CYPRESS,WPREG,0x0C); /* enable EEPROM writing */ } if(error>=0) { error=ct60_rw_clock(mode|CYPRESS,MATRIX2,(int)matrix2); if(error>=0) { if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); error=ct60_rw_clock(mode|CYPRESS,MATRIX3,(int)matrix3); if(error>=0) { if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); error=ct60_rw_clock(mode|CYPRESS,CHARGEP,(int)chargep); if(error>=0) { if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); error=ct60_rw_clock(mode|CYPRESS,PBCOUNTER,(int)(((p>>1)-4) & 0xFF)); if(error>=0) { if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); error=ct60_rw_clock(mode|CYPRESS,QCOUNTER,(int)((((p & 1)<<7)+q-2) & 0xFF)); if(error>=0) { if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); i=error=0; while((tab_cy_reg[i] || tab_cy_reg[i+1]) && error>=0) { error=ct60_rw_clock(mode|CYPRESS,tab_cy_reg[i],tab_cy_reg[i+1]); if(mode==CT60_CLOCK_WRITE_EEPROM) tempo_20ms(); i+=2; } } } } } } } } Super((void *)stack); /* user mode */ #ifndef NO_GEM graf_mouse(ARROW,(MFORM*)0); #endif return((int)error); } void tempo_20ms(void) { unsigned long start_time; start_time =*(unsigned long *)0x4BA; while( ((*(unsigned long *)0x4BA) - start_time) <= 4); /* 20 mS */ }