Created
October 14, 2011 04:39
-
-
Save Addidis/1286262 to your computer and use it in GitHub Desktop.
Beta source for drawbot firmware (don't use this unless you know what it is)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Drawbot 2.1 Firmware | |
// Inspired by the Makeitlast contest where the original example is from | |
// This version by @Addidis | |
// See www.jeselectronics.com for more info | |
///////////////////////////////////////////////////////////////////////////// | |
// Include files | |
///////////////////////////////////////////////////////////////////////////// | |
#include <p18lf26k22.h> // This file includes definitions for all of the registers on our chip | |
#include <usart.h> //see the c18 documentation for these | |
#include <math.h> | |
#include "delays.h" | |
#include "AN991.h" | |
#include "i2c.h" | |
//#include "EEP.h" //internal eeprom lib (left empty for user to use) | |
#pragma config FOSC = INTIO67 //use INTOSC | |
#pragma config PLLCFG = OFF //clocked at 16MHz | |
#pragma config WDTEN = OFF //WDT off | |
#pragma config PBADEN = OFF | |
// Fix a compiler bug | |
#undef INTCON | |
#undef INTCONbits | |
#define numSteps 400 //Number of steps per revolution us the | |
#define sw1 PORTBbits.RB0 //todo: perhaps juggle these around | |
#define sw2 PORTBbits.RB4 | |
#define sw3 PORTBbits.RB3 | |
#define sw4 PORTBbits.RB2 | |
#define sw5 PORTBbits.RB1 | |
//led macros | |
#define mLED_1 LATCbits.LATC2 | |
#define mLED_1_On() mLED_1 = 1; | |
#define mLED_1_Off() mLED_1 = 0; | |
#define mLED_1_Toggle() mLED_1 = !mLED_1; | |
///////////////////////////////////////////////////////////////////////////// | |
// Function declarations | |
// Declare any user functions that you want to use here | |
///////////////////////////////////////////////////////////////////////////// | |
void main (void); | |
void setup(void); | |
void loop(void); | |
void console(void); | |
void low_isr(void); | |
void high_isr(void); | |
void putc1USART( char data ); | |
void puts1USART( char *data ); | |
void putrs1USART ( const MEM_MODEL rom char *data); | |
void OpenI2C1( unsigned char sync_mode, unsigned char slew ); | |
void drawcircle(float a, float b, int r); | |
void setHome(void); | |
void getvars(void); | |
//////////////////////////////////////////////////////////////////////////// | |
//Variable declarations | |
//////////////////////////////////////////////////////////////////////////// | |
// Bit masks for the motor state tables | |
int A_C1states[4] = {0x00, 0x01, 0x01, 0x00}; | |
int A_C2states[4] = {0x02, 0x02, 0x00, 0x00}; | |
int B_C1states[4] = {0x00, 0x04, 0x04, 0x00}; | |
int B_C2states[4] = {0x08, 0x08, 0x00, 0x00}; | |
//Step variables for tracking | |
int Astate = 0; // state of left motor | |
int Bstate = 0; // state of right motor | |
int stepUnit = 100; // x= numSteps/(pi*Diameterofspool) | |
int w; // width of drawing field | |
int h; // height of drawing field | |
int a1; // length of left string | |
int b1; // length of right string | |
int x1; // current x position | |
int y1; // current y position | |
volatile int pause = 1; | |
//eprom declarations | |
//See AN991 PDF | |
unsigned char Length = 1; //length for byte read | |
volatile unsigned char PageString[128]; //Holds the device page data to/from EEPROM | |
unsigned int PageSize = 0x80; //Page size in bytes 128 | |
volatile unsigned short pageadd = 0; // variable for page address | |
volatile unsigned char ControlByte=0b10100110; //Control Byte | |
volatile unsigned char HighAdd=0; //High Order Address Byte | |
volatile unsigned char LowAdd=0; //Low Order Address Byte | |
typedef volatile union Pages { // Union to combine chars into ints | |
volatile int lc; | |
volatile unsigned char bc[2]; | |
}; | |
//serial | |
volatile unsigned char receiveCharacter = 0; // Stores the last character that was | |
unsigned char checksum = 0; //checksum for serial transfers | |
//Drawing variables | |
//First set are stored in DBI file header and retrieved on startup from eeprom | |
volatile unsigned int widthT = 0; //total width of paper | |
volatile unsigned int height = 0; //total height of paper | |
volatile unsigned int numofpixWide = 0; //from encoded image | |
volatile unsigned int numofpixHigh = 0; //from encoded image | |
volatile unsigned int speed = 0; //speed of drawing 10000 is kinda 50 % | |
volatile unsigned int caddystablizingdelay = 0; //delay after a move command | |
//these are calculated from the header data retrieved | |
int rightW = 0; //right side of the paper Calculated from header | |
int leftW = 0; //left side of the paper Calculated from header | |
volatile int offset = 100; // start the bottom of page at +100 | |
volatile char speedmap = 0; //used to get variables from the draw data | |
volatile char delaymap = 0; //used to get variables from the draw data | |
//********************************************************************************************************************* | |
// Begin code | |
//********************************************************************************************************************* | |
void main (void) | |
{ | |
// Call the setup function once to put everything in order | |
setup(); | |
// Then call the loop() function over and over | |
while (1) | |
{ | |
loop(); | |
} | |
} | |
// Map function, from: | |
// http://www.arduino.cc/en/Reference/Map | |
long map(long x, long in_min, long in_max, long out_min, long out_max) | |
{ | |
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | |
} | |
void smalldelay(void) | |
{ | |
Delay1KTCYx(10); //save a few bytes this way | |
} | |
void largedelay(void) | |
{ | |
Delay10KTCYx(120); //save a few bytes this way | |
} | |
void setHome(void) | |
{ | |
// set home position | |
x1 = w/2; | |
y1 = h; | |
// calculate starting lengths | |
a1 = sqrt(pow(x1, 2)+pow(y1, 2)); | |
b1 = sqrt(pow((w-x1), 2)+pow(y1,2)); | |
} | |
void setSpeed(void) | |
{ | |
PIE1bits.RC1IE=0; //Turn off interrupts so we can catch the next byte here and not in interrupt routine | |
while (!DataRdy1USART()); //wait for byte | |
speed = map(RCREG, 1,127, 20000,500); //Retrieve and map value | |
PIE1bits.RC1IE=1; //Turn on interrupts | |
} | |
void setdelay(void) | |
{ | |
PIE1bits.RC1IE=0; //Turn off interrupts so we can catch the next byte here and not in interrupt routine | |
while (!DataRdy1USART()); //wait for byte | |
caddystablizingdelay = map(RCREG, 1,127, 0,200); //Retrieve and map value | |
PIE1bits.RC1IE=1; //Turn on interrupts | |
} | |
void clearunion(void) | |
{ | |
union Pages word; | |
word.lc=0; | |
} | |
void turnMotors(int stepDirA, int stepDirB,int delay) | |
{ | |
// turn the left and right motors one step in the given direction | |
unsigned int count; | |
a1 += stepDirA; | |
b1 += stepDirB; | |
Astate-=stepDirA; | |
Bstate+=stepDirB; | |
if (Astate == -1) { Astate = 3; } | |
if (Bstate == -1) { Bstate = 3; } | |
Astate = Astate %4; | |
Bstate = Bstate %4; | |
PORTA = A_C1states[Astate] | A_C2states[Astate] | | |
B_C1states[Bstate] | B_C2states[Bstate] ; | |
for( count = 0; count < delay; count++) {} // delay is sent the speed variable | |
} | |
void moveTo(int x2, int y2, int delay) | |
{ | |
// move from the current point (x1, y1) to (x2, y2) | |
// implement Breshenham's algorithm to straighten this out | |
int dirA =0; | |
int dirB=0; | |
int a2 = sqrt(pow(x2, 2)+pow(y2, 2)); | |
int b2 = sqrt(pow((w-x2), 2)+pow(y2,2)); | |
if (a2 > a1) { dirA = 1; } | |
if (a2 < a1) { dirA = -1; } | |
if (b2 > b1) { dirB = 1; } | |
if (b2 < b1) { dirB = -1; } | |
while ((a1!=a2) || (b1!=b2)) { | |
if (a1 == a2) { dirA = 0; } | |
if (b1 == b2) { dirB = 0; } | |
turnMotors(dirA, dirB, delay); | |
} | |
x1=x2; | |
y1=y2; | |
} | |
void testpaper(void) | |
{ | |
LATCbits.LATC2 = 0; //led off | |
getvars(); //Make sure we use the dimensions from the image file | |
moveTo(w/2,h-height,800); //test top of paper | |
while (sw2==1){}; | |
moveTo(w/2,h,800); //moveback | |
moveTo(w/2+leftW,h,800); //test left of paper | |
while (sw2==1){}; | |
moveTo(w/2+rightW,h,800); //test right of paper | |
while (sw2==1){}; | |
moveTo(w/2,h,800); //test top of paper | |
LATCbits.LATC2 = 1; //led on | |
} | |
void trimcady(void) | |
{ | |
int i; | |
if (receiveCharacter != 0) // See if we got a command | |
{ | |
switch (receiveCharacter) | |
{ | |
case 'g': //Move caddy up 4 steps | |
for(i=0;i<4;i++){turnMotors(-1,-1,500);} | |
receiveCharacter = 0; | |
break; | |
case 'h': //move caddy down 4 steps | |
for(i=0;i<4;i++){turnMotors(1,1,500);} | |
receiveCharacter = 0; | |
break; | |
case 'j': //move caddy left 100 steps | |
for(i=0;i<4;i++){turnMotors(-1,1,500);} | |
receiveCharacter = 0; | |
break; | |
case 'k': //move caddy right | |
for(i=0;i<4;i++){turnMotors(1,-1,500);} | |
receiveCharacter = 0; | |
break; | |
} | |
} | |
} | |
void console(void) | |
{ | |
int i; | |
int t; | |
union Pages word; | |
int numofpages; | |
if (receiveCharacter != 0) | |
{ | |
trimcady(); //trim cady future update will add 1 step increment caddy movements while paused to realign after an adjustment | |
// See if we got a command | |
switch (receiveCharacter) | |
{ | |
case 'a': //left stepper up 4 steps | |
for(i=0; i<=4; i++){turnMotors(-1,0,500);} | |
break; | |
case 'q': //Left stepper up one turn | |
for(i=0; i<400; i++){turnMotors(-1,0,500);} | |
break; | |
case 's': //left stepper down 4 steps | |
for(i=0; i<=4; i++){turnMotors(1,0,500);} | |
break; | |
case 'w': //stepper one direction b one turn | |
for(i=0; i<400; i++){turnMotors(1,0,500);} | |
break; | |
case 'f': //Right stepper down 4 steps | |
for(i=0; i<=4; i++){turnMotors(0,1,500);} | |
break; | |
case 'r': //stepper down one turn | |
for(i=0; i<400; i++){turnMotors(0,1,500);} | |
break; | |
case 'd': //stepper two up 4 steps | |
for(i=0; i<=4; i++) {turnMotors(0,-1,500);} | |
break; | |
case 'e': //stepper one direction b one turn | |
for(i=0; i<400; i++){turnMotors(0,-1,500);} | |
break; | |
case 0x11: //Set Speed of drawing (DBC only) | |
setSpeed(); | |
break; | |
case 0x12: //Set delay between moves to reduce vibration (DBC only) | |
setdelay(); | |
break; | |
case 0x05: //Set delay between moves to reduce vibration (DBC only) | |
setHome(); | |
testpaper(); | |
break; | |
case 0x01: //download drawdata (DBC only) | |
PIE1bits.RC1IE=0; //Turn off interrupts | |
LATCbits.LATC2 = 0; //Turn off led to tell user mode entered | |
while (!DataRdy1USART()); //wait for first byte of numberof pages to download | |
word.bc[1] = RCREG; //put first byte in union | |
while (!DataRdy1USART()); //wait for second byte of numberof pages to download | |
word.bc[0] = RCREG; //put second byte in union | |
for (t=0; t<(word.lc*PageSize); t+=PageSize){ //Loop threw pages | |
checksum=0; | |
for(i=0; i<128; i++){ //Get 128 bytes Stick them in the PageString | |
while (!DataRdy1USART()); //wait for byte | |
PageString[i] = RCREG; //Stick it in PageString | |
} | |
pageadd = t; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); //Makes it easy to deal with pageaddress | |
LowAdd = (pageadd&0xff); | |
HDPageWriteI2C(ControlByte, HighAdd, LowAdd, PageString ); //High Density Page Write the data | |
largedelay(); //eeprom writes slow. . . | |
HDSequentialReadI2C(ControlByte, HighAdd, LowAdd, PageString, PageSize ); //read back the page we just wrote to verify eprom endurance | |
for (i=0; i<PageSize; i++){checksum+= PageString[i];} //add all the bytes to checksum | |
Write1USART((char)checksum); //send checksum | |
while (!DataRdy1USART()); //wait for byte | |
if (RCREG==21){break;} //if the checksum is different break | |
mLED_1_Toggle(); //if not induce joy and continue | |
} | |
LATCbits.LATC2 = 1; //turn on led to tell user its finished | |
PIE1bits.RC1IE = 1; //Turn back on interrupts | |
getvars(); //get new vars | |
break; | |
case 0x13: //Write new config from DBC (DBC only) | |
PIE1bits.RC1IE=0; //Turn off interrupts | |
mLED_1_Toggle(); //led off | |
ControlByte = 0b10100110; | |
pageadd = 0; //header is on first page | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDSequentialReadI2C(ControlByte, HighAdd, LowAdd, PageString, PageSize ); //Read the first page | |
Write1USART((char)0x06); //ack for new config to be sent | |
for (t=0; t<=16; t+=1){ //Loop threw pages | |
while (!DataRdy1USART()); //wait for byte | |
PageString[i] = RCREG; //Stick it in PageString buffer with the bytes we are not changing | |
mLED_1_Toggle(); //Induce joy | |
} | |
HDPageWriteI2C(ControlByte, HighAdd, LowAdd, PageString ); //High Density Page Write | |
largedelay(); //slow eprom write | |
getvars(); //get new vars | |
LATCbits.LATC2 = 1; //led on | |
PIE1bits.RC1IE = 1; //Turn on interrupts | |
break; | |
case '~': //Send data out serial (DBC or console app) I think this is fail sauce atm. Need to test it. | |
for (t=0; t<((numofpixWide*numofpixHigh)+16); t+=PageSize){ //Loop threw pages | |
ControlByte = 0b10100110; | |
pageadd = t; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDSequentialReadI2C(ControlByte, HighAdd, LowAdd, PageString, PageSize ); //High Density Page Read | |
for(i=0; i<128; i++){Write1USART((char)PageString[i]);} //write it to serial | |
} | |
break; | |
} | |
receiveCharacter=0; //clear byte | |
} | |
//*********************** | |
// Switch handeling code. | |
//*********************** | |
if (sw2==0) //if sw3 is pressed | |
{ | |
smalldelay(); //wait a bit | |
if(sw2==0) //if its still pressed | |
{ | |
receiveCharacter='a'; //move motor one direction A 4 steps | |
largedelay(); //Delay to see if its held down or not | |
if(sw2==0){receiveCharacter='q';} //Its still held down some one is impatient ;) | |
} //move motor one direction A untill released | |
}//end sw2 | |
if (sw3==0) //if sw3 is pressed | |
{ | |
smalldelay(); //wait a bit | |
if(sw3==0) //if its still pressed | |
{ | |
receiveCharacter='s'; //move motor one direction B 4 steps | |
largedelay(); //Delay to see if its held down or not | |
if(sw3==0){receiveCharacter='w';} //Its still held down some one is impatient ;) | |
} //move motor one direction B untill released | |
}//end sw3 | |
if (sw4==0) //if sw4 is pressed | |
{ | |
smalldelay(); //wait a bit | |
if(sw4==0) //if its still pressed | |
{ | |
receiveCharacter='d'; //move motor Two direction A 4 steps | |
largedelay(); //Delay to see if its held down or not | |
if(sw4==0){receiveCharacter='e';} //Its still held down some one is impatient ;) | |
} //move motor Two direction A untill released | |
}//end sw4 | |
if (sw5==0) //if sw5 is pressed | |
{ | |
smalldelay(); //wait a bit | |
if(sw5==0) //if its still pressed | |
{ | |
receiveCharacter='f'; //move motor two direction B 4 steps | |
largedelay(); //Delay to see if its held down or not | |
if(sw5==0){receiveCharacter='r';} //Its still held down some one is impatient ;) | |
} //move motor one direction B untill released | |
}//end sw5 | |
} //end trim motors | |
void setup(void) | |
{ | |
OSCCONbits.IRCF=111; | |
//Set all unused pins as output low | |
//todo: unused pins | |
TRISA = 0x00; // Set all of the pins on Port A to be outputs, low | |
PORTA = 0x00; | |
TRISB = 0B00011111; // Set up buttons as inputs RB0-START&\PAUSE\RESUME RB1 RB2 RB3 RB4 | |
//led | |
TRISCbits.TRISC2=0; //set as output | |
LATCbits.LATC2=1; //set output high | |
//I2C pin config | |
TRISCbits.TRISC3 = 1; //Must be set as inputs for an991 to take over | |
TRISCbits.TRISC4 = 1; | |
//I2C setup | |
ANSELCbits.ANSC3 = 0; // Disable analog mode for SCA | |
ANSELCbits.ANSC4 = 0; // Disable analog mode for SDA | |
SSP1STAT=0b10000000; | |
SSP1CON1=0b00101000; | |
SSP1ADD=0x27; //16mhz fosc/4 , 100Khz | |
SSP1CON2=0x00; | |
SSP1CON1bits.SSPEN=1; //Turn on MSSP | |
//Set up int0 for start &| pause resume | |
INTCONbits.GIE=1; | |
INTCON2bits.INTEDG0=1; | |
INTCONbits.INT0IF=0; | |
INTCONbits.INT0IE=1; | |
//serial port setup 9600 baud (see manual, page 275) | |
BAUDCON1= 0b00000000; | |
TXSTA1bits.BRGH = 0; | |
BAUD1CONbits.BRG16 = 0; | |
SPBRG1 = 0x19; | |
SPBRGH1 = 0x00; | |
// Serial port configuration | |
TRISCbits.TRISC6 = 1; // TX pin an input (p264 ds) | |
TRISCbits.TRISC7 = 1; // RX pin an input | |
ANSELCbits.ANSC7 = 0; // Specifically, an analog input | |
RCONbits.IPEN = 0; // Interrupt priority off | |
INTCONbits.PEIE = 1; // Peripheral Interrupt Enable bit | |
PIR1bits.RC1IF=0; // clear Interupt flag | |
PIE1bits.RC1IE = 1; // Turn on interrupts on serial receive | |
//turn on serial port | |
RCSTA1bits.CREN = 1; // Enable receive mode on the serial port | |
TXSTA1bits.TXEN = 1; // Enable transmitter | |
RCSTA1bits.SPEN = 1; // Enable receiver | |
receiveCharacter = RCREG; // some pic you need to clear this a few times for it to start functioning. Just a habbit I got into. | |
receiveCharacter = RCREG; | |
getvars(); | |
// This is not the paper size. | |
w = 72*stepUnit; //This is the distance between the steppers in inches | |
h = 36*stepUnit; //This is how far down the bottom is in inches | |
setHome(); //The pen must start at w/2 , h or for this set up 3 feet from either motor , and 3 feet down. | |
} | |
void getvars(void) | |
{ | |
union Pages word; | |
clearunion(); | |
pageadd = 4; //byte reads so start where we need to | |
ControlByte = 0b10100110; //todo: once its all tested and working try to remove all of these, dont think we need it. | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get numofpixWideMSB | |
pageadd ++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[0], Length); //get numofpixWideLSB | |
numofpixWide = word.lc; | |
clearunion(); | |
pageadd++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get numofpixHighMSB | |
pageadd ++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[0], Length); //get numofpixHighLSB | |
numofpixHigh = word.lc; | |
clearunion(); | |
pageadd++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get paperwidthMSB | |
pageadd ++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[0], Length); //get paperwidthLSB | |
widthT = word.lc; | |
clearunion(); | |
pageadd++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get paperheightMSB | |
pageadd ++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[0], Length); //get paperheightLSB | |
height = word.lc; | |
clearunion(); | |
pageadd++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get speed | |
speedmap = word.bc[1]; | |
clearunion(); | |
pageadd++; | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &word.bc[1], Length); //get delay | |
delaymap = word.bc[1]; | |
clearunion(); | |
//set rightw | |
rightW = widthT/2; //right side of the paper | |
//set leftW | |
leftW = (widthT/2)- (widthT/2)-(widthT/2); //left side of the paper in grid units (inches) | |
//set speed | |
speed = map(speedmap, 1,127, 20000,500); //Retrieve and map value | |
//set delay | |
caddystablizingdelay = map(delaymap, 1,127, 0,200); //Retrieve and map value | |
} | |
//not used atm saving space | |
/* | |
void drawcircle(float a, float b, int r) | |
{ | |
float t; | |
float x; | |
float y; | |
int x2; | |
int y2; | |
for(t=0;t<=8; t+=.25){ | |
x = (a + (r * cos(t))); | |
y = (b + (r * sin(t))); | |
x2 = x; | |
y2=y; | |
moveTo(x2, y2,6500); | |
} | |
} | |
*/ | |
void drawpixel(int startx, int starty, char shade, int direction) | |
{ | |
int widthofpixel = widthT/numofpixWide; | |
int heightofpixel = (height-offset)/numofpixHigh; | |
// int rows = numofpixHigh/2; | |
int newh = h-offset; | |
Delay10KTCYx( caddystablizingdelay ); | |
if(shade== '0'){ //Black | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
//The comments are not accurate after shade=0 , they are next up to be redone. | |
moveTo(startx,starty-heightofpixel,speed); //move up heightofpixel | |
moveTo(startx,starty,speed); //move back | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-heightofpixel,speed);//move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
moveTo(startx+widthofpixel,starty,speed); //move to end of pixel | |
moveTo(startx+widthofpixel,starty-heightofpixel,speed); //moveto end of pixel top | |
moveTo(startx+widthofpixel,starty,speed); //move to end of pixel | |
} | |
if(shade== '1'){ //black--1 | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx,starty-heightofpixel/4*3,speed); //move up heightofpixel | |
moveTo(startx,starty,speed); //move back | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-heightofpixel,speed);//move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
moveTo(startx+widthofpixel-1,starty-(heightofpixel/4)*3,speed); //moveto end of pixel top | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
} | |
if(shade== '2'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx,starty-(heightofpixel/4)*2,speed); //move up heightofpixel | |
moveTo(startx,starty,speed); //move back | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-heightofpixel,speed);//move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
moveTo(startx+widthofpixel-1,starty-(heightofpixel/4)*2,speed); //moveto end of pixel top | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
} | |
if(shade=='3'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx,starty-(heightofpixel/4)*2,speed); //move up heightofpixel | |
moveTo(startx,starty,speed); //move back | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-(heightofpixel/4)*3,speed);//move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-(heightofpixel/4)*3,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
moveTo(startx+widthofpixel-1,starty-(heightofpixel/4)*2,speed); //moveto end of pixel top | |
moveTo(startx+widthofpixel-1,starty,speed); //move to end of pixel | |
} | |
if(shade=='4'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-(heightofpixel/4)*3,speed); //move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-(heightofpixel/4)*3,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
} | |
if(shade=='5'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx+widthofpixel/4,starty,speed); //move to 1/4 width of pixel | |
moveTo(startx+widthofpixel/4,starty-(heightofpixel/4)*2,speed); //move to 1/4 width of pixel top | |
moveTo(startx+widthofpixel/4,starty,speed); //move back | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move to middle of pixel | |
moveTo(startx+(widthofpixel/4)*3,starty-(heightofpixel/4)*2,speed); //move to middle of pixel up to top | |
moveTo(startx+(widthofpixel/4)*3,starty,speed); //move back | |
} | |
if(shade=='6'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-heightofpixel,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
Delay10KTCYx(caddystablizingdelay);//delay to stabilize caddy | |
} | |
if(shade=='7'){ | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-(heightofpixel/4)*3,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
Delay10KTCYx(caddystablizingdelay);//delay to stabilize caddy | |
} | |
if(shade=='8'){ //near white | |
if(direction == 2){ | |
widthofpixel = widthofpixel - widthofpixel - widthofpixel; | |
} | |
moveTo(startx+widthofpixel/2,starty,speed); //move to middle of pixel | |
moveTo(startx+widthofpixel/2,starty-(heightofpixel/4)*2,speed); //move to middle of pixel up to top | |
moveTo(startx+widthofpixel/2,starty,speed); //move back | |
Delay10KTCYx(caddystablizingdelay);//delay to stabilize caddy | |
} | |
} | |
// This function is called repeatedly | |
void loop(void) | |
{ | |
LATCbits.LATC2 = pause; | |
if(pause==0) // This is a flag so you can trim motors before drawing. Pause is actually handled in interrupt once drawing is started. | |
{ | |
int widthofpixel = widthT/numofpixWide; | |
int heightofpixel = (height-offset)/numofpixHigh; | |
int rows = numofpixHigh/2; | |
int newh = h-offset; | |
int shade = 0; | |
int curentpixel; | |
int halfofpixelswide = numofpixWide/2; | |
pageadd = ((numofpixHigh-1)*numofpixWide)+16; //set pageadd to first byte of last row. | |
setHome(); //This is so if you trim the motors it doesnt remember where you started as the home position. | |
//Draw code | |
//loop to draw number of pixelsH /2 left to right, up one right to left to start , looped number of pixels high divided by 2 | |
for(rows = 0; rows<numofpixHigh*heightofpixel; rows+=heightofpixel*2) | |
{ | |
//draws from far left to middle of the first line in the row (direction 1) | |
for(curentpixel = halfofpixelswide*widthofpixel; curentpixel>0; curentpixel-=widthofpixel) | |
{ | |
//read data from eeprom | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &shade, Length); //High Density Byte Read | |
pageadd++; | |
moveTo(w/2-curentpixel,newh-rows ,speed); | |
drawpixel(w/2-curentpixel,newh-rows,shade,1); | |
} | |
//draws from middle to far right of the first line in the row (direction 1) | |
for(curentpixel=0; curentpixel< halfofpixelswide*widthofpixel; curentpixel+=widthofpixel) | |
{ | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &shade, Length); | |
pageadd++; | |
moveTo(w/2+curentpixel, newh-rows,speed); | |
drawpixel(w/2+curentpixel,newh-rows,shade,1); | |
} | |
pageadd-=(numofpixWide+1); | |
//draws from far right, to middle second line in the row (direction 2 ) | |
for(curentpixel= (widthofpixel*halfofpixelswide); curentpixel>0; curentpixel-=widthofpixel) | |
{ | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &shade, Length); | |
pageadd--; | |
moveTo(w/2+curentpixel, newh-rows-heightofpixel,speed); | |
drawpixel(w/2+curentpixel,newh-rows-heightofpixel,shade,2); | |
} | |
//draws from middle to left second line in the row (direction 2 ) | |
for(curentpixel= 0; curentpixel<=widthofpixel*halfofpixelswide; curentpixel+=widthofpixel) | |
{ | |
ControlByte = 0b10100110; | |
HighAdd = ((pageadd>>8)&0xff); | |
LowAdd = (pageadd&0xff); | |
HDByteReadI2C(ControlByte, HighAdd, LowAdd , &shade, Length); | |
pageadd--; | |
moveTo(w/2-curentpixel, newh-rows-heightofpixel,speed); | |
drawpixel(w/2-curentpixel, newh-rows-heightofpixel,shade,2); | |
} | |
pageadd-=(numofpixWide-2); | |
} | |
while (sw2==1){{Delay1KTCYx(500);Delay1KTCYx(500);mLED_1_Toggle();}}; // Only print once | |
} | |
else if (pause==1) //allow trimming on first power on, and any time drawing is not started yet | |
{ | |
console(); | |
} | |
} | |
//Interrupt vectors | |
//REFEREnce DS51288a-page 27 | |
#pragma code high_vector=0x08 | |
void interrupt_at_high_vector(void) | |
{ | |
_asm GOTO high_isr _endasm | |
} | |
#pragma code /* return to the default code section */ | |
#pragma interrupt high_isr | |
void high_isr (void) | |
{ | |
if(PIR1bits.RC1IF==1) //Was it the Serial recieve interupt | |
{ | |
receiveCharacter = RCREG; //Get the byte | |
PIR1bits.RCIF=0; //clear the flag | |
if(receiveCharacter=='p'){ //This is so we can pause by remote&DBC | |
if(pause==0) //if the serial byte was pause hold here till resume is sent | |
{ | |
while(RCREG!='a'){ //Hold in pause unless RCREG=='a' the resume key/button , | |
if(RCREG==0x11){setSpeed();} //allow setting speed while paused | |
if(RCREG==0x12){setdelay();} //allow setting delay while paused | |
mLED_1_Toggle(); //induce joy | |
} | |
} | |
else pause=0; //if the serial byte was start , pause=0 | |
receiveCharacter =0; //Clear receiveCharacter if we did stuff. | |
} | |
}//end serial interupt | |
if(INTCONbits.INT0IF==1) //int0 Start / Pause sw1 | |
{ | |
while(sw2!=0){largedelay();mLED_1_Toggle();} //Hold in infinite loop until sw2 is pressed induce joy so when people hit pause on accident panic is averted | |
if(pause==1) | |
{ | |
pause =0; | |
} | |
INTCONbits.INT0IF=0; | |
} | |
// high Interrupt goes here check which interrupt caused the interrupt , do stuff , clear int flag etc | |
} | |
//I didnt use this so to save space im commenting it out | |
//but it's good to have here if some one wants it | |
/* //REFEREnce DS51288a-page 27 | |
#pragma code low_vector=0x18 | |
void interrupt_at_low_vector(void) | |
{ | |
_asm GOTO low_isr _endasm | |
} | |
#pragma code // return to the default code section | |
#pragma interruptlow low_isr | |
void low_isr (void) | |
{ | |
// low Interrupt goes here check which interrupt caused the interrupt , do stuff , clear int flag etc | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment