Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*Main code by Igor Krepsky - www.frompinskto.wordpress.com
- based on fragments of code by Richard Visokey AD7C - www.ad7c.com
- Rev. 2.2 - Spt., 2016 for AD9851 chip.
- */
- // Подключение библиотек
- #include <rotary.h>
- #include <SPI.h>
- #include <Wire.h>
- #include <OLED_I2C.h>
- OLED myOLED(SDA, SCL, 8);
- extern uint8_t SmallFont[];
- //Определения
- #define W_CLK A2 // A2 - connect to AD9851 module word load clock pin (CLK)
- #define FQ_UD A3 // A3 - connect to freq update pin (FQ)
- #define DATA A6 // A4 - connect to serial data load pin (DATA)
- #define RESET A7 // A5 - connect to reset pin (RST)
- #define ENC_A 2 // Pin 2 - 1 канал валкодера
- #define ENC_B 3 // Pin 3 - 2 канал валкодера
- #define ENC_KEY 4 // Pin 4 - кнопка валкодера
- #define MODE_1 0 // Pin 0 - переключатель mode vfo
- #define MODE_2 1 // Pin 1 - переключатель mode sweep
- #define KEY_1 5 // Pin 5 - доп. кнопка
- #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
- Rotary r = Rotary(2,3); // Устанавливает пины для каналов энкодера. Должны поддерживать прерывания.
- // Переменные
- int_fast32_t rx=1000000; // Стартовая частота VFO
- int_fast32_t rif=0; // Значение IF
- int_fast32_t wif=450000; // рабочее значение IF
- int_fast32_t rx2=1; // переменная для сохранения обновлённой частоты
- int_fast32_t increment = 1000; // начальный VFO инкремент в HZ.
- int_fast32_t delta=1000; // Стартовая величина ширины качания sweep в Hz
- int_fast32_t sstep=1; // Стартовая величина шага качания sweep в Hz
- int buttonstate = 0; // Переменная для чтения состояния кнопки
- String hertz = "1 KHz";
- int hertzPosition = 0;
- byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ; //Разряды для частоты
- byte a_1, a_2; // разряды для отображения IF
- String freq; // string для получения частоты
- boolean mod_1; // текущее значение переключателя mode vfo
- boolean mod_1_old; // сохранённое значение переключателя mode vfo
- boolean mod_2; // текущее значение переключателя mode sweep
- boolean mod_2_old; // сохранённое значение переключателя mode sweep
- void setup() {
- Serial.begin(9600);
- myOLED.begin();
- myOLED.setFont(SmallFont);
- myOLED.clrScr();
- myOLED.print("AD9851 IS LOADING...", CENTER, 16);
- myOLED.update();
- delay(500);
- myOLED.clrScr();
- }
- void loop() {
- // ИЗМЕНЕНИЕ ИНКРЕМЕНТА (кнопка валкодера)
- buttonstate = digitalRead(ENC_KEY); // если нажатие кнопки валкодера - изменить инкремент
- if(buttonstate == LOW) {
- setincrement();
- }
- // ВОЗВРАТ ШАГА ИЗМЕНЕНИЯ ЧАСТОТЫ к 1КГЦ в РЕЖИМЕ ГЕНЕРАТОРА
- if ((mod_1 == 1)&&(mod_2 == 1)){
- buttonstate = digitalRead(KEY_1);
- if (buttonstate == LOW){increment = 1000; hertz="1 KHz"; hertzPosition=0;
- myOLED.print(hertz, LEFT, 0);
- myOLED.update();
- delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
- }
- }
- // ПЕРЕКЛЮЧАТЕЛЬ MODE
- mod_1 = digitalRead (MODE_1); // чтение значения переключателя mode vfo.
- mod_2 = digitalRead (MODE_2); // чтение значения переключателя mode sweep.
- // ДЕЙСТВИЯ ПОСЛЕ ПЕРЕКЛЮЧЕНИЯ MODE
- if ((mod_1 != mod_1_old)||(mod_2 != mod_2_old)){// если произошло переключение mode
- // и вывод на дисплей
- // 1.очистка
- // 2.вывод значения
- if ((mod_1 == 1)&&(mod_2 == 1)){// если режим генератора
- rif=0;
- myOLED.print("OSC.MODE:", LEFT, 8);
- myOLED.update();
- }
- if ((mod_1 == 1)&&(mod_2 == 0)){// если режим генератора с ПЧ
- rif=wif;
- sendFrequency(rx+rif);// отправить частоту в синтезатор
- myOLED.print(hertz, LEFT, 8);
- myOLED.print("IF:", RIGHT, 8);
- myOLED.update();
- if (wif < 1000000){
- myOLED.print(wif/1000, LEFT, 16);
- myOLED.print("KHz", RIGHT, 16);
- myOLED.update();}
- else{
- a_1 = ((wif/1000)%10);
- a_2 = ((wif/100)%10);
- myOLED.print(a_1, LEFT, 24);
- myOLED.print(".", RIGHT, 24);
- myOLED.print(a_2, LEFT, 32);
- myOLED.print("MHz ", RIGHT, 32);
- myOLED.update();}
- } delay(1000); myOLED.clrScr();
- if ((mod_1 == 0)&&(mod_2 == 1)){// если режим SWEEP
- rif=0;
- myOLED.print(hertz, LEFT, 40);
- if (delta < 10000){
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- else if (delta >= 100000){
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- else
- {
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- myOLED.update();
- delay(2000);
- }
- // ВЫВОД НА ДИСПЛЕЙ ЧАСТОТЫ И ПЕРЕДАЧА ЕЁ В DDS ПОСЛЕ ПЕРЕКЛЮЧЕНИЯ MODE
- showFreq();
- sendFrequency(rx+rif);
- rx2 = rx;
- mod_1_old = mod_1;
- mod_2_old = mod_2;
- }
- // ОКОНЧАНИЕ ДЕЙСТВИЯ ПОСЛЕ ПЕРЕКЛЮЧЕНИЯ MODE
- // ВЫЧИСЛЕНИЕ ЧАСТОТЫ ДЛЯ РЕЖИМА SWEEP
- if ((mod_1 == 0)&&(mod_2 == 1)){
- rif = rif + sstep;
- if (rif > delta) {rif = 0;}
- sendFrequency(rx+rif);// отправить частоту в синтезатор
- // переключение delta
- buttonstate = digitalRead(KEY_1);
- if (buttonstate == LOW) {
- if (delta == 1000){delta = 5000;}
- else if (delta == 5000){delta = 10000; sstep = 2;}
- else if (delta == 10000){delta = 50000; sstep = 5;}
- else if (delta == 50000){delta = 100000; sstep = 10;}
- else {delta = 1000; sstep = 1;}
- myOLED.clrScr();
- if (delta < 10000){
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- else if (delta == 100000){
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- else
- {
- myOLED.print(" SWP:", RIGHT, 40);
- myOLED.print(delta/1000, LEFT, 48);
- myOLED.print("KHz ", RIGHT, 48);
- }
- myOLED.update();
- delay(500);
- myOLED.update();}
- }
- // ВЫЧИСЛЕНИЕ ЧАСТОТЫ ДЛЯ РЕЖИМА УЧЁТА ПРОМЕЖУТОЧНОЙ ЧАСТОТЫ
- if ((mod_1 == 1)&&(mod_2 == 0)){
- rif = wif;
- // переключение wif
- buttonstate = digitalRead(KEY_1);
- if (buttonstate == LOW) {
- // нужные значения промежуточных частот прописываются здесь. при желании - как угодно много.
- if (wif == 450000){wif = 455000;}
- else if (wif == 455000){wif = 460000;}
- else if (wif == 460000){wif = 465000;}
- else if (wif == 465000){wif = 1600000;}
- else if (wif == 1600000){wif = 1800000;}
- else if (wif == 1800000){wif = 5500000;}
- else if (wif == 5500000){wif = 10700000;}
- else if (wif == 10700000){wif = 21400000;}
- else {wif = 450000;}
- sendFrequency(rx+rif);// отправить частоту в синтезатор
- if (wif < 1000000){
- myOLED.print(" IF:", LEFT, 56);
- myOLED.print(wif/1000, CENTER, 56);
- myOLED.print("KHz ", RIGHT, 56);
- else{
- myOLED.print(" IF:", LEFT, 56);
- myOLED.print(wif/1000, CENTER, 56);
- myOLED.print("K ", RIGHT, 56);
- }
- myOLED.update();
- delay(250);
- }
- }
- // ВЫВОД НА ДИСПЛЕЙ ЧАСТОТЫ И ПЕРЕДАЧА ЕЁ В DDS В ОБЩЕМ СЛУЧАЕ
- if (rx != rx2)
- {
- showFreq();// при изменении частоты вывести на дисплей
- sendFrequency(rx+rif);// отправить частоту в синтезатор
- rx2 = rx;
- }
- }// END LOOP
- // ПОДПРОГРАММЫ
- // Обработка прерывания
- ISR(PCINT2_vect) {
- // обработка энкодера
- unsigned char result = r.process();
- if (result) {
- if (result == DIR_CW){rx=rx+increment;}
- else {rx=rx-increment;};
- // конец обработки валкодера
- if ((rx+rif) >60000000){rx=(60000000-rif);}; // ВЕРХНИЙ VFO LIMIT
- if (rx <5){rx=5;}; // НИЖНИЙ VFO LIMIT
- }
- }
- // расчёт частоты на основе докумментации на микросхему = <sys clock> * <frequency tuning word>/2^32
- void sendFrequency(double frequency) {
- int32_t freq = frequency * 4294967296./180000000; // note 180 MHz clock on 9851.
- for (int b=0; b<4; b++, freq>>=8)
- {
- tfr_byte(freq & 0xFF);
- }
- tfr_byte(0x001); // Final control byte, LSB 1 to enable 6 x xtal multiplier on 9851 set to 0x000 for 9850
- pulseHigh(FQ_UD); // Сделано! Должен увидеть выход.
- }
- // передаёт байт, по биту за раз, начиная с LSB на 9851 через serial DATA line
- void tfr_byte(byte data)
- {
- for (int i=0; i<8; i++, data>>=1) {
- digitalWrite(DATA, data & 0x01);
- pulseHigh(W_CLK); //после передачи каждого бита, CLK is pulsed high
- }
- }
- void setincrement(){// установка значения инкремента частоты
- if(increment == 1){increment = 10; hertz = "10 Hz"; hertzPosition=0;}
- else if(increment == 10){increment = 100; hertz = "100 Hz"; hertzPosition=0;}
- else if (increment == 100){increment = 1000; hertz="1 Khz"; hertzPosition=0;}
- else if (increment == 1000){increment = 10000; hertz="10 Khz"; hertzPosition=0;}
- else if (increment == 10000){increment = 100000; hertz="100Khz"; hertzPosition=0;}
- else if (increment == 100000){increment = 1000000; hertz="1 Mhz"; hertzPosition=0;}
- else{increment = 1; hertz = "1 Hz"; hertzPosition=0;};
- myOLED.clrScr();
- myOLED.print(hertz, LEFT, 64);
- myOLED.update();
- delay(500); // Adjust this delay to speed up/slow down the button menu scroll speed.
- };
- void showFreq(){// вывод значения частоты на дисплей
- millions = int(rx/1000000);
- hundredthousands = ((rx/100000)%10);
- tenthousands = ((rx/10000)%10);
- thousands = ((rx/1000)%10);
- hundreds = ((rx/100)%10);
- tens = ((rx/10)%10);
- ones = ((rx/1)%10);
- myOLED.clrScr();
- //if (millions > 9){display.setCursor(1,0);}
- // else{display.setCursor(2,0);}
- myOLED.print(millions, LEFT, 0);
- myOLED.print(".", CENTER, 0);
- myOLED.print(hundredthousands, RIGHT, 0);
- myOLED.print(tenthousands, LEFT, 8);
- myOLED.print(thousands, CENTER, 8);
- myOLED.print(".", RIGHT, 8);
- myOLED.print(hundreds, LEFT, 16);
- myOLED.print(tens, CENTER, 16);
- myOLED.print(ones, RIGHT, 16);
- myOLED.print(" Mhz ", LEFT, 24);
- myOLED.update();
- delay(500);
- };
Advertisement
Add Comment
Please, Sign In to add comment