/***********************************************************************
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