//************************************************************ // PIC_METORONOME_TEST // // BEAT: 1,2,3,4 Time // TEMPO: 40-200bpm (1bpm step:ROTARY ENCODER) // Rhythm Tone: Wood Block(USED Envelope Contorol Block) // LCD unlook busy : not switch direction (write fixed) // // CPU: dsPIC30F4013 // // Condition: // 7.37MHz Internal RC oscillator, 16x PLL enabled // Fcy=7.37MHzx16/4=29.48MHz, Tcy=33.92ns // // 2012/6/28: N.Ishii //************************************************************* #include #include // Divice configuration _FWDT(WDT_OFF); _FGS(CODE_PROT_OFF); _FOSC(CSW_FSCM_OFF & FRC_PLL16); //OSC, PLL Setting _FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN); //------------------------------------------------------------------------- /// message table char msg1[] = {"BEAT :\0"}; char msg2[] = {"TEMPO: [bpm]\0"}; //------------------------------------------------------------------------- /// Envelope Contorol Block Define #define CK1 LATDbits.LATD2 #define CK1_Lo LATDbits.LATD2 = 0 #define UP1_Hi LATFbits.LATF4 = 1 #define UP1_Lo LATFbits.LATF4 = 0 #define DWN1_Hi LATFbits.LATF5 = 1 #define DWN1_Lo LATFbits.LATF5 = 0 //--------------------------------------------------------------------------------------------- /// Rotary ecoder #define RE_A PORTBbits.RB4 #define RE_B PORTBbits.RB5 //----------------------------------------------------------------------------------------- /// LCD Define: R/W_pin= GND (Fixed Write) #define LCD_DATA_WR_MODE LATFbits.LATF1 = 1 // RS_pin = 1 #define LCD_INST_WR_MODE LATFbits.LATF1 = 0 // RS_pin = 0 #define LCD_ENABLE_ON LATFbits.LATF0 = 1 #define LCD_ENABLE_OFF LATFbits.LATF0 = 0 #define LCD_DATA_BIT4 LATBbits.LATB9 #define LCD_DATA_BIT5 LATBbits.LATB10 #define LCD_DATA_BIT6 LATBbits.LATB11 #define LCD_DATA_BIT7 LATBbits.LATB12 //--------------------------------------------------------------------------------------------- /// LCD Instraction Code #define FOUR_BIT_FONT5x7dot 0x28 // + TWO_LINE(1/16Duty), SEG1_50_SEG51_100, COM1_COM16 #define DISP_ON_CURSOR_ON_BLINK_OFF 0x0e #define DISP_CLEAR_CURSOR_HOME 0x01 #define RAM_WR_AFTER_PLUS_1 0x06 // Entory mode set #define DDRAM_START_ADDRESS_SET 0x80 #define DISP_ON_CURSOR_OFF_BLINK_OFF 0x0c //--------------------------------------------------------------------------- unsigned int T3_count = 0; unsigned int beat_count = 0; unsigned char BPM = 60; unsigned int Beat_Period; unsigned int T3_count_MAX = 2000; unsigned char Beat_No = 3; unsigned char start_flag = 0; unsigned char sw1_m0 = 0; // Start/Stop SW unsigned char sw1_m1 = 0; unsigned char sw1_m2 = 0; unsigned char sw2_m0 = 0; // Beat Sel SW unsigned char sw2_m1 = 0; unsigned char sw2_m2 = 0; unsigned char re_b_m0 = 0; // ROTARY ENCODER B-OUT:Clock unsigned char re_b_m1 = 0; unsigned char re_b_m2 = 0; //unsigned char digit[3]; //----------------------------------------------------------------------------------- /// Delay Subrutin void Waitx1ms(int x) // Td = 1mS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5000 ; ++j) asm("clrwdt"); //Td=1mS } } void Waitx1us(int x) // Td = 1uS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5 ; ++j) asm("clrwdt"); //Td=1uS } } //-------------------------------------------------------------------- /// LCD Subrutin void one_chr_wr(char chr_code) { LCD_DATA_WR_MODE; //RS_pin = 1: select data Reg // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((chr_code & 0x10)>>4); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(chr_code & 0x01); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1us(50); } void lcd_chr_wr(char *buffer) { while(*buffer != '\0') { one_chr_wr(*buffer); /* calling another function */ /* to write each char to the lcd module */ buffer++; } } void lcd_inst_wr(char inst_code) { LCD_INST_WR_MODE; //RS_pin = 0: select Instruction Reg // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((inst_code & 0x10)>>4); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(inst_code & 0x01); Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; // if ((inst_code & 0x03) != 0) Waitx1ms(20); // inst_code is Clear(0x01) or Cursor Home(0x02) Then Wait 20mS if ((inst_code >= 0x01) && (inst_code <= 0x03)) Waitx1ms(20); // inst_code is Clear(0x01) or Cursor Home(0x02 or 0x03) Then Wait 20mS else Waitx1us(50); // other code Then Wait 50uS } void lcd_init(void) { // Allow a delay(minimum of 15ms) Waitx1ms(20); //------ 1st step: port_output regster set -------------- // Initialize the data port/control pins to zero LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 0; LCD_DATA_BIT4 = 0; LCD_INST_WR_MODE; //RS_pin = 0 LCD_ENABLE_OFF; //E_pin = 0 //-------------------------------------------------------- // dsPIC30F4013 //------- 2nd step: port_mode regster set --------------- // Configure the data pins as output TRISBbits.TRISB9 =0; // RB9 is LCD DB4 OUTPUT TRISBbits.TRISB10 =0; // RB10 is LCD DB5 OUTPUT TRISBbits.TRISB11 =0; // RB11 is LCD DB6 OUTPUT TRISBbits.TRISB12 =0; // RB12 is LCD DB7 OUTPUT // Make all control pins as outputs TRISFbits.TRISF0 =0; // RF0 is LCD Enable OUTPUT TRISFbits.TRISF1 =0; // RF1 is LCD RS OUTPUT //------------------------------------------------------- // Initialize stage 1: Set stage 1 only 8-bit Interface // Set Upper 4 Bit Data on RB9 - RB12 LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(5); // Initialize stage 2: Set stage 2 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); // Initialize stage 3: Set stage 3 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); // Initialize stage 4: 4-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 0; Waitx1us(1); LCD_ENABLE_ON; Waitx1us(1); LCD_ENABLE_OFF; Waitx1ms(1); //----- Fixed LCD Setting------------ lcd_inst_wr(FOUR_BIT_FONT5x7dot); // Function Set lcd_inst_wr(DISP_ON_CURSOR_ON_BLINK_OFF); lcd_inst_wr(DISP_CLEAR_CURSOR_HOME); // Set DDRAM Address = 0 lcd_inst_wr(RAM_WR_AFTER_PLUS_1); // Entry mode Set } void const_lcd_disp(void) { // Initialize LCD Disp lcd_inst_wr(0x80); lcd_chr_wr(msg1); // 'BEAT :' const disp1 lcd_inst_wr(0xc0); lcd_chr_wr(msg2); // 'TEMPO: [bpm]' const disp2 } void beat_no_disp(unsigned char Vol, unsigned char loc) { lcd_inst_wr(loc); one_chr_wr(Vol | 0x30); } void tempo_disp(unsigned char Vol, unsigned char loc) { unsigned char i; unsigned char digit[3]; unsigned char ascii[3]; // Bin_to_pacdec digit[0] = Vol%10; digit[1] = (Vol/10)%10; digit[2] = (Vol/100)%10; // Decimal_to_ascii for (i = 0; i <= 2; ++i) {ascii[i] = digit[i] | 0x30;} // LCD Disp lcd_inst_wr(loc); one_chr_wr(ascii[2]); one_chr_wr(ascii[1]); one_chr_wr(ascii[0]); } //----------------------------------------------------------------------------------------- /// SW and ROTARY ENCODER Read Subrutin void Start_Stop_SW_read(void) { // Waitx1ms(1); sw1_m0 = PORTBbits.RB0; //New SW1 Data sw1_m2 = sw1_m1^(sw1_m0 & sw1_m1); //Neg_Edge Sence SW1 sw1_m1 = sw1_m0; //Chenge New Data to Old Data m1 if (!start_flag) { if (sw1_m2) { // Start start_flag = 1; ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); // DISICNT = 0x0000; // Enable Interrupt } } else { if (sw1_m2) { // Stop start_flag = 0; T3_count = 0; beat_count = 0; CK1_Lo; UP1_Lo; DWN1_Lo; LATDbits.LATD0 = 1; // LED OFF ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_OFF); // DISICNT = 0x0001; // Disable Interrupt } } } void Beat_No_Sel_SW_read(void) { /* if ((PORTFbits.RF2 == 0) && (PORTFbits.RF3 == 0)) Beat_No = 1; if ((PORTFbits.RF2 == 1) && (PORTFbits.RF3 == 0)) Beat_No = 2; if ((PORTFbits.RF2 == 0) && (PORTFbits.RF3 == 1)) Beat_No = 3; if ((PORTFbits.RF2 == 1) && (PORTFbits.RF3 == 1)) Beat_No = 4; */ sw2_m0 = PORTBbits.RB8; //New SW2 Data sw2_m2 = sw2_m1^(sw2_m0 & sw2_m1); //Neg_Edge Sence SW2 sw2_m1 = sw2_m0; //Chenge New Data to Old Data m1 if (sw2_m2) { ++Beat_No; if (Beat_No == 5) Beat_No = 1; if (start_flag) { ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_OFF); T3_count = 0; beat_count = 0; CK1_Lo; UP1_Lo; DWN1_Lo; ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); } } } void Rotary_Encoder_read(void) { // Waitx1ms(10); //Read ROTARY ENCODER B_Clock re_b_m0 = RE_B; // re_b_m0 = RE_A; // re_b_m2 = re_b_m1^(re_b_m0 | re_b_m1); //Pos_Edge Sence CLOCK re_b_m2 = re_b_m1^(re_b_m0 & re_b_m1); //Neg_Edge Sence CLOCK re_b_m1 = re_b_m0; //Chenge New Data to Old Data m1 if (re_b_m2 == 1) { //Neg_Edge Sence B_Clock ? // if (PORTBbits.RB4 == 1) { // A_Data = 1 ? if (RE_A == 0) { // A_Data = 0 ? // if (RE_B == 0) { ++BPM; if (BPM >= 201) BPM = 200; } else { // B_Data = 0 --BPM; if (BPM <= 39) BPM = 40; } if (start_flag) { ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_OFF); T3_count = 0; beat_count = 0; CK1_Lo; UP1_Lo; DWN1_Lo; ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); } // while(RE_A == 1); // Wait RE_A is Lo } } //----------------------------------------------------------------------------------------------------- // Intterrupt routine: T = 0.5ms //void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _T3Interrupt(void) void __attribute__((__interrupt__, no_auto_psv)) _T3Interrupt(void) { // LATDbits.LATD3 = 1; ++T3_count; // if (T3_count <= 80) CK1 = !CK1; // Sound Block(0.5*80 = 40mS) // if (T3_count <= 160) CK1 = !CK1; // Sound Block(0.5*160 = 80mS) if (beat_count == 0) { // Top tone is 1kHz if (T3_count <= 160) CK1 = !CK1; } else { // Other tone is 500Hz if ((T3_count <= 160) && ((T3_count - 1) % 2) == 0) CK1 = !CK1; } switch (T3_count) { case 1: LATDbits.LATD0 = 0; // LED ON UP1_Hi; if (beat_count == 0) DWN1_Hi; break; case 21: // case 61: UP1_Lo; if (beat_count == 0) DWN1_Lo; break; case 25: // case 65: DWN1_Hi; break; // case 65: case 125: DWN1_Lo; LATDbits.LATD0 = 1; // LED OFF break; default: break; } if (T3_count == T3_count_MAX) { // 161-xxx: Interval Block T3_count = 0; ++beat_count; if (beat_count == Beat_No) beat_count = 0; } // LATDbits.LATD3 = 0; //Intterrupt Timer3 Clear IFS0bits.T3IF = 0; } //-------------------------------------------------------------------- /// Function Main int main(void) { // Set ADPCFG: RB Port is All Digital Pin ADPCFG = 0xFFFF; TRISDbits.TRISD0=0; // RD0 is LED output used debug TRISDbits.TRISD3=0; // RD3 is output used debug // Switch Port Set TRISBbits.TRISB0 =1; // RB0 is SW1 input TRISBbits.TRISB8 =1; // RB8 is SW2 input // DSW Port Set (Not Used) TRISFbits.TRISF2 =1; // RF2 is DSW-b0 input TRISFbits.TRISF3 =1; // RF3 is DSW-b1 input TRISFbits.TRISF6 =1; // RF6 is DSW-b2 input (Not Used) TRISBbits.TRISB2 =1; // RB2 is DSW-b3 input (Not Used) // PAT PORT is ALL OUTPUT TRISFbits.TRISF5 =0; // DWN1 TRISDbits.TRISD2 =0; // CK1 TRISFbits.TRISF4 =0; // UP1 // ROTARY ENCODER PORT TRISBbits.TRISB4 =1; // RB4 is RE_A input TRISBbits.TRISB5 =1; // RB5 is RE_B input LATDbits.LATD0 = 1; // LED OFF LATDbits.LATD3 = 0; // Debug Port // Initialize LCD lcd_init(); lcd_inst_wr(DISP_ON_CURSOR_OFF_BLINK_OFF); const_lcd_disp(); // Inittalize Timer3(2KHz = Fcy /14740) OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_1 & T3_SOURCE_INT, 14740-1); // T3 ON & Enable Interrupt // ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_OFF); DISICNT = 0x0000; // Enable Interrupt // MAIN LOOP while(1) { // LATDbits.LATD3 = !LATDbits.LATD3; Start_Stop_SW_read(); Beat_No_Sel_SW_read(); Rotary_Encoder_read(); Beat_Period = 60000/BPM; T3_count_MAX = Beat_Period * 2; beat_no_disp(Beat_No, 0x86); tempo_disp(BPM, 0xc6); } }