La mia piccola fusione fredda privata

Sperimentando la fusione fredda

Il contatore Geiger : lcd_text.c

Posted Sunday, April 19th, 2015

/* LCD.c
x LCD basati su HD44870

*/

#include “GenericTypeDefs.h”
#include “Compiler.h”
#include “hardwareprofile.h”        //
#include “contatoregeiger.h”
#include <stdlib.h>
#include <timer.h>
#include <ctype.h>
#include <libpic30.h>
#include “lcd.h”

#define LCD_MAX_COLS 16
#define LCD_MAX_ROWS 2

void subLCDInit(void);

void subLCDget(void);

void SetBeep(void);

#pragma udata

BYTE LCDCols;
BYTE LCDRows;
BYTE LCDX;
BYTE LCDY;
BYTE LuceLCD;                    // mirrored in EEPROM
BYTE ContrLCD;
BYTE StatoLCD;                    // usato per indicare se il cursore è attivo (b0);
BYTE BeepFreq;
BYTE TimerBuzz;

BYTE FLAGS_ESC;                    // per sequenze ESCAPE: 0=SetLuce, 1=SetContr, 2=SetFreq; 3=SetLed; 4&5=SetXY (1&2); 6=SetKClick; 7=invert_bitmap
BYTE FLAGS;

extern WORD I2CAddr;
BYTE I2CData;
BYTE I2CCnt;
BYTE I2CCntB;

BYTE lcd_temp0;            // usato dentro LCDOutCmd da 6963, in GetCharDef da KS0108
BYTE lcd_temp1;            // temporanea, usata da LCD
BYTE lcd_temp2;
BYTE lcd_temp3;
BYTE LCDtmpBuf[40];                    // temp per scroll display (almeno 40 BYTE), BANCO 1

//BYTE *iconptr;                        //    temp. per icone/bigchar LCD
WORD iconptr;                        //    temp. per icone/bigchar LCD

#define LCD_DELAY { Nop();     Nop();     Nop();    ClrWdt(); Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    }
//#define LCD_DELAY Delay_uS(1);

// ———————————————————————

//lang_1:                // italiano (in caso si volessero + lingue…)

const char CopyrDate[32] = {“12/03/12 – S/N 0001n” };
//    messg “Numero di serie: SERNUM”

static const char Copyright[32] = { ‘P’,'I’,'C’,'B’,'e’,'l’,'l’,’ ‘,’f',’w',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,0 };
//    dt    ”ADPM Synthesis – Terminale grafico USB “
//    dt  VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′, ‘ ‘
//    dt “08/04/05″,0
const char *CopyrString=Copyright;
static const char *Copyr1= { “(C) Cyberdyne 2009-2012; ADPM Synthesis 1999-2008 – G.Darn” };

const char String1_l1[32] = { “Cyberdyne” /*”ADPM Synthesis”*/  /*    ” K-tronic sas” */ };
const char String2_l1[] = {    ’ ‘,’P',’I',’C',’B',’e',’l',’l',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,’ ‘,0 };
//static const char String2_l1[] = {    ’S',’k',’y',’N',’E',’T',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,’ ‘,0 };
const char String3_l1[2] =
{ ‘_’,0    };            // icona splash-screen ?

const BYTE LUTLuce[16]= { 0,1,2,3, 4,5,7,8, 10,12,14,18, 20,24,28,32 };

void aggLuceContrasto(void) {
WORD w;

//    PR2=BeepFreq;
w = LUTLuce[LuceLCD & 0xf];
w *= 1000;        // quasi-100%, tanto per
// …moltiplico per Luce (ossia il DutyCycle voluto)…
// divido per 32 (v. tab luce)…
//    SetDCOC1PWM(w /* /32 */,BeepFreq);            // FINIRE
// …il risultato nel timer

OC4R=w;
//    SetDCOC2PWM(ContrLCD * 4,BeepFreq);            // FINIRE

}

// ———————————————————————

void print_init(void) {

LCDCls();
LCDX= (LCD_MAX_COLS-14)/2;                // “skynet/picbell vx.xx”: 16 char
LCDXY(0);                        // X,Y=[2,1]

#if LCD_MAX_ROWS>1
LCDWrite(String2_l1);
LCDX=(LCD_MAX_COLS-10)/2;                // “cyberdyne”: 10 char

LCDXY(1);                        // X,Y=[3,2]

LCDWrite(String1_l1);

if(!sw1) {
LCDPrintLF();
#if LCD_MAX_ROWS>2
LCDPrintHex(LuceLCD);
LCDPrintHex(ContrLCD);
LCDPrintLF();
#else
LCDPrintHex(LuceLCD);
#endif
return;
}

//    LCDWrite(String3_l1);
#else
LCDWrite(String2_l1);
#endif

}

// ———————————————————————
void LCDPutChar(BYTE ch) {
static BYTE parm1,parm2,nparms;

if(FLAGS & (1 << IN_ESCAPE_CHAR)) {

if(FLAGS_ESC & 1) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
EEscrivi_(&LuceLCD,ch-1);                    // 1..16
aggLuceContrasto();
return;
}

if(FLAGS_ESC & 2) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
EEscrivi_(&ContrLCD,ch-1);                    // 1..16
aggLuceContrasto();
return;
}
if(FLAGS_ESC & 4) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
// minimo 32 (v. PWM luce) (circa 10KHz per buzzer)
BeepFreq= ch < 32 ? 32 : ch;
aggLuceContrasto();
return;
}
if(FLAGS_ESC & 8) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
//            LATE = ch & 0xf;        // OCCHIO!
return;
}
if(FLAGS_ESC & 0×10) {
// http://ascii-table.com/ansi-escape-sequences-vt-100.php
if(isdigit(ch)) {        // set xy ESC [ x;y f/H
if(!nparms)
parm1=ch;            //NO! usare atoi... su + char...
if(nparms==1)
parm2=ch;            //NO! usare atoi... su + char...
nparms++;
}
else {
if(ch=='m') {
//                    if(nparms)
//                        bigFont=parm1 & 1;
}
if(ch=='f' || ch=='H') {
if(nparms>1) {
LCDY = parm1;
LCDX = parm2;
LCDXY_();
}
}
if(ch=='j') {
if(nparms && parm1=='2' /*sistemare!*/)
LCDCls();
}
FLAGS_ESC=0;
nparms=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
}

return;
}
if(FLAGS_ESC & 0x20) {
if(ch & 1)
FLAGS &= ~(1 << NOKCLICK);
else
FLAGS |= (1 << NOKCLICK);
return;
}

switch(ch) {
case 17:                        // v. sopra
FLAGS_ESC |= 1;
break;
case 18:                        // un po' a caso...
FLAGS_ESC |= 2;
break;
case 7:                        // come "BEL"
FLAGS_ESC |= 4;
break;
case 19:                        // v. sopra
FLAGS_ESC |= 8;
break;
case 91:                        // vagamente ANSI... (VT100 dice: "ESC [ ROW ; COLUMN f" , e simili...
FLAGS_ESC |= 0x10;
nparms=0;
break;
}

if(!FLAGS_ESC)        // se non e' stato trovato nessun char. accettabile, tolgo QUI ESC!
FLAGS &= ~(1 << IN_ESCAPE_CHAR);

return;
}

if(ch >= ' ') {

if(ch & 0x80)            // i caratteri >=0x80 sono usati per i char user-defined...
ch &= 0x7f;            // ...banalmente, se solo testo, li riporto al valore in LCD

LCDOutData(ch);

LCDX++;
if(LCDX >= LCDCols)
goto LCDPrintLF;
/*
if(LCDRows == 1) {
if(LCDX == 8)
LCDXY_();
}        per 1-riga, v. anche LCDXY e frequanzimetro
*/
}

else {

switch(ch) {
case 2:
StatoLCD |= 1;
LCDCursor(3);                // STX=cursor On
break;

case 3:
StatoLCD &= 0xfe;        // ETX=cursor Off
LCDCursor(0);
break;

case 7:
//  call StdBeep                        ; resa ASINCRONA (per velocita' I2C e anche SER)!
SetBeep();
break;

case 9:
LCDtab:
LCDX++;

LCDOutBlankRaw();        // meglio non LCDPutBlank, per lo stack!
// così però non gestisce l'a-capo...

if(LCDX & 7)
goto LCDtab;
break;

case 11:
LCDScrollDown();
break;

case 12:                    // FF = scroll up
LCDScrollUp();
break;

case 10:                // LF
LCDPrintLF:
LCDX=0;
LCDY++;
// METTERE un FLAG per disattivare scroll automatico (CHR$13) su ultima riga, per sfruttarla meglio??
LCDScroll();            // scroll SE necessario
break;

case 13:                // CR
LCDX=0;
LCDXY_();
break;

case 14:            // shift-in (cursor left)
LCDOutCmd(16);
break;
case 15:            // shift-out (cursor right)
LCDOutCmd(20);
break;

case 8:                    //; BS
if(LCDX) {                // solo se X>0...

LCDX--;

LCDOutCmd(16);
LCDOutBlankRaw();
LCDOutCmd(16);
}
break;

case 17:            // DC1..2 usati per Luce LCD
LuceLCD=15;
LCDPC_NoPrint_17_:
//            EEcopiaAEEPROM(&LuceLCD);
aggLuceContrasto();            // occhio allo stack...!
break;

case 18:
LuceLCD=0;
goto LCDPC_NoPrint_17_;
break;

case 19:                    // DC3..4 usati per Led on/off
mLED_1=1;
//            LED1_IO=1;
break;

case 20:
mLED_1=0;
break;

case 24:                    // CAN (opp. FormFeed ?) = CLS
LCDCls();
break;

case 27:                    // ESC (comandi ausiliari)
FLAGS |= (1 << IN_ESCAPE_CHAR);
break;

default:
// LCDPut1:            eliminato, eqv. a return
break;

}
}

}

// ---------------------------------------------------------------------

void LCDXY_(void) {
BYTE i,lcd_temp2;

lcd_temp2=0;

switch(LCDRows) {
case 1:
if(LCDRows == 1 && LCDX >= 8) {            // patch x 1 riga... (v. anche PutChar)
LCDOutCmd(0xc0 | (LCDX & 7));
return;
}
else {
LCDXY1:
i=LCDX & 0x7f;
i+=lcd_temp2;
LCDOutCmd(i | 0x80);
}

if(LCDX & 0x80) {
LCDX &= 0x7f;
LCDX-=LCDCols;
}

break;

case 2:
LCDXY2:
lcd_temp2=(LCDY & 1) * 0x40;
goto LCDXY1;
break;

case 4:
if(LCDCols < 40) {        // se e' 4x40 (M4024) va bene cosi' (hanno 2 ENABLE)...
if(LCDY >= 2) {            // ...altrimenti (4x20), se la riga e' 2 opp. 3...
LCDX+=LCDCols;        // ...aggiungo a X la larghezza (16 opp. 20)
LCDX |= 0x80;             //e me lo segno per poi ri-toglierla!
}
}
goto LCDXY2;
break;

default:                                // NON DEVE succedere!
break;

}
}

// ---------------------------------------------------------------------

void subLCDInit(void) {

LCDOutPort4Bit(0x3);          // init 1st        4 bit!
Delay_mS(5);                                // >4.1mS
LCDOutPort4Bit(0x3);         // init 2nd
Delay_mS(1);                                // >100uS
LCDOutPort4Bit(0x3);          // init 3rd
Delay_mS(1);                                // >39uS
LCDOutPort4Bit(0x2);          //
Delay_mS(1);                                //
LCDOutCmd(0b00101000);                  // function Set 0010NF**            4bit!
LCDOutCmd(0b00001100);      // display ON/OFF = 00001DCB, Display ON,Cursor&Blink OFF
// entry Mode Set = 000001IS, increment & shift off
LCDOutCmd(0b00000110);                 // cursore, blink e ON/OFF
}

const BYTE LCDUserDefChar[7][8]={
//    { 0b00000110,0b00001001,0b00011100,0b00001000,0b00011100,0b00001001,0b00000110,0b00000000    },        // EURO no qua
{ 0b00000000,0b00000000,0b00000001,0b00000011,0b00000111,0b00001111,0b00011111,0b00000000 }, //1=triang. dx (v. pag 77 rivista)
{ 0b00000100,0b00001110,0b00001110,0b00011111,0b00000000,0b00000000,0b00000000,0b00000000 }, //2=allarme
{ 0b00000000,0b00000000,0b00000011,0b00000111,0b00001111,0b00000111,0b00000011,0b00000000    }, //3=PC/232 conn.
{ 0b00000000,0b00000000,0b00011011,0b00010010,0b00011010,0b00001010,0b00011011,0b00000000    }, //4=SD card
{ 0b00000000,0b00000100,0b00001110,0b00001110,0b00001110,0b00001110,0b00001110,0b00000000 }, //5=batt. piena
{ 0b00000000,0b00000100,0b00001010,0b00001010,0b00001010,0b00001010,0b00001110,0b00000000 }, //6=batt. vuota
{ 0b00000000,0b00001010,0b00011011,0b00011111,0b00000100,0b00001110,0b00011111,0b00000000 }, //7=radioactive :)
//purtroppo ce ne sono solo 8!
};

void subLCDdefChar(void) {
BYTE x,y;

LCDOutCmd(0×48);            // definisco char user-def partendo da 1 (non 0!)
for(y=0; y<7; y++) {    // parametrizzare!!!
for(x=0; x<8; x++) {
LCDOutData(LCDUserDefChar[y][x]);
}
}

}

BYTE LCDInit(void) {

LCDY=0;
Delay_mS(15);                // 15mS
subLCDInit();

subLCDdefChar();

#if !defined(__PIC24FJ128GA106__) && !defined(__PIC24FJ256GA106__)
//    OpenOC1(OC_IDLE_CON & OC_TIMER4_SRC /* & CMP_FAULT2_IN_DISABLE */ /* & OC_FAULT1_IN_DISABLE */ & OC_PWM_FAULT_CLEAR & OC_TRIG_CLEAR_SYNC & OC_CONTINUE_PULSE,
//        OC_FAULT_MODE_PWM_CYCLE & OC_PWM_FAULT_OUT_HIGH & OC_FAULT_PIN_UNCHANGE & OC_OUT_NOT_INVERT & OC_CASCADE_DISABLE /* & OC_SYNC_ENABLE */ & OC_UNTRIGGER_TIMER & OC_DIRN_TRIS & OC_SYNC_TRIG_IN_DISABLE,
//        0,0);
//    OpenOC2(OC_IDLE_CON & OC_TIMER4_SRC /* & CMP_FAULT2_IN_DISABLE */ /* & OC_FAULT1_IN_DISABLE */ & OC_PWM_FAULT_CLEAR & OC_TRIG_CLEAR_SYNC & OC_CONTINUE_PULSE,
//        OC_FAULT_MODE_PWM_CYCLE & OC_PWM_FAULT_OUT_HIGH & OC_FAULT_PIN_UNCHANGE & OC_OUT_NOT_INVERT & OC_CASCADE_DISABLE /* & OC_SYNC_ENABLE */ & OC_UNTRIGGER_TIMER & OC_DIRN_TRIS & OC_SYNC_TRIG_IN_DISABLE,
//        0,0);
#else

// OCCHIO CHE SU GA questa sopra non funziona!
// sembra mappare erroneamente sulle funzioni “_GB” che poi non vanno. usare accesso ai registri diretti
#endif

/* Reset PWM */
OC4CON1 = 0×0000;
OC4CON2 = 0×0000;

/* set PWM duty cycle to 50% */
OC4R    = 16384 /* basato su SysClock => 500Hz (16MHz / 32768) */; //PWM_PERIOD >> 1; /* set the duty cycle tp 50% */
OC4RS   = 32768 /* se uso Timer come Src SEMBRA NON FARE NULLA… qua boh! */;  //PWM_PERIOD – 1;  /* set the period */

/* configure PWM */
OC4CON2 = 0x001f;   /* 0x001F = Sync with This OC module                               */
OC4CON1 = 0x1c00 /* 0×0400 => src=Timer3 */;  /* 0x1C08 = Clock source Fcyc, trigger mode 1, Mode 0 (disable OC1) */

/* enable the PWM */
OC4CON1 |= 0×0006;   /* Mode 6, Edge-aligned PWM Mode */

//v. anche PPS

LuceLCD=8;
ContrLCD=12;

LCDRows=LCD_MAX_ROWS;            // PARAMETRIZZARE (da FLASH?)
//            cp  3
//            jp m,LCDInit2

//            movlw 2
//            movwf LCDY
//            call subLCDInit

LCDCols=LCD_MAX_COLS;            // PARAMETRIZZARE (da FLASH?)

LCDCls();

return 1;
}
// CONTINUA

// ———————————————————————

void LCDCls(void) {

//    movfw LCDRows
//  cp  3
//            jp m,LCDCls1
//            ld  a,2
//            ld  (LCDY),a
//            dec a
//  call LCDOutPort

LCDX=0;
LCDY=0;
//    bcf  STATUS,C

LCDOutCmd(1);
// CONTINUA                        ; cls & home (comando 1)
}

// ———————————————————————

BYTE LCDOutPort(BYTE c, BYTE n) {                                                // scrivo W nel display
// dato se C=1, comando se C=0
BYTE t;

m_LCDRWBit=1;                                        // torno in lettura
m_LCDRSBit=0;                                        // preparo per leggere Flag
lcd_temp1=0;

LCD_DELAY;

#ifndef __DEBUG
while(1) {
//    clrwdt                                                                ; incorporato in LCD_DELAY
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

t=PORTB & 0×8;                                // esco se b7=0

m_LCDEnBit=0;
LCD_DELAY;

m_LCDEnBit=1;                                        // scrivo! cmq secondo nibble!
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

if(!t)                                            // esco se b7=0
break;

//    decf  lcd_temp1,f
//    bz  LCDDelay1_err
}
#endif

LCDDelay1_err:
LCDOut1:
m_LCDEnBit=0;                            // rimetto cmq a posto EN…

return LCDOutPortNoW(c,n);
}

BYTE LCDOutPortNoW(BYTE c,BYTE n) {                                    // qui per non aspettare BUSY!

if(c)
m_LCDRSBit=1;                                        // C=1, dato
else
m_LCDRSBit=0;                                        // C=0, comando
m_LCDRWBit=0;                                        // vado in scrittura
TRISB &= ~0b00001111;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n >> 4) & 0x0f);                // nibble H, shift 4 a dx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n & 0x0f) );                // nibble L, shift 0 a sx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

TRISB |= 0b00001111;
m_LCDRWBit=1;                                        // torno in lettura

m_LCDRSBit=1;

return n;
}

BYTE LCDOutPort4Bit(BYTE n) {

m_LCDRSBit=0;                                        // C=0, comando
m_LCDRWBit=0;                                        // vado in scrittura
TRISB &= ~0b00001111;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n & 0x0f) );                // nibble L, shift 0 a sx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

TRISB |= 0b00001111;
m_LCDRWBit=1;                                        // torno in lettura

return n;
}

void LCDOutBlankRaw(void) {
char c;

c=’ ‘;

LCDOutData(c);
}

// ———————————————————————
void LCDWrite(const char *p) {

while(*p)
LCDPutChar(*p++);
}

void LCDWriteN(const char *p, BYTE n) {

do {
LCDPutChar(*p++);
} while(–n);
}

// ———————————————————————

void subLCDget(void) {
BYTE *p;
BYTE i,lcd_temp1,t;

p=LCDtmpBuf;

for(i=0; i<LCDCols; i++) {

m_LCDRSBit=0;                                        // preparo per leggere Flag
m_LCDRWBit=1;                                        // vado in lettura
TRISB |= 0b00001111;

lcd_temp1=0;

while(1) {

m_LCDEnBit=1;                                        // strobe!
LCD_DELAY

t=PORTB & 0×8;                                        // esco se b7=0

m_LCDEnBit=0;
LCD_DELAY

m_LCDEnBit=1;                                        // strobe! cmq 2 nibble
LCD_DELAY

m_LCDEnBit=0;
LCD_DELAY

if(!t)                                        // esco se b7=0
break;

//    decf  lcd_temp1,f
//    bz  subLCDg3_err

}

subLCDg3_err:

m_LCDRSBit=1;                                        // dato

LCD_DELAY
m_LCDEnBit=1;                                        // leggo!
LCD_DELAY

Nop();
Nop();
t=PORTB << 4;            // nibble hi
t &= 0xf0;
*p=t;
Nop();
Nop();
Nop();

m_LCDEnBit=0;
LCD_DELAY

LCD_DELAY
m_LCDEnBit=1;                                        // leggo!
LCD_DELAY

Nop();
Nop();
t=PORTB >> 0;
t &= 0xf;
*p++ |= t;
Nop();
Nop();
Nop();

m_LCDEnBit=0;
LCD_DELAY
}

}

void LCDScroll(void) {
BYTE i,*p;
BYTE lcd_temp4;

if(LCDRows > 1) {                // se 1 riga, niente scroll!

goto skippa;     // QUA NO! e mettere ev. il flag di no scroll, v. sopra

if(LCDY == LCDRows) {

LCDScrollUp:

for(lcd_temp4=0; lcd_temp4<(LCDRows-1); lcd_temp4++) {                // riga corrente

lcd_temp4++;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga source
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

subLCDget();

lcd_temp4–;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga dest
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

p=LCDtmpBuf;
for(i=0; i<LCDCols; i++)
LCDOutData(*p++);

// se c’e’ clock attivo su prima riga, limitare lo scroll?
}

LCDY–;
LCDClearCurrentLine();
}

skippa:
LCDXY_();
}

}

void LCDScrollDown(void) {
BYTE i,*p;
BYTE lcd_temp4;

lcd_temp4=LCDRows-1;                    // riga corrente

do {

lcd_temp4–;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga source
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

subLCDget();

lcd_temp4++;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga dest
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

p=LCDtmpBuf;

for(i=0; i<LCDCols; i++)
LCDOutData(*p++);

// se c’e’ clock attivo su prima riga, limitare lo scroll?
} while(–lcd_temp4);

LCDY=0;
LCDClearCurrentLine();

LCDXY_();

}

void LCDPrintHex(BYTE w) {                    // stampa in HEX il BYTE in W
BYTE n;

n=(w >> 4) & 0xf;
if(n>=10)
n+=7;
LCDPutChar(n+’0′);
n=w & 0xf;
if(n>=10)
n+=7;
LCDPutChar(n+’0′);
LCDPutBlank();
}

void LCDPrintDec2(BYTE n) {                // stampa BYTE in W come decimale a 2 cifre (’0′ trailing)
char myBuf[4];

itoa(myBuf,n,10);        // C30 ce l’ha a cazzo!
LCDOutData(myBuf[0]);
LCDOutData(myBuf[1]);
}

void LCDClearLine(BYTE n) {                    // entra n=linea da pulire
BYTE temp;

LCDX=0;
LCDXY(n);
temp=LCDCols;
while(temp–) {
LCDOutBlankRaw();
}
LCDXY_();                    // in caso servisse, sono a inizio riga!
}

// —————————————————————————-

//         ————————————————————————-
#if PIXEL_PER_CELLA==6
BYTE drawLineaVertTable[8]= { 0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xfd,0xfc };
//    movlw 11111101b                    ; SetBit (su 6…)
#else
BYTE drawLineaVertTable[8]= { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8 };
//    movlw 11111101b                    ; SetBit (su 8…)
#endif

void drawLinea(BYTE x1,BYTE y1,BYTE x2,BYTE y2) {        // entrano coord. (lcd_temp2:lcd_temp3) (lcd_temp4:lcd_temp5)
// le X VENGONO ALTERATE!
//    alla fine si fa LCDXY per rimettere l’addr ptr a posto per il testo…
//    BYTE temp;
//    WORD bPos;
//    BYTE lcd_temp5;

}

void drawRect(BYTE x1,BYTE y1,BYTE x2,BYTE y2,BYTE w) {
// entrano coord. (lcd_temp6:lcd_temp7) (lcd_temp8:lcd_temp9); W=0 se vuoto, 1 se pieno, 2=grigio

}

void SetBeep(void) {                                    // asincrono, viene poi resettato da interrupt

//    PR2=BeepFreq;
//    CCPR1L=BeepFreq >> 1;        // /2 (duty cycle 50%)

//    SetDCOC3PWM(BeepFreq,BeepFreq>>1);
//    TRISBbits.TRISB9=0;

//    movlw  00000111b
//    movwf  T2CON
TimerBuzz=2;
}

/*
char *itoa(int i,char *buffer) {
unsigned int n;
unsigned char negate = 0;
int c = 6;

if(i < 0) {
negate=1;
n = -i;
}
else if(i == 0) {
buffer[0] = ’0′;
buffer[1] = 0;
return buffer;
}
else {
n = i;
}
buffer[c--] = 0;
do {
buffer[c--] = (n % 10) + ’0′;
n = n / 10;
} while (n);
if(negate) {
buffer[c--] = ‘-’;
}
return &buffer[c+1];
}
*/