#include "usbwave.h" struct channel_info { int cal_offset; int zero_offset_code; } cinfo[MAXFD]; int wave12_set_pll(int fd, int m, int n, int u, int dly) { unsigned char reg, temp; unsigned int pllbits; double fout, ratio; int obmux = 2, bit; if(!readreg(fd, 0xA, ®)) return 0; reg &= 0xE0; if(!writereg(fd, 0xA, reg | 0x10)) return 0; /* PLL Mode Hi */ if(!writereg(fd, 0xA, reg | 0x12)) return 0; /* PLL Mode & PLL Shift Hi */ fout = 12.5E6 * m/(n*u); ratio = (n*u)/(double)m; if(ratio == (int)ratio) obmux = 1, u = ratio; n--; m--; u--; pllbits = n | (m << 5) | (u << 11) | (obmux<<17) | (1<<20) | (dly<<22) | (1<<26); for(bit = 0; bit < 27; bit++) { temp = reg | 0x12 | (pllbits&1?0x4:0x0); if(!writereg(fd, 0xA, temp)) return 0; /* Data in */ if(!writereg(fd, 0xA, temp | 0x1)) return 0; /* Clock up */ if(!writereg(fd, 0xA, temp)) return 0; /* Clock down */ pllbits >>= 1; } if(!writereg(fd, 0xA, reg | 0x10)) return 0; /* Disable shift */ if(!writereg(fd, 0xA, reg | 0x1A)) return 0; /* Update */ if(!writereg(fd, 0xA, reg | 0x10)) return 0; /* Update done */ return 1; } int wave12_write_gain_pot(int fd, unsigned code, unsigned char fe) { if(!writeregdouble(fd, 0x2, code)) return 0; if(!writereg(fd, 0x4, 0xB0)) return 0; if(!writereg(fd, 0x8, fe | 0x40)) return 0; return delaycycle(fd, 6); } int wave12_write_offset_pot(int fd, unsigned code, unsigned char fe) { if(!writeregdouble(fd, 0x5, code)) return 0; if(!writereg(fd, 0x7, 0xB0)) return 0; if(!writereg(fd, 0x8, fe | 0x40)) return 0; return delaycycle(fd, 6); } int wave12_set_offset(int fd, float off, float volt) { unsigned char fe; if(!readreg(fd, 0x8, &fe)) return 0; if(off < -10) off = -10; if(off > 10) off = 10; return wave12_write_offset_pot(fd, (unsigned) (off*0.9*511/30 + cinfo[fd].zero_offset_code + volt*cinfo[fd].cal_offset), fe); } int wave12_set_amplitude(int fd, float val, float off) { unsigned char fe; if(!readreg(fd, 0x8, &fe)) return 0; if(val < 0.0) val = 0.0; if(val > 10.0) val = 10.0; if(!wave12_write_gain_pot(fd, (unsigned)(1023 - 102.3*0.882555*val), fe)) return 0; return wave12_set_offset(fd, off, val); } int wave12_cal_count(int fd) { unsigned char reg; int i, c; for(i = c = 0; i < 10; i++) { if(!readreg(fd, 0x8, ®)) return 0; if(!delaycycle(fd, 1)) return 0; if(reg & 0x10) c++; } return c; } int wave12_calibrate(int fd) { unsigned char reg; unsigned code; int i, c; /* min gain, integrator off, zero cross comp on */ if(!wave12_write_offset_pot(fd, 0x1F0, 0x0)) return 0; if(!wave12_write_gain_pot(fd, 0x3FF, 0x0)) return 0; for(code = 0x1F0; code < 0x20E; code++) { if(!wave12_write_offset_pot(fd, code, 0x0)) return 0; if(!delaycycle(fd, 1)) return 0; if(wave12_cal_count(fd) == 10) { cinfo[fd].zero_offset_code = code-1; cinfo[fd].cal_offset = code-1; break; } } /* gain 9V, integrator on, zero cross comp on */ if(!wave12_write_offset_pot(fd, 0x210, 0x4)) return 0; if(!wave12_write_gain_pot(fd, 0x180, 0x4)) return 0; if(!delaycycle(fd, 50)) return 0; code = 0x210; for(i = 0; i < 50; i++) { c = wave12_cal_count(fd); if(c == 0 || c == 10) break; } if(!readreg(fd, 0x8, ®)) return 0; if(c == 0) { for(i = 1; i < 700; i++) { code++; if(!wave12_write_offset_pot(fd, code, reg)) return 0; if(!delaycycle(fd, 25)) return 0; if(wave12_cal_count(fd) == 10) { cinfo[fd].cal_offset = code-1; break; } } } else if(c == 10) { for(i = 1; i < 500; i++) { code--; if(!wave12_write_offset_pot(fd, code, reg)) return 0; if(!delaycycle(fd, 25)) return 0; if(wave12_cal_count(fd) == 0) { cinfo[fd].cal_offset = code-1; break; } } } cinfo[fd].cal_offset = (cinfo[fd].cal_offset - cinfo[fd].zero_offset_code)/9; /* integrator off, zero cross comp off */ return writereg(fd, 0x8, 0x8); } int wave12_set_wave_type(int fd, int type) { switch(type) { case WAVE12_WAVE_TYPE_SINE: if(!writereg(fd, 0xB, 0x8)) return 0; return changereg(fd, 0x8, ~0x22, 0x20); case WAVE12_WAVE_TYPE_SQUARE: if(!writereg(fd, 0xB, 0x28)) return 0; return changereg(fd, 0x8, ~0x22, 0x22); case WAVE12_WAVE_TYPE_TRIANGLE: if(!writereg(fd, 0xB, 0xA)) return 0; return changereg(fd, 0x8, ~0x22, 0x20); } return 0; } int wave12_set_frequency(int fd, float val) { unsigned long uval; if(val < 0.2) val = 0.2; if(val > 1.2E7) val = 1.2E7; uval = (unsigned long)(val*(1<<26)/12.5E6) & 0xFFFFFFF; if(!writereg(fd, 0x0f, uval & 0xFF)) return 0; if(!writereg(fd, 0x10, ((uval >> 8) & 0x3F) | 0x40)) return 0; if(!writereg(fd, 0x11, (uval >> 14) & 0xFF)) return 0; if(!writereg(fd, 0x12, ((uval >> 22) & 0x3F) | 0x40)) return 0; if(!writereg(fd, 0x13, uval & 0xFF)) return 0; if(!writereg(fd, 0x14, ((uval >> 8) & 0x3F) | 0x80)) return 0; if(!writereg(fd, 0x15, (uval >> 14) & 0xFF)) return 0; if(!writereg(fd, 0x16, ((uval >> 22) & 0x3F) | 0x80)) return 0; return changereg(fd, 0x8, 0xFF, 0x20); } int wave12_set_phase(int fd, float val) { unsigned uval; if(val <= 0 || val >= 360) val = 0; uval = (unsigned)(val*4096.0/360.0) & 0xFFF; if(!writereg(fd, 0x17, uval & 0xFF)) return 0; if(!writereg(fd, 0x18, (unsigned char)((uval >> 8) & 0xF) - 0x40)) return 0; if(!writereg(fd, 0x19, uval & 0xFF)) return 0; if(!writereg(fd, 0x1A, (unsigned char)((uval >> 8) & 0xF) - 0x20)) return 0; return changereg(fd, 0x8, 0, 0x20); } int wave12_set_run(int fd, int state) { return changereg(fd, 0x0, 0xFE, state?0x01:0); } int wave12_set_arm(int fd, int state) { return changereg(fd, 0x0, 0xFD, state?0x02:0); } int wave12_set_trigger(int fd, int state) { return changereg(fd, 0x0, 0xDF, state?0x20:0); } int wave12_set_enable(int fd, int state) { return changereg(fd, 0x8, 0xFE, state?0x1:0); } int wave12_init_wave(int fd, int master, int *cal, int *zero) { cinfo[fd].cal_offset = 0; cinfo[fd].zero_offset_code = 0x1FF; if(!writereg(fd, 0x0, 0x4)) return 0; if(!writereg(fd, 0x1, 0x0)) return 0; if(!wave12_set_enable(fd, 0)) return 0; if(!wave12_set_amplitude(fd, 0, 0)) return 0; if(!writereg(fd, 0xB, 0x8)) return 0; if(!writereg(fd, 0xC, 0x22)) return 0; if(!wave12_set_frequency(fd, 1000)) return 0; if(!wave12_set_phase(fd, 0)) return 0; if(!writereg(fd, 0x1, 0x20)) return 0; if(!writereg(fd, 0x1, 0x24)) return 0; if(!writereg(fd, 0x1, 0x04)) return 0; if(!writereg(fd, 0x1, 0x24)) return 0; if(!usbtm_set_clock_master(fd, master)) return 0; if(!usbtm_set_trig_master(fd, master)) return 0; if(!wave12_set_trigger(fd, 0)) return 0; if(!wave12_set_arm(fd, 1)) return 0; if(!wave12_set_run(fd, 1)) return 0; if(cal == NULL || zero == NULL || (*cal == 0 && *zero == 0)) { if(!wave12_calibrate(fd)) return 0; } else { cinfo[fd].cal_offset = *cal; cinfo[fd].zero_offset_code = *zero; } if(cal != NULL && zero != NULL) { *cal = cinfo[fd].cal_offset; *zero = cinfo[fd].zero_offset_code; } if(!usbtm_set_led_mode(fd, USBTM_LED_MODE_NORMAL)) return 0; return 1; }