/*********************************************************************** 2011 (C) Alex Dobrianski Stepper Motor controller module This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see ************************************************************************/ /*********************************************************************** see www.adobri.com for communication protocol spec ************************************************************************/ #include "int16CXX.H" // this line for debug and may be normal operations // on pin 15 (RA6) no oscilator output //#pragma config PWRTE=on, WDTE=off, FOSC=4, BODEN=off //#define DEBUG_OSC_PIN15 1 // this line for pin 15 (RA6) oscilator output 2MHz #pragma config PWRTE=off, WDTE=off, FOSC=5, BODEN=off #pragma config |= 0x2f20 // 0010 1111 0000 0000 // 1 = 1 = Code protection off // 0 = 0 = CCP1 function on RB3 // 1 = 1 = In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins // 11 = 11 = Write protection off // 1 = 1 = Code protection off; // 0 = 1 = RB3/PGM pin has PGM function, Low-Voltage Programming enabled // 0 = 0 = BOR disabled // 0 = 0 = RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD // 0 = 0 = PWRT enabled // 0 = 0 = WDT disabled // 1 00= FOSC=4 =100 = INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin // bit 13 CP: Flash Program Memory Code Protection bits // 1 = Code protection off; 0 = 0000h to 0FFFh code-protected (all protected) // bit 12 CCPMX: CCP1 Pin Selection bit // 1 = CCP1 function on RB0; 0 = CCP1 function on RB3 // bit 11 DEBUG: In-Circuit Debugger Mode bit // 1 = In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins // 0 = In-Circuit Debugger enabled, RB6 and RB7 are dedicated to the debugger // bit 10-9 WRT<1:0>: Flash Program Memory Write Enable bits // 11 = Write protection off // 10 = 0000h to 00FFh write-protected, 0100h to 0FFFh may be modified by EECON control // 01 = 0000h to 07FFh write-protected, 0800h to 0FFFh may be modified by EECON control // 00 = 0000h to 0FFFh write-protected // bit 8 CPD: Data EE Memory Code Protection bit // 1 = Code protection off; 0 = Data EE memory code-protected // bit 7 LVP: Low-Voltage Programming Enable bit // 1 = RB3/PGM pin has PGM function, Low-Voltage Programming enabled // 0 = RB3 is digital I/O, HV on MCLR must be used for programming // bit 6 BOREN: Brown-out Reset Enable bit // 1 = BOR enabled ; 0 = BOR disabled // bit 5 MCLRE: RA5/MCLR/VPP Pin Function Select bit // 1 = RA5/MCLR/VPP pin function is MCLR ; 0 = RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD // bit 3 PWRTEN: Power-up Timer Enable bit // 1 = PWRT disabled; 0 = PWRT enabled // bit 2 WDTEN: Watchdog Timer Enable bit // 1 = WDT enabled ; 0 = WDT disabled // bit 4, 1-0 FOSC<2:0>: Oscillator Selection bits // 111 = EXTRC oscillator; CLKO function on RA6/OSC2/CLKO // 110 = EXTRC oscillator; port I/O function on RA6/OSC2/CLKO // 101 = INTRC oscillator; CLKO function on RA6/OSC2/CLKO pin and port I/O function on RA7/OSC1/CLKI pin // 100 = INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin // 011 = ECIO; port I/O function on RA6/OSC2/CLKO // 010 = HS oscillator // 001 = XT oscillator // 000 = LP oscillator #pragma config reg2 = 0 #define Clock_8MHz #define bitset(i,j) i |= 1U << j #define bitclr(i,j) i &= ~(1U << j) #define bittest(i,j) (i & (1U<= BUFFER_LEN) iPtr1InQu = 0; iInQuSize++; } else W = RCREG; } } } else if (TXIF) { if (iOutQuSize) { TXREG = OutQu[iPtr2OutQu]; if (++iPtr2OutQu >= BUFFER_LEN) iPtr2OutQu = 0; iOutQuSize--; } else { if (!TRMT) TXIE = 0; } } //#pragma updateBank 0 // if (TMR0IF) // transfer byte using TMR0 // { // TMR0IF = 0; // if (!TMR0IE) // goto NextCheckBit; // } // else //NextCheckBit: // if (TMR1IF) // { // TMR1IF = 0; ////#pragma updateBank 1 // if (!TMR1IE) // goto Next2CheckBit; // } // else //Next2CheckBit: // if (RBIF) // { ////#pragma updateBank 0 // } ExitIntr: FSR = sv_FSR; // restore FSR if saved int_restore_registers // W, STATUS (and PCLATH) } //#define ONEBIT_TMR0_LEN 0x10 ///////////////////////////////////////////////COPY END////////// void enable_uart(void)//bit want_ints) { TX9 = 0; RX9 = 0; BRGH = 1; //Normal speed UART port 0x98 // 00000x00 BRGH: High Baud Rate Select bit //Asynchronous mode: // 1 = High speed 0 = Low speed SPBRG = 51;// 9600 //SPBRG = 25;// 19200 //SPBRG = 12;// 38400 //SPBRG = 8; // 57600 SYNC = 0; // port 0x98 = 000x0000 x=0 asynch mode 1-synchr SPEN = 1; // port 0x18 x0000000 SPEN: Serial Port Enable bit // 1 = Serial port enabled (configures RB2/SDO/RX/DT // and RB5/SS/TX/CK pins as serial port pins) //TXIF = 0; TXIE = 0; TXEN = 1; //Enable transmission port 0x8c // AUSART Transmit Interrupt Enable bit // 1 = Enabled 0 = Disabled ADDEN = 0; //RCIF = 0; // clean bit of receive interrupt RCIE = 1; // enable interrupt on recieve byte CREN = 1; // port 0x18 000x0000 CREN: Continuous Receive Enable bit // Asynchronous mode: 1 = Enables continuous receive //WREN = 1; } //void putch(unsigned char nate) //{ // TXREG = nate; // port 0x19 // while(TXIF == 0); // port 0x0c 000x0000 TXIF: // // AUSART Transmit Interrupt Flag bit // // 1 = The AUSART transmit buffer is empty // // (cleared by writing to TXREG) //} void putch(unsigned char simbol) { if (iOutQuSize == 0) { if (TRMT) TXREG = simbol; else goto SEND_BYTE_TO_QU; } else { if (iOutQuSize < BUFFER_LEN) { SEND_BYTE_TO_QU: OutQu[iPtr1OutQu] = simbol; if (++iPtr1OutQu >= BUFFER_LEN) iPtr1OutQu = 0; iOutQuSize++; TXIE = 1; } } } void puts(const char * s) { while(*s) { putch(*s); s++; } } // this function has to be called when iInQuSize>=0 only unsigned char getch(void) { unsigned char bRet = InQu[iPtr2InQu]; if (++iPtr2InQu >= BUFFER_LEN) iPtr2InQu = 0; iInQuSize --; return bRet; } unsigned char eeprom_read(unsigned char addr) { EEADR = addr; EECON1 &= 0x3F; RD = 1; return EEDATA; } void eeprom_write(unsigned char addr, unsigned char value) { EEADR = addr; EEDATA = value; EECON1 &= 0x3F; Carry = 0; if(GIE) Carry = 1; GIE = 0; WREN = 1; EECON2 = 0x55; EECON2 = 0xAA; WR = 1; WREN = 0; if(Carry) GIE = 1; while(WR) { } } void Reset_device(void) { // this is will be better at the begining of a program OSCCON = 0b01110000; //OSCILLATOR CONTROL REGISTER (ADDRESS 8Fh) // bit 6-4 IRCF<2:0>: Internal RC Oscillator Frequency Select bits // 000 = 31.25 kHz // 001 = 125 kHz // 010 = 250 kHz // 011 = 500 kHz // 100 = 1 MHz // 101 = 2 MHz // 110 = 4 MHz // 111 = 8 MHz // bit 3 OSTS: Oscillator Start-up Time-out Status bit(1) // 1 = Device is running from the primary system clock // 0 = Device is running from T1OSC or INTRC as a secondary system clock // Note 1: Bit resets to ‘0’ with Two-Speed Start-up mode and LP, XT or HS selected as the // oscillator mode. // bit 2 IOFS: INTOSC Frequency Stable bit // 1 = Frequency is stable // 0 = Frequency is not stable // bit 1-0 SCS<1:0>: Oscillator Mode Select bits // 00 = Oscillator mode defined by FOSC<2:0> // 01 = T1OSC is used for system clock // 10 = Internal RC is used for system clock // 11 = Reserved #ifdef _NOT_SIMULATOR while((OSCCON&0b00000100) == 0); //Wait for frequency to stabilize #endif ANSEL = 0b00000000; //Turn pins to Digital instead of Analog CMCON = 0b00000111; //Turn off comparator on RA port // for each unit it is individual // RA0,1,2,3,4,7 this will be DATA0,1,2,3,4,5 TRISA = 0b10011111; //0 = Output, 1 = Input PORTA = 0b11111111; // RB5 - Serial Out Pin 11 // RB2 - Serial In Pin 8 // RB4-RB7 - Serial // RB0,1 will be DATA6,6 // RB2 - serial input // RB4 == W/R (out) // RB5 - serial out // set to 1 // RB6 == RST (out) // RB7 == CLCR (out) TRISB = 0b00000111; //0 = Output, 1 = Input //bitclr(OPTION,RBPU_); //Each of the PORTB pins has a weak internal pull-up. A //single control bit can turn on all the pull-ups. This is //performed by clearing bit RBPU (OPTION_REG<7>). //The weak pull-up is automatically turned off when the //port pin is configured as an output. The pull-ups are //disabled on a Power-on Reset. // default RST(RB6) = 1; W/R(RB3) = 0; CLCR(RB7) = 1; PORTB = 0b11100111; //RBIF = 0; //RBIE = 1; enable_uart(); //Setup the hardware UART for 20MHz at 9600bps // next two bits has to be set after all intialization done //PEIE = 1; // bit 6 PEIE: Peripheral Interrupt Enable bit // 1 = Enables all unmasked peripheral interrupts // 0 = Disables all peripheral interrupts //GIE = 1; // bit 7 GIE: Global Interrupt Enable bit // 1 = Enables all unmasked interrupts // 0 = Disables all interrupts ///////////////////////////////////2COPY BEGIN////////////// /////////////////////////////////////2COPY END///////////////////// } //////////////////////////////////////3COPY BEGIN/////////////////// ///////////////////////////////////////3COPY END////////////////////////// void readDataBus(void) { unsigned char readHex; unsigned char sendHex; readHex = PORTA & 0x1f; if (bittest(PORTA,7)) bitset(readHex,5); // bit 5 == RA7 if (bittest(PORTB,0)) bitset(readHex,6); // bit 6 == RB0 if (bittest(PORTB,1)) bitset(readHex,7); // bit 7 == RB1 sendHex = (readHex >> 4) + '@'; putch(sendHex); sendHex = (readHex & 0xf) + '@'; putch(sendHex); } void setDataBus(void) { if (bittest(byteHex,0)) #pragma updateBank 0 bitset(PORTA,0); // bit 0 == RA0 else bitclr(PORTA,0); if (bittest(byteHex,1)) bitset(PORTA,1); // bit 1 == RA1 else bitclr(PORTA,1); if (bittest(byteHex,2)) bitset(PORTA,2); // bit 2 == RA2 else bitclr(PORTA,2); if (bittest(byteHex,3)) bitset(PORTA,3); // bit 3 == RA3 else bitclr(PORTA,3); if (bittest(byteHex,4)) bitset(PORTA,4); // bit 4 == RA4 else bitclr(PORTA,4); if (bittest(byteHex,5)) bitset(PORTA,7); // bit 5 == RA7 else bitclr(PORTA,7); if (bittest(byteHex,6)) bitset(PORTB,0); // bit 6 == RB0 else bitclr(PORTB,0); if (bittest(byteHex,7)) bitset(PORTB,1); // bit 7 == RB1 else bitclr(PORTB,1); #pragma updateBank 1 } void ShowMessage(void) { puts("\n\rLTRX"); putch(UnitADR); puts("\n\rOK\n\r"); } // ASCI // @ == 0 // A == 1 // B == 2 // C == 3 // D == 4 // E == 5 // F == 6 // G == 7 // H == 8 // I == 9 // : == 0xA J // ; == 0xB K // < == 0xc L // = == 0xd M // > == 0xe N // ? == 0xf O void ProcessCMD(unsigned char bByte) { if (!getCMD) { if (bByte == UnitADR) { getCMD = 1; } else putch(bByte); } else { if (getDataL) { if (getHbit) { getHbit = 0; byteHex = bByte << 4; } else { byteHex = byteHex | (bByte & 0x0f); getDataL = 0; //getCMD = 0; setDataBus(); bitclr(PORTB,7); // CLCR == LOW, counter will be advanced on 'd' } } else if (getDataH) { //if (getHbit) //{ // getHbit = 0; // byteHex = bByte << 4; //} //else //{ // byteHex = byteHex | (bByte & 0x0f); // setDataBus(); // uiCount++; // if (uiCount == 32768) // { getDataH = 0; getCMD = 0; // } // bitclr(PORTB,7); // CLCR == LOW, counter will be advanced on 'd' //} } else { //getCMD = 0; if (bByte == UnitADR) { getCMD = 0; } if (bByte == 'W') // output RB3 (PIN10) high // write to memory (Write op) { // this command for DAC bitset(PORTB,4); // W/R = high // DataBus will be in output mode TRISA = 0b00000000; //0 = Output, 1 = Input TRISB = 0b00000100; //0 = Output, 1 = Input byteHex = 0; setDataBus(); } else if (bByte == 'w') // output RB3 (PIN9) low // write memory -> DAC (Read op) { // this commant for DAC bitclr(PORTB,4); // W/R == low // DataBus will be in input mode TRISA = 0b10011111; //0 = Output, 1 = Input TRISB = 0b00000111; //0 = Output, 1 = Input } if (bByte == 'V') // output RB3 (PIN10) high // write to memory (Write op) from ADC { // this is for ADC bitset(PORTB,4); // W/R = high // DataBus will be in input mode TRISA = 0b10011111; //0 = Output, 1 = Input TRISB = 0b00000111; //0 = Output, 1 = Input } else if (bByte == 'r') // output RB6 (PIN12) low // RST low bitclr(PORTB,6); else if (bByte == 'R') // output RB6 (PIN12) high // RST high bitset(PORTB,6); else if (bByte == 'c') // output RB6 (PIN12) low //CLCR low { //if (readDataL) // if read was requaested then read byte and send as 2 bytes //{ // readDataL = 0; //} bitclr(PORTB,7); } else if (bByte == 'C') // output RB6 (PIN12) high // CLCR high bitset(PORTB,7); else if (bByte == 'd') // data == next 2 bytes will be hex values { //getCMD = 1; getDataL = 1; getDataH = 0; getHbit = 1; bitset(PORTB,7); // CLCR =RB7=(PIN13)==HIGH on first it will be NOP(CLCR already high) // on each next it will be advance counter } else if (bByte == 'h') // read data == and next 2 bytes will be tranfered back to host { //getCMD = 1; //readDataL = 1; readDataBus(); bitset(PORTB,7); // CLCR =RB7=(PIN13)==HIGH on first it will be NOP(CLCR already high) // on each next it will be advance counter } else if (bByte == 'D') // data == next 2*32768 bytes will be hex values { uiCount = 0; //getCMD = 1; getDataL = 0; getDataH = 1; getHbit = 1; bitset(PORTB,7); // CLCR ==HIGH on first it will be NOP(CLCR already high) // on each next it will be advance counter } #ifdef DEBUG_OSC_PIN15 //for debuging oscilator a) low/high b) PIN15 oscilator output // else if (bByte == 'o') // output RA6 (PIN12) low //OCS low bitclr(PORTA,6); else if (bByte == 'O') // output RB6 (PIN12) high // OCS high bitset(PORTA,6); else if (bByte == '-') // output RA6 (PIN12) low //OCS low bitclr(PORTA,6); else if (bByte == '+') // output RB6 (PIN12) high // OCS high { readDataBus(); bitset(PORTA,6); } #endif else if (bByte == '?') // output RB6 (PIN12) low // RST low ShowMessage(); } } } void main() { Reset_device(); // needs to check what is it: //if (TO) // Power up or MCLR { iPtr1InQu = 0; iPtr2InQu = 0; iInQuSize = 0; iPtr1OutQu = 0; iPtr2OutQu = 0; iOutQuSize = 0; getCMD = 0; getDataL = 0; getDataH = 0; // Unit == 1 (one) is ADC and unit == 2 (two) is DAC UnitADR = '1'; //UnitADR = '2'; /////////////////////////////////4COPY BEGIN/////////////////// //////////////////////////////////////4COPY END///////////////////////// } //////////////////////////////////////5COPY BEGIN/////////////////////// /////////////////////////////////////////5COPY END/////////////////// PEIE = 1; // bit 6 PEIE: Peripheral Interrupt Enable bit // 1 = Enables all unmasked peripheral interrupts // 0 = Disables all peripheral interrupts GIE = 1; // bit 7 GIE: Global Interrupt Enable bit // 1 = Enables all unmasked interrupts // 0 = Disables all interrupts RBIF = 0; ShowMessage(); while(1) { if (iInQuSize) { ProcessCMD(getch()); } } } // at the end will be Sleep which then continue to main