// Generic Dobby Interface (up to 28 shaft)
// Arduino Uno has 14 digital pins (2 for computer I/O) so can control up to 12 Shafts
// Arduino Mega2560 has lots of pins - can handle up to 32 shafts
// This implementation includes a 2.5" LCD touchscreen display to control the loom without a computer (primarily for troubleshooting)
// Generic stuff for loom interface
// Setup for 28 output pins controlling shafts
// LADV is digital pin to connect foot button for loom
#define MAX_CHARS 200
char message[MAX_CHARS]="";
unsigned long ShaftQue=0; // Qued state of shafts of loom
char LastAdvState=1;
// Maps loom shaft to Arduino output pins (Mega 2560)
char PinForShaft[32]={22,23,24,25,26, 29,30,31,32,34, 36,37,38,39,40, 43,44,45,46,47, -1,-1,-1,-1}; // 32 shaft map
// there are 2 spares per driver package with 5 of 7 drivers set. if a driver blows change the above to move to another channel
#define LADV 52
char term_char='\n';
unsigned long Bits[32]={1,2,4,8,0x10,0x20,0x40,0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000,
0x10000,0x20000,0x40000,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,
0x10000000,0x20000000,0x40000000,0x80000000};
// Display/Touchscreen stuff:
#include <TouchScreen.h>
// Display overlay UNO pin usage:
// LCD Data Bit : 7 6 5 4 3 2 1 0
// Uno dig. pin : 7 6 5 4 3 2 9 8
// Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0
// Mega dig. pin: 29 28 27 26 25 24 23 22
// : PH4 PH3 PE3 PG5 PE5 PE4 PH6 PH5
#define LCD_RD A0
#define LCD_WR A1
#define LCD_RS A2
#define LCD_CS A3
#define LCD_REST A4
// Touchscreen definitions:
#define YP A3 // must be an analog pin, use "An" notation!
#define XM A2 // must be an analog pin, use "An" notation!
#define YM 9 // can be a digital pin
#define XP 8 // can be a digital pin
#define TS_THRESHOLD 10
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// Touchscreen min & max values - note this is twisted from the LCD x & axes
struct Point
{
unsigned int x;
unsigned int y;
};
struct Rect
{
unsigned int x1;
unsigned int y1;
unsigned int x2;
unsigned int y2;
};
#define MAX_BUTTONS 42
#define BUTTON_STRING_SIZE 9
#define GAP 5
Rect ButtonRect[MAX_BUTTONS]; // defines location/size of the buttons
char ButtonString[MAX_BUTTONS][BUTTON_STRING_SIZE]; // Strings used within buttons
char ButtonState[MAX_BUTTONS]; // State of button to show
char ButtonStateLast[MAX_BUTTONS]; // Last button state drawn
#define CHAR_WIDTH 6
#define FIRST_SHAFT 8
#define BUTTON_INACTIVE 0
#define BUTTON_BOLD 1
#define BUTTON_GREEN 2
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
// Dimentions for 2.6" display
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
// dimentions for 3.5" display
#define LCD_3p5 0
//#define LCD_WIDTH 480
//#define LCD_HEIGHT 320
#define WHITE RGB(255,255,255)
#define BLACK RGB(0,0,0)
#define RED RGB(255,0,0)
#define ORANGE RGB(255,127,0)
#define YELLOW RGB(255,255,0)
#define GREEN RGB(0,255,0)
#define BLUE RGB(0,0,255)
#define VIOLET RGB(255,0,255)
#define WR_MASK B00000010
#define RS_MASK B00000100
//typedef struct record Record;
int RGB(int r,int g,int b)
{
int rgb;
rgb=r/8;
rgb=rgb<<5;
rgb|=(g/8);
rgb=rgb<<6;
rgb|=b/8;
return rgb;
// return r << 16 | g << 8 | b;
}
// Generic stuff for loom interface
void SendAdvance(char state)
{ // Loom independent command to send "advance" to the host
Serial.write("Advance\n"); // Generic command to advance
}
void Advance(char state)
{
if(state==0)
{ // button is down
SetShafts(ShaftQue); // shafts are active while button is pressed
ButtonState[0]=BUTTON_GREEN; // Set Advance indicator
SetShaftButtons(ShaftQue,BUTTON_GREEN); // Set active buttons
DrawButtons(); // show display
delay(500); // delay to avoid button bounce, etc
}
else
{ // button released
SendAdvance(LastAdvState); // tell host to advance
SetShafts(0); // button release, release shafts
ButtonState[0]=BUTTON_INACTIVE; // clear Advance indicator
SetShaftButtons(ShaftQue,BUTTON_BOLD); // button indicators back to que
DrawButtons(); // show buttons
}
}
void SimulateLoom()
{
char inChar;
char command[MAX_CHARS]="";
int serial_chars=0;
if((Serial.available()>0))
{ // Someone talking to us, get command
inChar=-1;
while((Serial.available()>0)&&(serial_chars<MAX_CHARS)&&(inChar!=term_char))
{
inChar=char(Serial.read());
command[serial_chars]=inChar;
serial_chars++;
command[serial_chars]=0;
if((inChar!=term_char)&&(Serial.available()==0)) // delay unless done
delay(5);
}
// Got a command, digest it
//sprintf(message,"Command: %s - LT=%d\n",command,LoomType);
//Serial.write(message);
GenericReceiver(command); // Pass command string to generic loom interface
DrawButtons(); // update the display with the host settings
}
if(digitalRead(LADV)!=LastAdvState)
{ // State change on Last Advance Button
LastAdvState^=1; // toggle to new state
Advance(LastAdvState); // activate loom, etc
delay(50); // wait a tick do de-bounce the switch
}
}
unsigned long get_shafts(char* command) // extract desired shafts from host transmission
{
int chars=strlen(command);
int i=0;
unsigned long shafts=0;
char shaft=0,digit=0, character;
while(i<=chars)
{
character=command[i];
if((character==',')||(i==chars))
{ // have field seperator or end of string, not shaft desired
if((shaft>0)&&(shaft<=32))
{ // 'shafts' notes this shaft is required
shafts|=Bits[shaft-1];
shaft=0;
}
}
else if(('0'<=character)&&(character<='9'))
{ // have digit
character&=0x0f; // reduce to decimal
shaft=shaft*10+character;
}
else if((character==' ')||(character=='\n')); // ignore spaces/returns
else
{
Serial.println("Invalid Character detected in command:"); // debug display of command extracted
Serial.println(command); // debug display of command extracted
i=chars; // quit, got crap
}
i++;
}
return shafts;
}
void SetShaftButtons (unsigned long shafts, char state) // Set indicator buttons as indicated
{
unsigned long mask=1;
int i;
while(i<32)
{
if(shafts&mask) ButtonState[FIRST_SHAFT+i]=state;
else ButtonState[FIRST_SHAFT+i]=BUTTON_INACTIVE;
mask=mask<<1;
i++;
}
}
void SetShafts (unsigned long shafts) // set output bits to state desired
{
unsigned long mask=1;
int shaft, pin;
while(shaft<32)
{
pin=PinForShaft[shaft];
if(shafts&mask) digitalWrite(pin,1);
else digitalWrite(pin,0);
mask=mask<<1;
shaft++;
}
}
void GenericReceiver(char *command)
{
//unsigned long temp;
//unsigned char chunk;
if(command[0]=='?')
Serial.write("Generic Dobby Interface - 20 Shaft Macomber Air Assist\n");
else if(('0'<=command[0])&&(command[0]<='9')) // go number, should be shafts
{
ShaftQue=get_shafts(command); // host request for shafts to set
SetShaftButtons(ShaftQue, BUTTON_BOLD);
}
}
void send_advance() // Touchscreen response function for "ADVANCE" command
{
SendAdvance(1);
}
/////////////////////////// generic functions for LCD display & touchscreen /////////////////
char check_touchscreen(TSPoint *p )
{
char state=0;
unsigned long temp;
TSPoint tp= ts.getPoint(),tp2= ts.getPoint();
int i=0, i2=0;
int TS_MINX, TS_MAXX, TS_MINY,TS_MAXY;
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if(tp.z>TS_THRESHOLD)
{
if(LCD_3p5)
{ // Large display
TS_MINX=112; TS_MAXX=860; TS_MINY=70;TS_MAXY=780;
tp.x=1024-tp.x;
tp.y=1024-tp.y;
tp.x=tp.x-TS_MINX; if(tp.x<0)tp.x=0;
tp.y=tp.y-TS_MINY; if(tp.y<0)tp.y=0;
}
else
{ // 2.6 inch display
//TS_MINX=190; TS_MAXX=730; TS_MINY=190; TS_MAXY=730;
TS_MINX=150; TS_MAXX=850; TS_MINY=150; TS_MAXY=950;
tp.x=tp.x-TS_MINX; if(tp.x<0)tp.x=0;
//tp.y=tp.y-TS_MINY; if(tp.y<0)tp.y=0;
tp.y=TS_MAXY-tp.y; if(tp.y<0)tp.y=0;
TS_MAXX-=TS_MINX; TS_MAXY-=TS_MINY;
}
temp=tp.y;temp*=LCD_WIDTH;temp/=TS_MAXY;
if(temp>LCD_WIDTH)temp=LCD_WIDTH;
(*p).x=int(temp);
temp=tp.x;temp*=LCD_HEIGHT;temp/=TS_MAXX;
if(temp>=LCD_HEIGHT)temp=LCD_HEIGHT;
(*p).y=int(temp);
//(*p).x=tp.y;
//(*p).y=tp.x;
(*p).z=tp.z;
//sprintf(message,"Touched, @ (%d,%d, %d :: pxls %d, %d)\n",tp2.x,tp2.y,tp2.z,(*p).x,(*p).y);
//Serial.write(message);
state=1; // got something
while(i<MAX_BUTTONS)
{
if(point_within((*p),ButtonRect[i]))
{
//if(i<FIRST_SHAFT)
// sprintf(message,"Touched button %d {x,y: %d<%d<%d , %d<%d<%d)\n",i, ButtonRect[i].x1,(*p).x,ButtonRect[i].x2, ButtonRect[i].y1,(*p).y,ButtonRect[i].y2);
//else
// sprintf(message,"Touched button %d (shaft %d) {x,y: %d<%d<%d , %d<%d<%d)\n",i, i-FIRST_SHAFT+1,ButtonRect[i].x1,(*p).x,ButtonRect[i].x2, ButtonRect[i].y1,(*p).y,ButtonRect[i].y2);
//Serial.write(message);
if(i==0){Advance(0);Advance(1); } // Advance
//if(i==1) // buttons deleted
//if(i==2)
if(i==3) // SET ALL
{ShaftQue=0xffffffff;SetShaftButtons(ShaftQue,BUTTON_GREEN); SetShafts(ShaftQue); DrawButtons(); } // Set the shaft controls
if(i==4) // CLEAR ALL
{
i2=0;
while(i2<MAX_BUTTONS)ButtonStateLast[i2++]=BUTTON_BOLD;
LCD_Clear(WHITE); // Clear screen to get rid of crap that might have accumulated
ShaftQue=0;
SetShafts(ShaftQue);
SetShaftButtons(ShaftQue,BUTTON_INACTIVE);
DrawButtons();
}
// Have shaft command, toggle state of shaft
i2=i-FIRST_SHAFT;
if((0<=i2)&&(i2<32))
{ // have touch on a shaft control button,
temp=Bits[i2];
ShaftQue^=temp; // Update the list
SetShafts(ShaftQue);
SetShaftButtons(ShaftQue,BUTTON_GREEN);
DrawButtons();
}
}
i++;
}
}
return state;
}
char point_within(struct Point point, struct Rect rect) // within display rectangle
{
char within=0;
if((rect.x1<=point.x)&&(point.x<=rect.x2)&&(rect.y1<=point.y)&&(point.y<=rect.y2))within=1;
return within;
}
char point_within(struct TSPoint point, struct Rect rect) // within touchscreen rectangle
{
char within=0;
if((rect.x1<=point.x)&&(point.x<=rect.x2)&&(rect.y1<=point.y)&&(point.y<=rect.y2))within=1;
//sprintf(message,"p= %d,%d r=%d,%d to %d,%d, within = %d\n",point.x,point.y, rect.x1,rect.y1, rect.x2,rect.y2, within);
//Serial.write(message);
return within;
}
void Lcd_Writ_Bus(unsigned char d) // Send data to LCD display
{
PORTH &= ~(0x78);
PORTH |= ((d&0xC0) >> 3) | ((d&0x3) << 5);
PORTE &= ~(0x38);
PORTE |= ((d & 0xC) << 2) | ((d & 0x20) >> 2);
PORTG &= ~(0x20);
PORTG |= (d & 0x10) << 1;
PORTF &= ~WR_MASK;
PORTF |= WR_MASK;
}
void Lcd_Write_Com(unsigned char VH)
{
PORTF &= ~RS_MASK;//RS=0
Lcd_Writ_Bus(VH);
}
void Lcd_Write_Data(unsigned char VH)
{
PORTF |= RS_MASK;//LCD_RS=1;
Lcd_Writ_Bus(VH);
}
void Lcd_Write_Com_Data(unsigned char com,unsigned char dat)
{
Lcd_Write_Com(com);
Lcd_Write_Data(dat);
}
void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{
Lcd_Write_Com(0x2a);
Lcd_Write_Data(x1>>8);
Lcd_Write_Data(x1);
Lcd_Write_Data(x2>>8);
Lcd_Write_Data(x2);
Lcd_Write_Com(0x2b);
Lcd_Write_Data(y1>>8);
Lcd_Write_Data(y1);
Lcd_Write_Data(y2>>8);
Lcd_Write_Data(y2);
Lcd_Write_Com(0x2c);
digitalWrite(LCD_RS,HIGH);
}
void Lcd_Init(void)
{
digitalWrite(LCD_REST,HIGH);
delay(5);
digitalWrite(LCD_REST,LOW);
delay(15);
digitalWrite(LCD_REST,HIGH);
delay(15);
digitalWrite(LCD_CS,HIGH);
digitalWrite(LCD_WR,HIGH);
digitalWrite(LCD_CS,LOW); //CS
Lcd_Write_Com(0x11);
delay(20);
Lcd_Write_Com(0xD0);
Lcd_Write_Data(0x07);
Lcd_Write_Data(0x42);
Lcd_Write_Data(0x18);
Lcd_Write_Com(0xD1);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x07);//07
Lcd_Write_Data(0x10);
Lcd_Write_Com(0xD2);
Lcd_Write_Data(0x01);
Lcd_Write_Data(0x02);
Lcd_Write_Com(0xC0);
Lcd_Write_Data(0x10);
Lcd_Write_Data(0x3B);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x02);
Lcd_Write_Data(0x11);
Lcd_Write_Com(0xC5);
Lcd_Write_Data(0x03);
Lcd_Write_Com(0x36);
Lcd_Write_Data(0x0A);
Lcd_Write_Com(0x3A);
Lcd_Write_Data(0x55);
Lcd_Write_Com(0x2A);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x01);
Lcd_Write_Data(0x3F);
Lcd_Write_Com(0x2B);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x00);
Lcd_Write_Data(0x01);
Lcd_Write_Data(0xE0);
delay(120);
Lcd_Write_Com(0x29);
Lcd_Write_Com(0x002c);
}
void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) // Draw Horizontal Line
{
unsigned int i,j;
unsigned char c1=c>>8, c2=c;
Lcd_Write_Com(0x02c); //write_memory_start
digitalWrite(LCD_RS,HIGH);
digitalWrite(LCD_CS,LOW);
l=l+x;
Address_set(x,y,l,y);
j=l*2;
for(i=1;i<=j;i++)
{
Lcd_Write_Data(c1);
Lcd_Write_Data(c2);
}
digitalWrite(LCD_CS,HIGH);
}
void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) // Draw Vertical Line
{
unsigned int i,j;
unsigned char c1=c>>8, c2=c;
Lcd_Write_Com(0x02c); //write_memory_start
digitalWrite(LCD_RS,HIGH);
digitalWrite(LCD_CS,LOW);
l=l+y;
Address_set(x,y,x,l);
j=l*2;
for(i=1;i<=j;i++)
{
Lcd_Write_Data(c1);
Lcd_Write_Data(c2);
}
digitalWrite(LCD_CS,HIGH);
}
void Rect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c) // open rectangle
{
H_line(x , y , h, c);
H_line(x , y+w, h, c);
V_line(x , y , w, c);
V_line(x+h, y , w, c);
}
void Rectf(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c) // filled rectangle
{
unsigned int i;
for(i=0;i<w;i++)
{
H_line(x , y+i, h, c);
}
}
void LCD_rect( struct Rect rect, unsigned int *data)
{
unsigned int x=0,y=0;
int d0=0, di=d0, dx=rect.x2-rect.x1;
Lcd_Write_Com(0x02c); //write_memory_start
digitalWrite(LCD_RS,HIGH);
digitalWrite(LCD_CS,LOW);
Address_set(rect.y1, rect.x1,rect.y2-1,rect.x2-1);
for(x=rect.x1;x<rect.x2;x++)
{
di=d0;
for(y=rect.y1;y<rect.y2;y++)
{
Lcd_Write_Data(data[di]>>8);
Lcd_Write_Data(data[di]);
di+=dx;
}
d0++;
}
digitalWrite(LCD_CS,HIGH);
}
////////// specific functions to display loom data on display //////////
void pointP(int button_no, unsigned int *data,struct Point point,unsigned int color)
{
int dx=ButtonRect[button_no].x2-ButtonRect[button_no].x1;
int z=point.x+point.y*dx;
data[z]=color;
}
void line(int button_no, unsigned int *data,struct Point from, struct Point to, unsigned int color)
{
struct Point point;
int dx=to.x-from.x, dy=to.y-from.y;
float fy=from.y, fdy=(float)dy/float(dx);
float fx=from.x, fdx=(float)dx/float(dy);
point.x=from.x; point.y=from.y;
if(dx>dy)
{
while(point.x<to.x)
{
pointP(button_no,data,point,color);
point.x++;
fy+=fdy;
point.y=(int)fy;
}
}
else
{
while(point.y<to.y)
{
pointP(button_no,data,point,color);
point.y++;
fx+=fdx;
point.x=(int)fx;
}
}
}
void rect(int button_no, unsigned int *data,int thickness, unsigned int color)
{
int dx=ButtonRect[button_no].x2-ButtonRect[button_no].x1;
int dy=ButtonRect[button_no].y2-ButtonRect[button_no].y1;
struct Point point1, point2;
int i=0;
point1.x=0; point2.x=dx;
point1.y=point2.y=0;
while(i<thickness)
{
line(button_no,data,point1,point2,color);
point1.y=point2.y=i++;
}
point1.y=point2.y=dy-thickness+1;
i=1;
while(i<thickness)
{
line(button_no,data,point1,point2,color);
point1.y++;point2.y++;
i++;
}
point1.x=point2.x=0;
point1.y=0; point2.y=dy;
i=0;
while(i<thickness)
{
line(button_no,data,point1,point2,color);
point1.x=point2.x=i++;
}
point1.x=point2.x=dx-thickness+1;
i=1;
while(i<thickness)
{
line(button_no,data,point1,point2,color);
point1.x++;point2.x++;
i++;
}
}
char Character(char input_char,unsigned char *bit_map)
{
char caps[]=" ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned char CapMap[27][CHAR_WIDTH]={{0,0,0,0,0,0},{0x3e,0x50,0x90,0x50,0x3e,0},{0xfe,0x92,0x92,0x92,0x6c,0}, // - A B
{0x7c,0x82,0x82,0x82,0x44,0},{0xfe,0x82,0x82,0x82,0x7c,0},{0xfe,0x92,0x92,0x92,0x82,0},{0xfe,0x90,0x90,0x90,0x80,0}, //C D E F
{0x7c,0x82,0x82,0x92,0x5c,0},{0xfe,0x10,0x10,0x10,0xfe,0},{0x00,0x82,0xfe,0x82,0x00,0},{0x84,0x82,0x82,0xfc,0x80,0}, //G H I J
{0xfe,0x10,0x28,0x44,0x82,0},{0xfe,0x02,0x02,0x02,0x00,0},{0xfe,0x80,0x60,0x80,0xfe,0},{0xfe,0x40,0x10,0x04,0xfe,0}, //K L M N
{0x7c,0x82,0x82,0x82,0x7c,0},{0xfe,0x90,0x90,0x90,0x60,0},{0x7c,0x82,0x8a,0x86,0x7e,0},{0xfe,0x90,0x98,0x84,0x62,0}, //O P Q R
{0x64,0x92,0x92,0x92,0x4c,0},{0x80,0x80,0xfe,0x80,0x80,0},{0xfc,0x02,0x02,0x02,0xfc,0},{0xf0,0x0c,0x02,0x0c,0xf0,0}, //S T U V
{0xfc,0x02,0x0c,0x02,0xfc,0},{0xc6,0x28,0x10,0x28,0xc6,0},{0xc0,0x20,0x1e,0x20,0xc0,0},{0x86,0x8a,0x92,0xa2,0xc2,0}}; //W X Y Z
char numbers[]="0123456789";
unsigned char NumMap[10][CHAR_WIDTH]={{0x7c,0x8a,0x92,0xa2,0x7c,0},{0x00,0x42,0xfe,0x02,0x00,0}, // 0 1
{0x42,0x86,0x8a,0x92,0x62,0},{0x82,0x92,0x92,0x92,0x6c,0},{0xf0,0x10,0x10,0xfe,0x10,0},{0xf4,0x92,0x92,0x92,0x8c,0}, // 2 3 4 5
{0x7c,0x92,0x92,0x92,0x8c,0},{0x80,0x80,0x86,0x98,0xe0,0},{0x6c,0x92,0x92,0x92,0x6c,0},{0x62,0x92,0x92,0x92,0x7c,0}}; // 6 7 8 9
unsigned char *pointer=CapMap[0], hit=0;
int i=1;
if(('A'<=input_char)&&(input_char<='Z'))
{
while((i<27)&&(hit==0))
{
if(input_char==caps[i]){hit=1; pointer=CapMap[i];}
i++;
}
}
else if(('0'<=input_char)&&(input_char<='9'))
{
i=0;
while((i<10)&&(hit==0))
{
if(input_char==numbers[i]){hit=1; pointer=NumMap[i];}
i++;
}
}
i=0;
while(i<CHAR_WIDTH){bit_map[i]=pointer[i]; i++;} // store the result
return hit;
}
void fill_char_col(int button_no, unsigned int *data, int x, unsigned char column, int scale, unsigned int color)
{
unsigned char mask=0x80;
int w,h,row=5;
struct Point point;
while(mask)
{
if(column&mask)
{
w=0;
point.x=x;
while(w<scale)
{
point.y=row;
h=0;
while(h<scale)
{
pointP(button_no,data,point,color);
h++;
point.y++;
}
w++;
point.x++;
}
}
row+=scale;
mask=mask>>1;
}
}
void fill_char(int button_no, unsigned int *data, int x, unsigned char *CharMap, int scale, unsigned int color)
{
int i=0;
while(i<CHAR_WIDTH-1)
{
fill_char_col(button_no,data,x,CharMap[i],scale,color);
x+=scale;
i++;
}
}
void string(int button_no, unsigned int *data,int scale, unsigned int color)
{
int x,i=0, chars=strlen(ButtonString[button_no]);
unsigned char CharMap[CHAR_WIDTH];
if(chars>0)
{
x=(ButtonRect[button_no].x2-ButtonRect[button_no].x1)/2-(chars*CHAR_WIDTH*scale)/2; // starting position for first char
i=0;
while(i<chars)
{
Character(ButtonString[button_no][i],CharMap);
fill_char(button_no,data,x,CharMap,scale,color);
x+=CHAR_WIDTH*scale;
i++;
}
}
}
void DrawButton(int button_no)
{
int dx=ButtonRect[button_no].x2-ButtonRect[button_no].x1;
int dy=ButtonRect[button_no].y2-ButtonRect[button_no].y1;
int i=0, s=dx*dy, border=2, chars=0;
unsigned int data[s];
unsigned int brush_color=WHITE,pen_color=BLACK,font_color=BLACK;
struct Point point1,point2;
char shaft,pin;
if((dx>0)&&(dy>0)&&(ButtonState[button_no]!=ButtonStateLast[button_no]))
{
//sprintf(message,"button %d: %d,%d, %d,%d \n",button_no,ButtonRect[button_no].x1,ButtonRect[button_no].y1,ButtonRect[button_no].x2,ButtonRect[button_no].y2);
//Serial.write(message);
//delay(100);
if(ButtonState[button_no]==BUTTON_GREEN){brush_color=GREEN; border=5;}
else if(ButtonState[button_no]==BUTTON_BOLD){brush_color=YELLOW;border=6;}
while(i<s)data[i++]=brush_color; // Setup the button background
rect(button_no,data,border,pen_color); // Overlay the border
string(button_no,data,2,font_color); // Overlay the string key cap
LCD_rect(ButtonRect[button_no],data);
ButtonStateLast[button_no]=ButtonState[button_no];
}
}
void DrawButtons()
{
int i=0;
while(i<MAX_BUTTONS)DrawButton(i++);
}
void LCD_Clear(unsigned int c)
{
unsigned int i=0,m=0;
unsigned char c1=c>>8, c2=c;
Address_set(0,0,LCD_HEIGHT,LCD_WIDTH);
digitalWrite(LCD_CS,LOW);
for(i=0;i<LCD_HEIGHT;i++)
{
for(m=0;m<LCD_WIDTH;m++)
{
Lcd_Write_Data(c1);
Lcd_Write_Data(c2);
}
}
digitalWrite(LCD_CS,HIGH);
}
unsigned long ShaftsFromButtons()
{
unsigned long shafts=0, mask=1;
int i=0;
while(i<32)
{
if(ButtonState[FIRST_SHAFT+i]!=BUTTON_INACTIVE)shafts|=mask;
mask=mask<<1;
i++;
}
}
void setup()
{
int i;
// Generic loom functions initialization:
Serial.begin(9600); // Setup serial channel to host
Serial.write("GENERIC LOOM SIMULATOR\n");
i=0; // set all shaft controls to output mode & low
while(i<32)
{
if(PinForShaft[i]>=0)
{
pinMode(PinForShaft[i], OUTPUT);
digitalWrite(PinForShaft[i],0);
}
i++;
}
pinMode(LADV, INPUT_PULLUP);
// Display initialization
DDRH |= 0x78;
DDRE |= 0x38;
DDRG |= 0x20;
pinMode(A0,OUTPUT);
pinMode(A1,OUTPUT);
pinMode(A2,OUTPUT);
pinMode(A3,OUTPUT);
pinMode(A4,OUTPUT);
digitalWrite(A0, HIGH);
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);
digitalWrite(A4, HIGH);
Lcd_Init();
//LCD_Clear(0xf800);
// Clear all buttons
i=0;
while(i<MAX_BUTTONS)
{ // initialize all the buttons
ButtonState[i]=BUTTON_INACTIVE; // null state of button
ButtonStateLast[i]=-1; // Set to redraw buttons
ButtonRect[i].x1=ButtonRect[i].y1=ButtonRect[i].x2=ButtonRect[i].y2=0;
ButtonString[i][0]=0; // terminate the strings
i++;
}
// draw top buttons
int button_width=100, button_height=30;
int top=3,left=3, first_shaft=FIRST_SHAFT;
char text[30];
i=0;
ButtonRect[i].x1=left; ButtonRect[i].y1=top;
ButtonRect[i].x2=ButtonRect[i].x1+button_width-1; ButtonRect[i].y2=ButtonRect[i].y1+button_height-1;
ButtonState[i]=BUTTON_INACTIVE;
strcpy(ButtonString[i],"ADVANCE");
//i=1; // Button deleted
i=2; // Button deleted
i=3;
ButtonRect[i].x1=ButtonRect[1].x1+GAP*3+button_width; ButtonRect[i].y1=top; //ButtonRect[1].y2+button_height;
ButtonRect[i].x2=ButtonRect[i].x1+button_width-1; ButtonRect[i].y2=ButtonRect[i].y1+button_height-1;
ButtonState[i]=BUTTON_INACTIVE; // Set Generic as default
strcpy(ButtonString[i],"SET ALL");
i=4;
ButtonRect[i].x1=ButtonRect[3].x2+GAP; ButtonRect[i].y1=ButtonRect[3].y1;
ButtonRect[i].x2=ButtonRect[i].x1+button_width-1; ButtonRect[i].y2=ButtonRect[i].y1+button_height-1;
ButtonState[i]=BUTTON_INACTIVE;
strcpy(ButtonString[i],"CLR ALL");
// Draw the shaft buttons
i=0;
int col, gap=5,row=ButtonRect[1].y2+button_height+gap;
int ii;
button_height=40; button_width=50; left=gap*3;
while(i<20)
{ // fill first column of each row, will be used for other columns next
ii=0;
col=left;
while(ii<5)
{
ButtonRect[first_shaft+i].x1=col; ButtonRect[first_shaft+i].y1=row;
ButtonRect[first_shaft+i].x2=ButtonRect[first_shaft+i].x1+button_width-1;
ButtonRect[first_shaft+i].y2=ButtonRect[first_shaft+i].y1+button_height-1;
sprintf(ButtonString[first_shaft+i],"%d",i+1);
col=ButtonRect[first_shaft+i].x2+gap;
i++; ii++;
}
row+=button_height+gap;
}
}
void loop()
{
TSPoint p; // touch point on touch screen
int i=0;
LCD_Clear(WHITE); // white
DrawButtons(); // Update the button states
while(i<1000)
{
SimulateLoom(); // Handles commands to/from host computer to/from loom
if(check_touchscreen(&p))
{
DrawButtons(); // Update the button states
delay(250); // wait a tick
}
}
}