// ==================================================================== // sig-gen.c // Signal Generator based on: // DDS-8950 DDS Module // 16x2 HD44780 LCD Display // ATTiny2313 AVR uC // Rotary Encoder with Switch // // Mike Shegedin, 2017 // ezDenki.com // ==================================================================== // ==================================================================== // // Connections between peripherals and Tiny2313 uC. // // // ATTiny2313 // -----__----- // (ISP_RST) RESET | 1 20 | VCC // (ENC_A) D0 | 2 19 | B7/SCK (ISP_SCK) // (ENC_C) D1 | 3 18 | B6/MISO (ISP_MISO) // XTAL2 | 4 17 | B5/MOSI (ISP_MOSI) // XTAL1 | 5 16 | B4 (LCD_RS) // (DDS_W_CLK) D2 | 6 15 | B3 (LCD_E) // (DDS_FQ_UD) D3 | 7 14 | B2 (LCD_D3) // (DDS_DATA) D4 | 8 13 | B1 (LCD_D2) // (ENC_SW) D5 | 9 12 | B0 (LCD_D1) // GND | 10 11 | D6 (LCD_D0) // ------------ // // ==================================================================== // // AD9850 MODULE PINOUT // _____________ // | ___ | // | | | @ | // | |___| | // VCC | 1 20 | VCC // W_CLK | 2 19 | D0 // FQ_UD | 3 18 | D1 // DATA (D7) | 4 17 | D2 // RESET | 5 16 | D3 // GND | 6 15 | D4 // SQ_OUT_2 | 7 14 | D5 // SQ_OUT_1 | 8 13 | D6 // SIN_OUT_2 | 9 12 | D7 // SIN_OUT_1 | 10 [X] 11 | GND // |_____________| // // ==================================================================== // ==================================================================== // // ENCODER PINOUT // // (D5) (GND) // SW SW // _|||_______|||_ // | | // | ___ TOP | // | / \ | // | { @ } | // | \___/ | // | | // |_ __ __ _| // ||| ||| ||| // A B C // (D0) (GND) (D1) // // ==================================================================== #include #include #include #include #include "hd44780.h" #include // LCD Port/Pin Definitions. These actually (re)defined // in hd44780_settings.h. #define LCD_D4_DDR DDRB #define LCD_D4_PORT PORTB #define LCD_D4_PIN_PORT PINB #define LCD_D4_PIN PB2 #define LCD_D5_DDR DDRB #define LCD_D5_PORT PORTB #define LCD_D5_PIN_PORT PINB #define LCD_D5_PIN PB1 #define LCD_D6_DDR DDRB #define LCD_D6_PORT PORTB #define LCD_D6_PIN_PORT PINB #define LCD_D6_PIN PB0 #define LCD_D7_DDR DDRD #define LCD_D7_PORT PORTD #define LCD_D7_PIN_PORT PIND #define LCD_D7_PIN PD6 #define LCD_RS_DDR DDRB #define LCD_RS_PORT PORTB #define LCD_RS_PIN_PORT PINB #define LCD_RS_PIN PB4 #define LCD_E_DDR DDRB #define LCD_E_PORT PORTB #define LCD_E_PIN_PORT PINB #define LCD_E_PIN PB3 // ==================================================================== // ENCODER PORT/POIN DEFINITIONS (DO NOT INITIALIZE PORT HERE) // ==================================================================== #define ENC_A_DDR DDRD // Encoder A DDRx #define ENC_A_PORT PORTD // PORT #define ENC_A_PIN_PORT PIND // PIN PORT #define ENC_A_PIN PD0 // PIN No. #define ENC_C_DDR DDRD // Encoder C DDRx #define ENC_C_PORT PORTD // PORT #define ENC_C_PIN_PORT PIND // PIN PORT #define ENC_C_PIN PD1 // PIN No. #define ENC_SW_DDR DDRD // Encoder Switch DDRx #define ENC_SW_PORT PORTD // PORT #define ENC_SW_PIN_PORT PIND // PIN PORT #define ENC_SW_PIN PD5 // PIN No. // ==================================================================== // DDS PORT/PIN DEFINITIONS (DO NOT INITIALIZE PORT HERE) // Note that the RESET pin is not needed. // ==================================================================== #define DDS_W_CLK_DDR DDRD // DDS CLC DDRx #define DDS_W_CLK_PORT PORTD // PORT #define DDS_W_CLK_PIN_PORT PIND // PIN PORT #define DDS_W_CLK_PIN PD2 // PIN No. #define DDS_FQ_UD_DDR DDRD // DDS FQ_UD DDRx #define DDS_FQ_UD_PORT PORTD // PORT #define DDS_FQ_UD_PIN_PORT PIND // PIN PORT #define DDS_FQ_UD_PIN PD3 // PIN No. #define DDS_DATA_DDR DDRD // DDS DATA DDRx #define DDS_DATA_PORT PORTD // PORT #define DDS_DATA_PIN_PORT PIND // PIN PORT #define DDS_DATA_PIN PD4 // PIN No. // ==================================================================== // GLOBAL DEFINE CONSTANTS // ==================================================================== #define minGran 1 // Actually minimum gran level (index) #define maxGran 7 // Max gran level (index) #define iniGran 3 // Starting gran level #define maxFreq 5.9e7L // Maximum output freq #define minFreq 0L // Minimum output freq #define iniFreq 1e3 // Starting freq #define longPress 1e4 // # cycles considered to be long press. #define shortWait 1e4 // Number of cycles to wait before updating // diplayed and output frequency. #define freqStrLen 10 // 10 characters (8 digits & 2 ','.) #define DDS_CLOCK 125000000 // Timebase of AD9850 oscillator. #define ep0 3 // Encoder progression when encoder contacts A and C are #define ep1 1 // connected to I/O pin 0 and 1.ep0 is in detent. #define ep2 0 #define ep3 2 // ==================================================================== // DispFreq (Simple) // Display setFreq on the LCD display. // Max digits is 12345678 // ==================================================================== void DispFreq( void ) { extern uint32_t setFreq; extern char tmpStr[]; ltoa(setFreq,tmpStr,10); // Convert long to string. lcd_goto(0x46); lcd_puts(" "); lcd_goto(0x46); lcd_puts(tmpStr); } // ==================================================================== // DispGran // Updates the LCD with the current granularity value. // Note that the granularity level is set outside of this routine. // ==================================================================== void DispGran( void ) { extern uint8_t granLevel; lcd_goto(0x0B); // Erase old text. lcd_puts(" "); lcd_goto(0x0B); // Position for new text. if (granLevel==1) lcd_puts(" 1"); else if( granLevel==2 ) lcd_puts(" 10"); else if( granLevel==3 ) lcd_puts(" 100"); else if( granLevel==4 ) lcd_puts(" 1k"); else if( granLevel==5 ) lcd_puts(" 10k"); else if( granLevel==6 ) lcd_puts("100k"); else if( granLevel==7 ) lcd_puts(" 1M"); else lcd_puts("errr"); } // ==================================================================== // waitFor // Will wait until the ecoder returns the value of "number" or until // the shortWait time has elapsed. The return value is the remaining // wait time. A non-zero return indicates that the desired number // (from the encoder) came up. A zero return indicates a timeout and // the desired number did not occur. // ==================================================================== uint16_t waitFor( uint8_t number ) { uint16_t waitT=shortWait; while( (( (ENC_C_PIN_PORT & (1<maxFreq ) setFreq=maxFreq; // If the frequency goes out of } // bounds, it is capped off at its } // end of ab==ep3 // maximum or minimum limit. } // end of ab==ep2 } } // end of ab==ep1 else if( ab==ep3 ) { // ab==ep3 if( CTS==0 ) goto ctsExit; else { // CTS==1 if( !waitFor(ep2) ) goto ctsExit; else { // ab==ep2 if( !waitFor(ep1) ) goto ctsExit; else { // ab==ep1 if( !waitFor(ep0) ) goto ctsExit; else { setFreq=setFreq-gran[granLevel]; if( setFreq>maxFreq ) // Need to do this since using setFreq=minFreq; // unsigned variable. } } // end of ab==ep1 } // end of ab==ep2 } // end of CTS==1 } // end of ab==ep3 goto exit; ctsExit: CTS=0; exit: ; } // ==================================================================== // ==================================================================== // GLOBAL VARIABLES OUTSIDE OF MAIN OR OTHER FUNCTIONS // ==================================================================== // ==================================================================== uint32_t setFreq = 1e3; // Initial frequency uint8_t granLevel = 4; // Initial Gran Level uint8_t CTS = 0; // Assume encoder not ready. char tmpStr[9]; // Can hold a number string this large. // These are gran levels const uint32_t gran[] = {0,1,10,100,1000,10000,100000,1000000}; // ==================================================================== // ==================================================================== // MAIN // ==================================================================== // ==================================================================== int main(void) { uint8_t i; uint32_t oldFreq=0; uint32_t tuningWord; uint16_t swTimer=0; // =================================================================== // INITIALIZE PORTS AS INPUT OR OUTPUT, ETC. // =================================================================== // INITIALIZE ENCODER PINS AS INPUTS WITH PULLUPS ENC_A_DDR &= ~(1<=longPress ) // If long press was detected, then: { granLevel++; // Undo the previous gran bump. if( granLevel>maxGran ) // If maximunm gran exceeded, granLevel=minGran; // go back to top level of gran. setFreq=gran[granLevel]; DispGran(); // Display the updated gran and freq. DispFreq(); // here for visual feedback of long push. } } while( !(ENC_SW_PIN_PORT & (1<