/* Init string for Ublox Neo-7M to produce 1 MHz output * (c) PA3FYM, V0.1 Feb 2019 * * Note: this code is written for an ATTiny13a but of course * also runs on an Arduino (Nano, Pro Mini, Blah etc). * * This code may be used (by you) for non commercial purposes, * and/or intentions, and/or actions as long as you refer to me. * * For commercial use mail me at my QRZ.com address. */ // ATTiny13a settings: 1.2 MHz internal osc, no BOD // PB0 connected to RX pin of Ublox GPS // PB3 VCO voltage input (10k in series) V(T)CXO side! // PB4 LED output (active high), plade 1K in series #define sbi(x,y) x |= _BV(y) // set bit #define cbi(x,y) x &= ~(_BV(y)) // clear bit #define is_high(x,y) (x & _BV(y) == _BV(y)) // check if the y'th bit of register 'x' is high #define gps 0 // PB0 is connected to GPS #define vco 3 // PB3 is VCO read pin #define led 4 // PB4 lock led #define tick 94 // bit time in us , tweak to 4800 Hz with loop0 as main loop uint16_t last = 0; // 1 MHz const byte gps_data[] PROGMEM = {0xB5,0x62,0x06,0x31,0x20,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x40,0x42, 0x0F,0x00,0x80,0x84,0x1E,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xEB,0x00,0x00,0x00,0xA7,0x8F}; // 6MHz //const byte gps_data[] PROGMEM = {0xB5,0x62,0x06,0x31,0x20,0x00,0x00,0x01,0x00,0x00,0x32,0x00,0x00,0x00,0x80,0x8D, // 0x5B,0x00,0x80,0x84,0x1E,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0xEB,0x08,0x00,0x00,0x87,0x0B}; // 8 MHz ref //const byte gps_data[] PROGMEM = {0xB5,0x62,0x06,0x31,0x20,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x00,0x12, // 0x7A,0x00,0x00,0x12,0x7A,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00, // 0x00,0x00,0xEF,0x00,0x00,0x00,0x90,0x03}; void send_byte(uint8_t b) { // sends a byte from PB0, rate: 9600 baud 8N1 cbi(PORTB,gps); // send start bit _delay_us(tick); // 1 tick delay for (uint8_t i = 0; i < 8; i++) { // a byte has 8 bits, LSB first if (b & 0x01) sbi(PORTB,gps); else cbi(PORTB,gps); _delay_us(tick); b >>= 1; // shift right for next bit } sbi(PORTB,gps); // make line high _delay_us(tick); // stopbit is one (1) tick _delay_us(tick); // no parity is also (1) tick } void setup () { #ifdef __AVR_ATtiny13__ analogReference(0); //this line is essential for the Attiny13 when reading analog input #endif // define data direction registers for PORTB (1 = output, 0 = input) DDRB |= 0b00000001; // PB0 output PORTB |= 0b00000001; // PB0 high (for TTL rs232) for (uint8_t i = 0; i<5; i++) { // to be safe send data several times _delay_ms(2000); for (uint8_t i = 0; i < sizeof(gps_data); i++) { send_byte(pgm_read_byte_near(gps_data+i)); // program Ublox GPS with string _delay_us(tick); // one (1) tick between characters to prevent framing errors } } } // setup void loop0() { // calibration loop. Measure frequency on PB0, should be as close to 4800 Hz as possible _delay_us(tick); PINB = bit(gps); // toggle PB0 } void loop() { // main loop uint16_t sample = 0; for (uint8_t i = 0; i < 8; i++) { // take 8 samples sample += analogRead(vco); // read ADC _delay_ms(10); // some delay } sample /= 8; // average samples if (abs(last - sample) < 4) sbi(PORTB,led); // if VCO voltage is stable enough, there is a lock else cbi(PORTB,led); // otherwise no lock, switch off LED last = sample; // update last sample _delay_ms(500); // delay } // loop