1 /***************************************************************************
2  *   Copyright (C) 2004-2005 by Daniel Clarke                              *
3  *   daniel.jc@gmail.com						   *
4  *									   *
5  *   24-04-2007                                                            *
6  *   Modified to add pic 16f877,16f627 and 16f628 			   *
7  *   by george john george@space-kerala.org 				   *
8  *   supported by SPACE www.space-kerala.org	 			   *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  ***************************************************************************/
25 
26 
27 #include "instruction.h"
28 #include "parser.h"
29 #include "pic14.h"
30 
31 #include <QDebug>
32 
33 #include <cassert>
34 #include <iostream>
35 using namespace std;
36 QString pic_type;
37 bool LEDSegTable[][7] = {
38 { 1, 1, 1, 1, 1, 1, 0 },
39 { 0, 1, 1, 0, 0, 0, 0 }, // 1
40 { 1, 1, 0, 1, 1, 0, 1 }, // 2
41 { 1, 1, 1, 1, 0, 0, 1 }, // 3
42 { 0, 1, 1, 0 ,0, 1, 1 }, // 4
43 { 1, 0, 1, 1, 0, 1, 1 }, // 5
44 { 1, 0, 1, 1, 1, 1, 1 }, // 6
45 { 1, 1, 1, 0, 0, 0, 0 }, // 7
46 { 1, 1, 1, 1, 1, 1, 1 }, // 8
47 { 1, 1, 1, 0, 0, 1, 1 }, // 9
48 { 1, 1, 1, 0, 1, 1, 1 }, // A
49 { 0, 0, 1, 1, 1, 1, 1 }, // b
50 { 1, 0, 0, 1, 1, 1, 0 }, // C
51 { 0, 1, 1, 1, 1, 0, 1 }, // d
52 { 1, 0, 0, 1, 1, 1, 1 }, // E
53 { 1, 0, 0, 0, 1, 1, 1 }  // F
54 };
55 
56 
57 
PIC14(Microbe * master,Type type)58 PIC14::PIC14( Microbe * master, Type type )
59 {
60 	mb = master;
61 	m_pCode = nullptr;
62 	m_type = type;
63 
64 }
65 
66 
~PIC14()67 PIC14::~PIC14()
68 {
69 }
70 
toPortPin(const QString & portPinString)71 PortPin PIC14::toPortPin( const QString & portPinString )
72 {
73 	QString port,holdport;
74 	int pin = -1;
75 /*****************************modified *********************************************/
76 //inorder to support RB.3=high/1
77 
78 	if ( portPinString.length()  == 3 )
79 	{
80 		port = QString("PORT%1").arg( portPinString[1].toUpper() );
81 		pin = QString( portPinString[2] ).toInt();
82 	}
83 	// In form e.g. RB.3
84 	else if ( portPinString.length()  == 4 )//modification change ==3 to ==4
85 	{
86 		port = QString("PORT%1").arg( portPinString[1].toUpper() );
87 		pin = QString( portPinString[3] ).toInt();//modification change 2 to 3
88 	}
89 	else
90 	{
91 		int dotpos = portPinString.indexOf(".");
92 		if ( dotpos == -1 )
93 			return PortPin();
94 
95 		port = portPinString.left(dotpos);
96 //modified checking is added in the case of Register also
97 //now INTCON.GIE is high ,and INTCON.GIE=1/high works
98 		if(isValidRegister( port))
99 		{
100 
101 			RegisterBit REG(portPinString.mid(dotpos+1));
102 			pin=REG.bitPos();
103 			Register Reg(REG.registerType());
104 			holdport=Reg.name();
105 			if(holdport!=port)
106 		    	 cerr << QString(" ERROR: %1 is not a Register bit\n").arg(portPinString ).toStdString();
107 		}
108 		else
109 			pin = portPinString.mid(dotpos+1).toInt();
110 
111 
112 //***************************Modification ends********************************
113 	}
114 
115 	PortPin portPin( port, pin );
116 
117 	if ( isValidPortPin( portPin ) )
118 		return portPin;
119 //**************************Modification start ********************************
120 	else if(isValidRegister(port))
121 		return portPin;
122 //**************************Modification ends ********************************
123 	else
124 	{
125 		cerr << QString("ERROR: %1 is not a Port/Register bit\n").arg(portPinString ).toStdString();
126 		return PortPin();
127 	}
128 }
129 
130 
mergeCode(Code * code)131 void PIC14::mergeCode( Code * code )
132 {
133 	m_pCode->merge( code );
134 }
135 
136 
gprStart() const137 uchar PIC14::gprStart() const
138 {
139 	switch ( m_type )
140 	{
141 		case P16C84:
142 		case P16F84:
143 			return 0xc;
144 
145 		case P16F627:
146 		case P16F628:
147 		case P16F877:
148 			return 0x20;
149 
150 		case unknown:
151 			break;
152 	}
153 
154 	qCritical() << Q_FUNC_INFO << "Unknown PIC type = " << m_type << endl;
155 	return 0xc;
156 }
157 
158 
toType(const QString & _text)159 PIC14::Type PIC14::toType( const QString & _text )
160 {
161 	QString text = _text.toUpper().simplified().remove('P');
162 
163 	if ( text == "16C84" )
164 	{
165 		pic_type="P16C84";
166 		return P16C84;
167 	}
168 	if ( text == "16F84" )
169 	{
170 		pic_type="P16F84";
171 		return P16F84;
172 	}
173 	if ( text == "16F627" )
174 	{
175 		pic_type="P16F627";
176 		return P16F627;
177 	}
178 
179 	if ( text == "16F628" )
180 	{
181 		pic_type="P16F627";
182 		return P16F628;
183 	}
184 //modified checking of 16F877 is included
185 	if ( text == "16F877" )
186 	{
187 		pic_type="P16F877";
188 		return P16F877;
189 	}
190 
191 	cerr << QString("%1 is not a known PIC identifier\n").arg(_text).toStdString();
192 	return unknown;
193 }
194 
195 
minimalTypeString() const196 QString PIC14::minimalTypeString() const
197 {
198 	switch ( m_type )
199 	{
200 		case P16C84:
201 			return "16C84";
202 
203 		case P16F84:
204 			return "16F84";
205 
206 		case P16F627:
207 			return "16F627";
208 
209 		case P16F628:
210 			return "16F628";
211 
212 //modified checking of 16F877 is included
213 
214 		case P16F877:
215 			return "16F877";
216 
217 		case unknown:
218 			break;
219 	}
220 
221 	qCritical() << Q_FUNC_INFO << "Unknown PIC type = " << m_type << endl;
222 	return nullptr;;
223 }
224 
225 
postCompileConstruct(const QStringList & interrupts)226 void PIC14::postCompileConstruct( const QStringList &interrupts )
227 {
228 	m_pCode->append( new Instr_raw("\n\tEND\n"), Code::Subroutine );
229 
230 	if ( interrupts.isEmpty() )
231 	{
232 		// If there are no ISRs then we don't need to put in any handler code.
233 		// Instead, just insert the goto start instruction in case we need to
234 		// jump past any lookup tabes (and if there are none, then the optimizer
235 		// will remove the goto instruction).
236 		m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler);
237 		m_pCode->queueLabel( "_start", Code::LookupTable );
238 		return;
239 	}
240 
241 	/*
242 		INTCON register:
243 		7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0
244 
245 		E: enable
246 		F: flag
247 		Flag bits must be cleared manually before reactivating GIE,
248 		but we do this in each individual interrupt handler
249 	*/
250 
251 	// The bizarre dance with swap is to ensure the status bits
252 	// are preserved properly
253 	m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler);
254 
255 	m_pCode->append(new Instr_raw("ORG 0x4"), Code::InterruptHandler);
256 	// When we arrive here:
257 	// Return address on stack,
258 	// GIE flag cleared (globally interrupts disabled)
259 	// W or STATUS not preserved by processor.
260 	m_pCode->append(new Instr_movwf("W_TEMP"), Code::InterruptHandler);
261 	m_pCode->append(new Instr_swapf("STATUS",0), Code::InterruptHandler);
262 	m_pCode->append(new Instr_movwf("STATUS_TEMP"), Code::InterruptHandler);
263 
264 	QStringList::ConstIterator interruptsEnd = interrupts.end();
265 	for( QStringList::ConstIterator it = interrupts.begin(); it != interruptsEnd; ++it )
266 	{
267 		// Is the interrupt's flag bit set?
268 		m_pCode->append(new Instr_btfsc("INTCON",QString::number(interruptNameToBit((*it), true))), Code::InterruptHandler);
269 		m_pCode->append(new Instr_goto("_interrupt_" + (*it)), Code::InterruptHandler); // Yes, do its handler routine
270 		// Otherwise fall through to the next.
271 	}
272 
273 	// If there was "somehow" a suprious interrupt there isn't really
274 	// much we can do about that (??) so just fall through and hope for the worst.
275 
276 	m_pCode->queueLabel( "_interrupt_end", Code::InterruptHandler );
277 	m_pCode->append(new Instr_swapf("STATUS_TEMP",0), Code::InterruptHandler );
278 	m_pCode->append(new Instr_movwf("STATUS"), Code::InterruptHandler );
279 	m_pCode->append(new Instr_swapf("W_TEMP",1), Code::InterruptHandler );
280 	m_pCode->append(new Instr_swapf("W_TEMP",0), Code::InterruptHandler );
281 	m_pCode->append(new Instr_retfie()); // Returns and renables globally interrupts.
282 
283 	m_pCode->queueLabel( "_start", Code::LookupTable );
284 }
285 
interruptNameToBit(const QString & name,bool flag)286 int PIC14::interruptNameToBit(const QString &name, bool flag)
287 {
288 	// 7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0
289 
290 	if( name == "change" ) // RB
291 	{
292 		if(flag) return 0;
293 		else return 3;
294 	}
295 	else if( name == "timer" )
296 	{
297 		if(flag) return 2;
298 		else return 5;
299 	}
300 	else if( name == "external" )
301 	{
302 		if(flag) return 1;
303 		else return 4;
304 	}
305 
306 	return -1;
307 }
308 
309 
isValidPort(const QString & portName) const310 bool PIC14::isValidPort( const QString & portName ) const
311 {
312 
313 	if(pic_type =="P16F84"||pic_type =="P16C84"||pic_type =="P16F627"||pic_type =="P16F628")
314 		return ( portName == "PORTA" || portName == "PORTB");
315 
316 	if(pic_type=="P16F877")
317 		return ( portName == "PORTA" ||portName == "PORTB"||portName == "PORTC" ||portName == "PORTD"||portName == "PORTE");
318 
319 	return false;
320 }
321 
322 
isValidPortPin(const PortPin & portPin) const323 bool PIC14::isValidPortPin( const PortPin & portPin ) const
324 {
325 
326 	if(pic_type == "P16F84" ||pic_type =="P16C84")
327 	{
328 		if ( portPin.port() == "PORTA" )
329 			return (portPin.pin() >= 0) && (portPin.pin() <= 4);
330 
331 		if ( portPin.port() == "PORTB" )
332 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
333 	}
334 	if(pic_type == "P16F627" ||pic_type =="P16F628")
335 	{
336 		if ( portPin.port() == "PORTA" )
337 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
338 
339 		if ( portPin.port() == "PORTB" )
340 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
341 	}
342 
343 	if(pic_type=="P16F877")
344 	{
345 		if ( portPin.port() == "PORTA" )
346 			return (portPin.pin() >= 0) && (portPin.pin() <= 5);
347 
348 		if ( portPin.port() == "PORTB" )
349 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
350 		if ( portPin.port() == "PORTC" )
351 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
352 
353 		if ( portPin.port() == "PORTD" )
354 			return (portPin.pin() >= 0) && (portPin.pin() <= 7);
355 
356 		if ( portPin.port() == "PORTE" )
357 			return (portPin.pin() >= 0) && (portPin.pin() <= 2);
358 	}
359 
360 	return false;
361 }
362 
363 
isValidTris(const QString & trisName) const364 bool PIC14::isValidTris( const QString & trisName ) const
365 {
366 	if(pic_type =="P16F84"||pic_type =="P16C84"||pic_type =="P16F627"||pic_type =="P16F628")
367 		return ( trisName == "TRISA" || trisName == "TRISB");
368 
369 	if(pic_type=="P16F877")
370 		return ( trisName =="TRISA"|| trisName =="TRISB"||trisName =="TRISC"||trisName == "TRISD"||trisName == "TRISE" );
371 
372 	return false;
373 }
374 
375 //*****************Modified ****************************//
376 //New function isValiedRegister is added to check whether a register is valied or not
isValidRegister(const QString & registerName) const377 bool PIC14::isValidRegister( const QString & registerName)const
378 {
379  	if(pic_type=="P16F84"||pic_type=="P16C84")
380 		return ( registerName == "TMR0"
381 			|| registerName == "PCL"
382 			|| registerName == "STATUS"
383 			|| registerName == "FSR"
384 			|| registerName == "EEDATH"
385 			|| registerName == "EEADR"
386 			|| registerName == "PCLATH"
387 			|| registerName == "INTCON"
388 			|| registerName == "EECON1"
389 			|| registerName == "EECON2"
390 			|| registerName == "OPTION_REG");
391 
392 	if(pic_type=="P16F877")
393 		return ( registerName == "TMR0"
394 			|| registerName == "PCL"
395 			|| registerName == "STATUS"
396 			|| registerName == "FSR"
397 			|| registerName == "PCLATH"
398 			|| registerName == "INTCON"
399 			|| registerName == "PIR1"
400 			|| registerName == "PIR2"
401 			|| registerName == "TMR1L"
402 			|| registerName == "TMR1H"
403 			|| registerName == "T1CON"
404 			|| registerName == "TMR2"
405 			|| registerName == "T2CON"
406 			|| registerName == "SSPBUF"
407 			|| registerName == "SSPCON"
408 			|| registerName == "CCPR1L"
409 			|| registerName == "CCPR1H"
410 			|| registerName == "CCP1CON"
411 			|| registerName == "RCSTA"
412 			|| registerName == "TXREG"
413 			|| registerName == "RCREG"
414 			|| registerName == "CCPR2L"
415 			|| registerName == "CCPR2H"
416 			|| registerName == "CCP2CON"
417 			|| registerName == "ADRESH"
418 			|| registerName == "ADCON0" /*bank0ends*/
419 			|| registerName == "OPTION_REG"
420 			|| registerName == "PIE1"
421 			|| registerName == "PIE2"
422 			|| registerName == "PCON"
423 			|| registerName == "SSPCON2"
424 			|| registerName == "PR2"
425 			|| registerName == "SSPADD"
426 			|| registerName == "SSPSTAT"
427 			|| registerName == "TXSTA"
428 			|| registerName == "SPBRG"
429 			|| registerName == "ADRESL"
430 			|| registerName == "ADCON1" /*bank1ends*/
431 			|| registerName == "EEDATA"
432 			|| registerName == "EEADR"
433 			|| registerName == "EEDATH"
434 			|| registerName == "EEADRH" /*bank2ends*/
435 			|| registerName == "EECON1"
436 			|| registerName == "EECON2" /*bank3ends*/   );
437 
438 	if(pic_type=="P16F627"||pic_type=="P16F628")
439 		return ( registerName == "TMR0"
440 			|| registerName == "PCL"
441 			|| registerName == "STATUS"
442 			|| registerName == "FSR"
443 			|| registerName == "PCLATH"
444 			|| registerName == "INTCON"
445 			|| registerName == "PIR1"
446 			|| registerName == "TMR1L"
447 			|| registerName == "TMR1H"
448 			|| registerName == "T1CON"
449 			|| registerName == "TMR2"
450 			|| registerName == "T2CON"
451 			|| registerName == "CCPR1L"
452 			|| registerName == "CCPR1H"
453 			|| registerName == "CCP1CON"
454 			|| registerName == "RCSTA"
455 			|| registerName == "TXREG"
456 			|| registerName == "RCREG"
457 			|| registerName == "CMCON"/*bank0ends*/
458 			|| registerName == "OPTION_REG"
459 			|| registerName == "PIE1"
460 			|| registerName == "PCON"
461 			|| registerName == "PR2"
462 			|| registerName == "TXSTA"
463 			|| registerName == "SPBRG"
464 			|| registerName == "EEDATA"
465 			|| registerName == "EEADR"
466 			|| registerName == "EECON1"
467 			|| registerName == "EECON2"
468 			|| registerName == "VRCON"/*bank1ends*/ );
469 
470 	return false;
471 }
472 
473 //****************************modifications ends********************************************
474 
isValidInterrupt(const QString & interruptName) const475 bool PIC14::isValidInterrupt( const QString & interruptName ) const
476 {
477 	if(pic_type == "P16F84" ||pic_type =="P16C84"||pic_type =="P16F877"||pic_type=="P16F627"||pic_type=="P16F628")
478 		return ( interruptName == "change" ||
479 				 interruptName == "timer" ||
480 				 interruptName == "external" );
481 
482 	return false;
483 }
484 
485 
setConditionalCode(Code * ifCode,Code * elseCode)486 void PIC14::setConditionalCode( Code * ifCode, Code * elseCode )
487 {
488 	m_ifCode = ifCode;
489 	m_elseCode = elseCode;
490 }
491 
Sgoto(const QString & label)492 void PIC14::Sgoto(const QString &label)
493 {
494 	m_pCode->append( new Instr_goto(label) );
495 }
496 
Slabel(const QString & label)497 void PIC14::Slabel(const QString &label)
498 {
499 // 	std::cout << Q_FUNC_INFO << "label="<<label<<'\n';
500 	m_pCode->queueLabel( label, Code::Middle );
501 }
502 
Send()503 void PIC14::Send()
504 {
505 	m_pCode->append( new Instr_sleep() );
506 }
507 
Ssubroutine(const QString & procName,Code * subCode)508 void PIC14::Ssubroutine( const QString &procName, Code * subCode )
509 {
510 	m_pCode->queueLabel( procName, Code::Subroutine );
511 	m_pCode->merge( subCode, Code::Subroutine );
512 	m_pCode->append( new Instr_return(), Code::Subroutine );
513 }
514 
Sinterrupt(const QString & procName,Code * subCode)515 void PIC14::Sinterrupt( const QString &procName, Code * subCode )
516 {
517 	m_pCode->queueLabel( "_interrupt_" + procName, Code::Subroutine );
518 
519 	// Clear the interrupt flag for this particular interrupt source
520 	m_pCode->append( new Instr_bcf("INTCON",QString::number(interruptNameToBit(procName,true))) );
521 	m_pCode->merge( subCode, Code::Subroutine );
522 
523 	m_pCode->append( new Instr_goto("_interrupt_end"), Code::Subroutine );
524 }
525 
526 
Scall(const QString & name)527 void PIC14::Scall(const QString &name)
528 {
529 	m_pCode->append( new Instr_call(name) );
530 }
531 
532 
Ssetlh(const PortPin & portPin,bool high)533 void PIC14::Ssetlh( const PortPin & portPin, bool high)
534 {
535 	if(high)
536 		m_pCode->append( new Instr_bsf( portPin.port(),QString::number(portPin.pin()) ) );
537 	else
538 		m_pCode->append( new Instr_bcf( portPin.port(), QString::number(portPin.pin()) ) );
539 }
540 
rearrangeOpArguments(QString * val1,QString * val2,LocationType * val1Type,LocationType * val2Type)541 void PIC14::rearrangeOpArguments( QString * val1, QString * val2, LocationType * val1Type, LocationType * val2Type)
542 {
543 	if( *val2Type == work && *val1Type != work )
544 	{
545 		LocationType tempType = *val2Type;
546 		QString tempVal = *val2;
547 
548 		*val2Type = *val1Type;
549 		*val2 = *val1;
550 
551 		*val1Type = tempType;
552 		*val1 = tempVal;
553 	}
554 }
555 
add(QString val1,QString val2,LocationType val1Type,LocationType val2Type)556 void PIC14::add( QString val1, QString val2, LocationType val1Type, LocationType val2Type )
557 {
558 	rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type );
559 
560 	switch(val1Type)
561 	{
562 		case num:  m_pCode->append(new Instr_movlw( val1.toInt( nullptr, 0 ) )); break;
563 		case work: break;
564 		case var: m_pCode->append(new Instr_movf(val1,0)); break;
565 	}
566 
567 	switch(val2Type)
568 	{
569 		case num: m_pCode->append(new Instr_addlw(val2.toInt( nullptr, 0 ))); break;
570 		case work: break;
571 		case var: m_pCode->append(new Instr_addwf(val2,0)); break;
572 	}
573 }
574 
subtract(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)575 void PIC14::subtract( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type )
576 {
577 	switch(val2Type)
578 	{
579 		case num:  m_pCode->append(new Instr_movlw( val2.toInt( nullptr, 0 ) )); break;
580 		case work: break;
581 		case var: m_pCode->append(new Instr_movf(val2,0)); break;
582 	}
583 	switch(val1Type)
584 	{
585 		case num: m_pCode->append(new Instr_sublw(val1.toInt( nullptr, 0 ))); break;
586 		case work: break;
587 		case var: m_pCode->append(new Instr_subwf(val1,0)); break;
588 	}
589 }
590 
assignNum(const QString & val)591 void PIC14::assignNum(const QString & val)
592 {
593 	m_pCode->append(new Instr_movlw(val.toInt( nullptr, 0 )));
594 }
595 
assignVar(const QString & val)596 void PIC14::assignVar(const QString &val)
597 {
598 	m_pCode->append(new Instr_movf(val,0));
599 }
600 
saveToReg(const QString & dest)601 void PIC14::saveToReg(const QString &dest)
602 {
603 	m_pCode->append(new Instr_movwf(dest));
604 }
605 
saveResultToVar(const QString & var)606 void PIC14::saveResultToVar( const QString & var )
607 {
608 	m_pCode->append( new Instr_movwf( var ) );
609 }
610 
mul(QString val1,QString val2,LocationType val1Type,LocationType val2Type)611 void PIC14::mul(QString val1, QString val2, LocationType val1Type, LocationType val2Type)
612 {
613 	multiply();
614 
615 	rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type );
616 
617 	// First, set _i argument
618 	switch(val1Type)
619 	{
620 		case num: m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); break;
621 		case work: break;
622 		case var: m_pCode->append(new Instr_movf(val1,0)); break;
623 	}
624 
625 	m_pCode->append(new Instr_movwf("__i"));
626 
627 	// Then set _j argument
628 	switch(val2Type)
629 	{
630 		case num: m_pCode->append(new Instr_movlw(val2.toInt( nullptr, 0 ))); break;
631 		case work: break;
632 		case var: m_pCode->append(new Instr_movf(val2,0)); break;
633 	}
634 
635 	m_pCode->append(new Instr_movwf("__j"));
636 	m_pCode->append(new Instr_call("__picfunc_multiply"));
637 	m_pCode->append(new Instr_movf("__result",0));
638 }
639 
640 
multiply()641 void PIC14::multiply()
642 {
643 	if ( m_pCode->instruction("__picfunc_multiply") )
644 		return;
645 
646 	m_pCode->queueLabel( "__picfunc_multiply", Code::Subroutine );
647 	m_pCode->append(new Instr_clrf("__result"), Code::Subroutine ); //result+=m_pCode->appenduction("clrf __result");
648 
649 	m_pCode->queueLabel( "__picfunc_multiply_loop", Code::Subroutine );
650 	m_pCode->append(new Instr_movf("__i",0), Code::Subroutine ); //result+=m_pCode->appenduction("movf __i,0");
651 	m_pCode->append(new Instr_btfsc("__j","0"), Code::Subroutine ); //result+=m_pCode->appenduction("btfsc __j,0");
652 	m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine ); //result+=m_pCode->appenduction("addwf __result,1");
653 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C");
654 	m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("rrf __j,1");
655 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C");
656 	m_pCode->append(new Instr_rlf("__i",1), Code::Subroutine ); //result+=m_pCode->appenduction("rlf __i,1");
657 	m_pCode->append(new Instr_movf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("movf __j,1");
658 	m_pCode->append(new Instr_btfss("STATUS","Z"), Code::Subroutine ); //result+=m_pCode->appenduction("btfss STATUS,Z");
659 	m_pCode->append(new Instr_goto("__picfunc_multiply_loop"), Code::Subroutine ); //result+=m_pCode->appenduction("goto __picfunc_multiply_loop");
660 	m_pCode->append(new Instr_return(), Code::Subroutine ); //result+=m_pCode->appenduction("return");
661 }
662 
663 
div(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)664 void PIC14::div( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type)
665 {
666 	divide();
667 
668 	// NOO - "x / 2" is NOT the same as "2 / x"
669 // 	rearrangeOpArguments( val1, val2, val1Type, val2Type );
670 
671 	// First, set _i argument
672 	switch(val1Type)
673 	{
674 		case num: m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); break;
675 		case work: break;
676 		case var: m_pCode->append(new Instr_movf(val1,0)); break;
677 	}
678 
679 	m_pCode->append(new Instr_movwf("__i"));
680 
681 	// Then set _j argument
682 	switch(val2Type)
683 	{
684 		case num: m_pCode->append(new Instr_movlw(val2.toInt( nullptr, 0 ))); break;
685 		case work: break;
686 		case var: m_pCode->append(new Instr_movf(val2,0)); break;
687 	}
688 
689 	m_pCode->append(new Instr_movwf("__j"));
690 
691 	m_pCode->append(new Instr_call("__picfunc_divide"));//result+=instruction("call __picfunc_divide");
692 	m_pCode->append(new Instr_movf("__result",0));//result+=instruction("movf __result,0");
693 }
694 
divide()695 void PIC14::divide()
696 {
697 	m_pCode->queueLabel( "__picfunc_divide", Code::Subroutine );
698 	m_pCode->append(new Instr_movf("__j",1), Code::Subroutine );
699 	m_pCode->append(new Instr_btfsc("STATUS","2"), Code::Subroutine );
700 	m_pCode->append(new Instr_return(), Code::Subroutine );
701 	m_pCode->append(new Instr_clrf("__result"), Code::Subroutine );
702 	m_pCode->append(new Instr_movlw(1), Code::Subroutine );
703 	m_pCode->append(new Instr_movwf("__k"), Code::Subroutine );
704 
705 	m_pCode->queueLabel( "__divide_shift", Code::Subroutine );
706 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
707 	m_pCode->append(new Instr_rlf("__k",1), Code::Subroutine );
708 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
709 	m_pCode->append(new Instr_rlf("__j",1), Code::Subroutine );
710 	m_pCode->append(new Instr_btfss("__j","7"), Code::Subroutine );
711 	m_pCode->append(new Instr_goto("__divide_shift"), Code::Subroutine );
712 
713 	m_pCode->queueLabel( "__divide_loop", Code::Subroutine );
714 	m_pCode->append(new Instr_movf("__j",0), Code::Subroutine );
715 	m_pCode->append(new Instr_subwf("__i",1), Code::Subroutine );
716 	m_pCode->append(new Instr_btfsc("STATUS","C"), Code::Subroutine );
717 	m_pCode->append(new Instr_goto("__divide_count"), Code::Subroutine );
718 	m_pCode->append(new Instr_addwf("__i",1), Code::Subroutine );
719 	m_pCode->append(new Instr_goto("__divide_final"), Code::Subroutine );
720 
721 	m_pCode->queueLabel( "__divide_count", Code::Subroutine );
722 	m_pCode->append(new Instr_movf("__k",0), Code::Subroutine );
723 	m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine );
724 
725 	m_pCode->queueLabel( "__divide_final", Code::Subroutine );
726 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
727 	m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine );
728 	m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine );
729 	m_pCode->append(new Instr_rrf("__k",1), Code::Subroutine );
730 	m_pCode->append(new Instr_btfss("STATUS","C"), Code::Subroutine );
731 	m_pCode->append(new Instr_goto("__divide_loop"), Code::Subroutine );
732 	m_pCode->append(new Instr_return(), Code::Subroutine );
733 }
734 
735 
ifCode()736 Code * PIC14::ifCode()
737 {
738 	return m_ifCode;
739 }
740 
741 
elseCode()742 Code * PIC14::elseCode()
743 {
744 	return m_elseCode;
745 }
746 
747 
ifInitCode(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)748 void PIC14::ifInitCode( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
749 {
750 	// NOO - "x < 2" is NOT the same as "2 < x"
751 // 	rearrangeOpArguments( val1, val2, val1Type, val2Type );
752 
753 	switch(val1Type)
754 	{
755 		case num:
756 			m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 )));
757 			break;
758 
759 		case work:
760 			break; // Nothing to do
761 
762 		case var:
763 			m_pCode->append(new Instr_movf(val1,0));
764 			break;
765 	}
766 
767 	switch(val2Type)
768 	{
769 		case num:
770 			m_pCode->append(new Instr_sublw(val2.toInt( nullptr, 0 )));
771 			break;
772 
773 		case work:
774 			qCritical() << Q_FUNC_INFO << "Cannot subtract working from working!" << endl;
775 			break;
776 
777 		case var:
778 			m_pCode->append(new Instr_subwf(val2,0));
779 			break;
780 	}
781 }
782 
equal(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)783 void PIC14::equal( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
784 {
785 	ifInitCode( val1, val2, val1Type, val2Type );
786 	const QString labelEnd = mb->uniqueLabel()+"_endif";
787 	const QString labelFalse = mb->uniqueLabel()+"_case_false";
788 
789 	m_pCode->append(new Instr_btfss("STATUS","2"));
790 	m_pCode->append(new Instr_goto(labelFalse));
791 
792 	mergeCode( ifCode() );
793 
794 	m_pCode->append(new Instr_goto(labelEnd));
795 
796 	m_pCode->queueLabel( labelFalse );
797 	mergeCode( elseCode() );
798 	m_pCode->queueLabel( labelEnd );
799 }
800 
notEqual(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)801 void PIC14::notEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
802 {
803 	ifInitCode( val1, val2, val1Type, val2Type );
804 	const QString labelEnd = mb->uniqueLabel()+"_endif";
805 	const QString labelFalse = mb->uniqueLabel()+"_case_false";
806 
807 	m_pCode->append(new Instr_btfsc("STATUS","2"));
808 	m_pCode->append(new Instr_goto(labelFalse));
809 
810 	mergeCode( ifCode() );
811 
812 	m_pCode->append(new Instr_goto(labelEnd));
813 
814 	m_pCode->queueLabel( labelFalse );
815 	mergeCode( elseCode() );
816 	m_pCode->queueLabel( labelEnd );
817 }
818 
greaterThan(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)819 void PIC14::greaterThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
820 {
821 	ifInitCode( val1, val2, val1Type, val2Type );
822 	const QString labelEnd = mb->uniqueLabel()+"_endif";
823 	const QString labelFalse = mb->uniqueLabel()+"_case_false";
824 
825 	m_pCode->append(new Instr_btfsc("STATUS","0"));
826 	m_pCode->append(new Instr_goto(labelFalse));
827 
828 	mergeCode( ifCode() );
829 	m_pCode->append(new Instr_goto(labelEnd));
830 
831 	m_pCode->queueLabel( labelFalse );
832 	mergeCode( elseCode() );
833 	m_pCode->queueLabel( labelEnd );
834 }
835 
lessThan(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)836 void PIC14::lessThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
837 {
838 	cout << Q_FUNC_INFO << endl;
839 	ifInitCode( val1, val2, val1Type, val2Type );
840 	const QString labelEnd = mb->uniqueLabel()+"_endif";
841 	const QString labelFalse = mb->uniqueLabel()+"_case_false";
842 
843 	m_pCode->append(new Instr_btfss("STATUS","0"));
844 	m_pCode->append(new Instr_goto(labelFalse));
845 	m_pCode->append(new Instr_btfsc("STATUS","2"));
846 	m_pCode->append(new Instr_goto(labelFalse));
847 
848 	mergeCode( ifCode() );
849 
850 	m_pCode->append(new Instr_goto(labelEnd));
851 
852 	m_pCode->queueLabel( labelFalse );
853 	mergeCode( elseCode() );
854 	m_pCode->queueLabel( labelEnd );
855 }
856 
greaterOrEqual(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)857 void PIC14::greaterOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
858 {
859 	ifInitCode( val1, val2, val1Type, val2Type );
860 	const QString labelEnd = mb->uniqueLabel()+"_endif";
861 	const QString labelTrue = mb->uniqueLabel()+"_case_true"; // Note that unlike the others, this is labelTrue, not labelFalse
862 
863 	m_pCode->append(new Instr_btfsc("STATUS","2"));
864 	m_pCode->append(new Instr_goto(labelTrue));
865 	m_pCode->append(new Instr_btfss("STATUS","0"));
866 	m_pCode->append(new Instr_goto(labelTrue));
867 
868 	mergeCode( elseCode() );
869 
870 	m_pCode->append(new Instr_goto(labelEnd));
871 
872 	m_pCode->queueLabel( labelTrue );
873 	mergeCode( ifCode() );
874 	m_pCode->queueLabel( labelEnd );
875 }
876 
lessOrEqual(const QString & val1,const QString & val2,LocationType val1Type,LocationType val2Type)877 void PIC14::lessOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type )
878 {
879 	ifInitCode( val1, val2, val1Type, val2Type );
880 	const QString labelEnd = mb->uniqueLabel()+"_endif";
881 	const QString labelFalse = mb->uniqueLabel()+"_case_false";
882 
883 	m_pCode->append(new Instr_btfss("STATUS","0"));
884 	m_pCode->append(new Instr_goto(labelFalse));
885 
886 	mergeCode( ifCode() );
887 	m_pCode->append(new Instr_goto(labelEnd));
888 
889 	m_pCode->queueLabel( labelFalse );
890 	mergeCode( elseCode() );
891 	m_pCode->queueLabel( labelEnd );
892 }
893 
894 
Swhile(Code * whileCode,const QString & expression)895 void PIC14::Swhile( Code * whileCode, const QString &expression)
896 {
897 	QString result;
898 	QString ul = mb->uniqueLabel();
899 
900 	whileCode->append( new Instr_goto(ul) );
901 
902 	m_pCode->queueLabel( ul, Code::Middle );
903 
904 	// If the condition is not true, just fall through
905 	m_parser->compileConditionalExpression( expression, whileCode, nullptr );
906 }
907 
908 
Srepeat(Code * repeatCode,const QString & expression)909 void PIC14::Srepeat( Code * repeatCode, const QString &expression)
910 {
911 	QString result;
912 	QString ul = mb->uniqueLabel();
913 
914 	Code * elseCode = new Code;
915 	elseCode->append( new Instr_goto(ul) );
916 
917 	m_pCode->queueLabel( ul );
918 	m_pCode->merge( repeatCode );
919 
920 	// If the condition is true, just fall through
921 	m_parser->compileConditionalExpression( expression, nullptr, elseCode );
922 }
923 
Sif(Code * ifCode,Code * elseCode,const QString & expression)924 void PIC14::Sif( Code * ifCode, Code * elseCode, const QString &expression)
925 {
926 	m_parser->compileConditionalExpression( expression, ifCode, elseCode );
927 }
928 
929 
Sfor(Code * forCode,Code * initCode,const QString & expression,const QString & variable,const QString & step,bool stepPositive)930 void PIC14::Sfor( Code * forCode, Code * initCode, const QString &expression, const QString &variable, const QString &step, bool stepPositive)
931 {
932 	QString ul = mb->uniqueLabel();
933 
934 	if ( step == "1" )
935 	{
936 		if (stepPositive)
937 			forCode->append(new Instr_incf(variable,1));
938 		else
939 			forCode->append(new Instr_decf(variable,1));
940 	}
941 	else
942 	{
943 		forCode->append(new Instr_movlw(step.toInt( nullptr, 0 )));
944 		if (stepPositive)
945 			forCode->append(new Instr_addwf(variable,1));
946 		else
947 			forCode->append(new Instr_subwf(variable,1));
948 	}
949 	forCode->append(new Instr_goto(ul));
950 
951 	m_pCode->merge( initCode );
952 
953 	m_pCode->queueLabel( ul );
954 
955 	m_parser->compileConditionalExpression( expression, forCode, nullptr );
956 }
957 
958 
Spin(const PortPin & portPin,bool NOT)959 void PIC14::Spin( const PortPin & portPin, bool NOT)
960 {
961 	QString lowLabel, highLabel, postLabel;
962 	lowLabel = mb->uniqueLabel();
963 	highLabel = mb->uniqueLabel();
964 	postLabel = mb->uniqueLabel();
965 	/*result += indent + "goto\t" + lowLabel;
966 	result += indent + "movlw\t1" + "goto\t"+postLabel+;
967 	result += lowLabel +  + indent + "movlw\t0" + indent;
968 	result += postLabel + ;*/
969 
970 	if(NOT)
971 		m_pCode->append(new Instr_btfsc( portPin.port(), QString::number( portPin.pin() ) ));
972 	//result +=instruction((QString)(NOT?"btfsc":"btfss")+"\t"+port+","+pin);
973 	else
974 		m_pCode->append(new Instr_btfss( portPin.port(), QString::number( portPin.pin() ) ));
975 
976 	m_pCode->append(new Instr_goto(lowLabel));//result += instruction("goto\t" + lowLabel);
977 	mergeCode( ifCode() );
978 	m_pCode->append(new Instr_goto(postLabel));//result += instruction("goto\t"+postLabel);
979 
980 	m_pCode->queueLabel( lowLabel );
981 	mergeCode( elseCode() );
982 
983 	m_pCode->queueLabel( postLabel );
984 }
985 
986 
Sdelay(unsigned length_us,Code::InstructionPosition pos)987 void PIC14::Sdelay( unsigned length_us, Code::InstructionPosition pos )
988 {
989 	if ( length_us == 0 )
990 		return;
991 
992 	if ( length_us > 50070524 )
993 	{
994 		length_us += 50267642;
995 		int l = length_us/50070530;
996 		length_us -= l * 50070530;
997 		int k = length_us/196355;
998 
999 		m_pCode->append( new Instr_movlw( l ), pos );
1000 		m_pCode->append( new Instr_movwf( "__l" ), pos );
1001 		m_pCode->append( new Instr_movlw( k ), pos );
1002 		m_pCode->append( new Instr_movwf( "__k" ), pos );
1003 
1004 		mb->addDelayRoutineWanted( Delay_50S );
1005 	}
1006 
1007 	else if ( length_us > 196350 )
1008 	{
1009 		length_us += 197116;
1010 		int k = length_us/196355;
1011 		length_us -= k * 196355;
1012 		int j = length_us/770;
1013 
1014 		m_pCode->append( new Instr_incf( "__l", 1 ), pos );
1015 		m_pCode->append( new Instr_movlw( k ), pos );
1016 		m_pCode->append( new Instr_movwf( "__k" ), pos );
1017 		m_pCode->append( new Instr_movlw( j ), pos );
1018 		m_pCode->append( new Instr_movwf( "__j" ), pos );
1019 
1020 		mb->addDelayRoutineWanted( Delay_200mS );
1021 	}
1022 
1023 	else if ( length_us > 766 )
1024 	{
1025 		length_us += 765;
1026 		int j = length_us/770;
1027 		length_us -= j * 770;
1028 		int i = length_us/3;
1029 
1030 		m_pCode->append( new Instr_incf( "__l", 1 ), pos );
1031 		m_pCode->append( new Instr_incf( "__k", 1 ), pos );
1032 		m_pCode->append( new Instr_movlw( j ), pos );
1033 		m_pCode->append( new Instr_movwf( "__j" ), pos );
1034 		m_pCode->append( new Instr_movlw( i ), pos );
1035 		m_pCode->append( new Instr_movwf( "__i" ), pos );
1036 
1037 		mb->addDelayRoutineWanted( Delay_768uS );
1038 	}
1039 
1040 	else
1041 	{
1042 		length_us += -1;
1043 		int i = length_us/3;
1044 
1045 		m_pCode->append( new Instr_incf( "__l", 1 ), pos );
1046 		m_pCode->append( new Instr_incf( "__k", 1 ), pos );
1047 		m_pCode->append( new Instr_incf( "__j", 1 ), pos );
1048 		m_pCode->append( new Instr_movlw( i ), pos );
1049 		m_pCode->append( new Instr_movwf( "__i" ), pos );
1050 
1051 		mb->addDelayRoutineWanted( Delay_3uS );
1052 	}
1053 
1054 	m_pCode->append( new Instr_call( "__delay_subroutine"), pos );
1055 }
1056 
1057 
addCommonFunctions(DelaySubroutine delay)1058 void PIC14::addCommonFunctions( DelaySubroutine delay )
1059 {
1060 	if ( delay != Delay_None )
1061 	{
1062 		QString subName = "__delay_subroutine";
1063 		m_pCode->queueLabel( subName, Code::Subroutine );
1064 
1065 		m_pCode->append( new Instr_decfsz( "__i", 1 ), Code::Subroutine );
1066 		m_pCode->append( new Instr_goto( subName ), Code::Subroutine );
1067 
1068 		if ( delay > Delay_3uS )
1069 		{
1070 			m_pCode->append( new Instr_decfsz( "__j", 1 ), Code::Subroutine );
1071 			m_pCode->append( new Instr_goto( subName ), Code::Subroutine );
1072 		}
1073 
1074 		if ( delay > Delay_768uS )
1075 		{
1076 			m_pCode->append( new Instr_decfsz( "__k", 1 ), Code::Subroutine );
1077 			m_pCode->append( new Instr_goto( subName ), Code::Subroutine );
1078 		}
1079 
1080 		if ( delay > Delay_200mS )
1081 		{
1082 			m_pCode->append( new Instr_decfsz( "__l", 1 ), Code::Subroutine );
1083 			m_pCode->append( new Instr_goto( subName ), Code::Subroutine );
1084 		}
1085 
1086 		m_pCode->append( new Instr_return(), Code::Subroutine );
1087 	}
1088 }
1089 
1090 
SsevenSegment(const Variable & pinMap)1091 void PIC14::SsevenSegment( const Variable & pinMap )
1092 {
1093 	assert( pinMap.type() == Variable::sevenSegmentType );
1094 	assert( pinMap.portPinList().size() == 7 );
1095 
1096 	QString subName = QString("__output_seven_segment_%1").arg( pinMap.name() );
1097 
1098 	m_pCode->append( new Instr_call( subName ) );
1099 
1100 	if ( m_pCode->instruction(subName) )
1101 		return;
1102 
1103 	// Build up what are going to write to each port from the pin map
1104 	struct SSPortOutput
1105 	{
1106 		bool used; // Wheter we use this port at all
1107 		bool use[8]; // Whether or not we use each pin.
1108 		bool out[16][8]; // The bit to write to each pin for each value.
1109 		uchar useMask; // The bits of use[8] - this is generated later from use[8]
1110 	};
1111 
1112 	unsigned numPorts = 2;
1113 	SSPortOutput portOutput[ 2 ];  // numPorts
1114 	memset( portOutput, 0, numPorts * sizeof(SSPortOutput) );
1115 
1116 	for ( unsigned i = 0; i < 7; ++i )
1117 	{
1118 		PortPin portPin = pinMap.portPinList()[i];
1119 
1120 		unsigned port = unsigned( portPin.portPosition() );
1121 		unsigned pin = unsigned( portPin.pin() );
1122 
1123 		portOutput[ port ].used = true;
1124 		portOutput[ port ].use[ pin ] = true;
1125 
1126 		for ( unsigned num = 0; num < 16; ++num )
1127 		{
1128 			portOutput[ port ].out[ num ][ pin ] = LEDSegTable[num][ i ];
1129 		}
1130 	}
1131 
1132 
1133 	// See if we've used more than one port
1134 	unsigned portsUsed = 0;
1135 	for ( unsigned port = 0; port < numPorts; ++port )
1136 	{
1137 		if ( portOutput[port].used )
1138 			portsUsed++;
1139 	}
1140 
1141 
1142 	// Generate the useMasks
1143 	for ( unsigned port = 0; port < numPorts; ++port )
1144 	{
1145 		portOutput[port].useMask = 0;
1146 		for ( unsigned pin = 0; pin < 8; ++pin )
1147 			portOutput[port].useMask |= portOutput[port].use[pin] ? (1 << pin) : 0;
1148 	}
1149 
1150 
1151 	//BEGIN Generate [subName] Subroutine
1152 	m_pCode->queueLabel( subName, Code::Subroutine );
1153 // 	if ( portsUsed > 1 )
1154 	{
1155 		m_pCode->append( new Instr_movwf("__i"), Code::Subroutine );
1156 	}
1157 
1158 // 	bool overwrittenW = false;
1159 	bool overwrittenW = true;
1160 
1161 	for ( unsigned port = 0; port < numPorts; ++port )
1162 	{
1163 		if ( !portOutput[port].used )
1164 			continue;
1165 
1166 		QString portName = QString("PORT%1").arg( char('A'+port) );
1167 
1168 		// Save the current value of the port pins that we should not be writing to
1169 		m_pCode->append( new Instr_movf( portName, 0 ), Code::Subroutine );
1170 		m_pCode->append( new Instr_andlw( ~portOutput[port].useMask ), Code::Subroutine );
1171 		m_pCode->append( new Instr_movwf( "__j" ), Code::Subroutine );
1172 
1173 		if ( overwrittenW )
1174 			m_pCode->append( new Instr_movf("__i",0), Code::Subroutine );
1175 
1176 		m_pCode->append( new Instr_call( subName + QString("_lookup_%1").arg(port) ), Code::Subroutine );
1177 		overwrittenW = true;
1178 
1179 		// Restore the state of the pins which aren't used
1180 		m_pCode->append( new Instr_iorwf( "__j", 0 ), Code::Subroutine );
1181 
1182 		// And write the result to the port
1183 		m_pCode->append( new Instr_movwf( portName ), Code::Subroutine );
1184 	}
1185 
1186 	m_pCode->append( new Instr_return(), Code::Subroutine );
1187 	//END Generate [subName] Subroutine
1188 
1189 	// For each port, generate code for looking up the value for writing to it
1190 	for ( unsigned port = 0; port < numPorts; ++port )
1191 	{
1192 		if ( !portOutput[port].used )
1193 			continue;
1194 
1195 		m_pCode->queueLabel( subName + QString("_lookup_%1").arg(port), Code::LookupTable );
1196 		m_pCode->append( new Instr_andlw(15), Code::LookupTable );
1197 
1198 		// Generate the lookup table
1199 		m_pCode->append( new Instr_addwf( "pcl", 1 ), Code::LookupTable );
1200 		for ( unsigned num = 0; num < 16; ++num )
1201 		{
1202 			unsigned literal = 0;
1203 			for ( unsigned bit = 0; bit < 8; ++bit )
1204 				literal += ( portOutput[port].out[num][bit] ? 1 : 0 ) << bit;
1205 
1206 			m_pCode->append( new Instr_retlw( literal ), Code::LookupTable );
1207 		}
1208 	}
1209 }
1210 
1211 
Skeypad(const Variable & pinMap)1212 void PIC14::Skeypad( const Variable & pinMap )
1213 {
1214 	// pinMap = 4 rows, n columns
1215 
1216 	assert( pinMap.type() == Variable::keypadType );
1217 	assert( pinMap.portPinList().size() >= 7 ); // 4 rows, at least 3 columns
1218 
1219 	QString subName = QString("__wait_read_keypad_%1").arg( pinMap.name() );
1220 	QString waitName = QString("__wait_keypad_%1").arg( pinMap.name() );
1221 	QString readName = QString("__read_keypad_%1").arg( pinMap.name() );
1222 
1223 	m_pCode->append( new Instr_call( subName ) );
1224 
1225 	if ( m_pCode->instruction( subName ) )
1226 		return;
1227 
1228 	//BEGIN Wait until read subroutine
1229 	m_pCode->queueLabel( subName, Code::Subroutine );
1230 
1231 	// Read current key (if any) from keypad and save to temporary variable
1232 	m_pCode->append( new Instr_call( readName ), Code::Subroutine );
1233 	m_pCode->append( new Instr_movwf( "__m" ), Code::Subroutine );
1234 
1235 	// Test if any key was pressed; if not, then start again
1236 // 	std::cout << "mb->alias(\"Keypad_None\")="<<mb->alias("Keypad_None") << std::endl;
1237 	m_pCode->append( new Instr_sublw( mb->alias("Keypad_None").toInt( nullptr, 0 ) ), Code::Subroutine );
1238 	m_pCode->append( new Instr_btfsc( "STATUS","Z" ), Code::Subroutine );
1239 	m_pCode->append( new Instr_goto( subName ), Code::Subroutine );
1240 	m_pCode->append( new Instr_goto( waitName ), Code::Subroutine );
1241 	//END Wait until read subroutine
1242 
1243 
1244 	//BEGIN Wait until released subroutine
1245 	m_pCode->queueLabel( waitName, Code::Subroutine );
1246 
1247 	Sdelay( 10000, Code::Subroutine ); // 10 milliseconds for debouncing
1248 
1249 	// Key was pressed; now we wait until the key is released again
1250 	m_pCode->append( new Instr_call( readName ), Code::Subroutine );
1251 	m_pCode->append( new Instr_sublw( mb->alias("Keypad_None").toInt( nullptr, 0 ) ), Code::Subroutine );
1252 	m_pCode->append( new Instr_btfss( "STATUS","Z" ), Code::Subroutine );
1253 	m_pCode->append( new Instr_goto( waitName ), Code::Subroutine );
1254 	m_pCode->append( new Instr_movf( "__m", 0 ), Code::Subroutine );
1255 	m_pCode->append( new Instr_return(), Code::Subroutine );
1256 	//END Wait until released subroutine
1257 
1258 
1259 	if ( m_pCode->instruction( readName ) )
1260 		return;
1261 
1262 	//BEGIN Read current value of keypad subroutine
1263 	m_pCode->queueLabel( readName, Code::Subroutine );
1264 
1265 	// Make the four row lines low
1266 	for ( unsigned row = 0; row < 4; ++ row )
1267 	{
1268 		PortPin rowPin = pinMap.portPinList()[row];
1269 		m_pCode->append( new Instr_bcf( rowPin.port(), QString::number( rowPin.pin() ) ), Code::Subroutine );
1270 	}
1271 
1272 	// Test each row in turn
1273 	for ( unsigned row = 0; row < 4; ++ row )
1274 	{
1275 		// Make the high low
1276 		PortPin rowPin = pinMap.portPinList()[row];
1277 		m_pCode->append( new Instr_bsf( rowPin.port(), QString::number( rowPin.pin() ) ), Code::Subroutine );
1278 
1279 		for ( unsigned col = 0; col < 3; ++ col )
1280 		{
1281 			PortPin colPin = pinMap.portPinList()[4+col];
1282 			m_pCode->append( new Instr_btfsc( colPin.port(), QString::number( colPin.pin() ) ), Code::Subroutine );
1283 			m_pCode->append( new Instr_retlw( mb->alias( QString("Keypad_%1_%2").arg(row+1).arg(col+1) ).toInt( nullptr, 0 ) ), Code::Subroutine );
1284 		}
1285 
1286 		// Make the low again
1287 		m_pCode->append( new Instr_bcf( rowPin.port(), QString::number( rowPin.pin() ) ), Code::Subroutine );
1288 	}
1289 
1290 	// No key was pressed
1291 	m_pCode->append( new Instr_retlw( mb->alias("Keypad_None").toInt( nullptr, 0 ) ), Code::Subroutine );
1292 	//END Read current value of keypad subroutine
1293 }
1294 
1295 /*****************************commented for modification *******************************
1296 
1297 void PIC14::bitwise( Expression::Operation op, const QString &r_val1, const QString &val2, bool val1IsNum, bool val2IsNum )
1298 {
1299 	QString val1 = r_val1;
1300 	// There is no instruction for notting a literal,
1301 	// so instead I am going to XOR with 0xFF
1302 	if( op == Expression::bwnot ) val1 = "0xFF";
1303 	if( val1IsNum ) m_pCode->append(new Instr_movlw(val1.toInt( 0, 0 )));// result += instruction("movlw\t"+val1);
1304 	else m_pCode->append(new Instr_movf(val1,0));//result += instruction("movf\t"+val1+",0");
1305 
1306 	QString opString;
1307 	if( val2IsNum )
1308 	{
1309 		switch(op)
1310 		{
1311 			case Expression::bwand: m_pCode->append(new Instr_andlw(val2.toInt( 0, 0 ))); break;
1312 			case Expression::bwor: m_pCode->append(new Instr_iorlw(val2.toInt( 0, 0 ))); break;
1313 			case Expression::bwxor: m_pCode->append(new Instr_xorlw(val2.toInt( 0, 0 ))); break;
1314 			case Expression::bwnot: m_pCode->append(new Instr_xorlw(val2.toInt( 0, 0 ))); break;
1315 			default: break;
1316 		}
1317 	}
1318 	else
1319 	{
1320 		switch(op)
1321 		{
1322 			case Expression::bwand: m_pCode->append(new Instr_andwf(val2,0)); break;
1323 			case Expression::bwor: m_pCode->append(new Instr_iorwf(val2,0)); break;
1324 			case Expression::bwxor: m_pCode->append(new Instr_xorwf(val2,0)); break;
1325 			case Expression::bwnot: m_pCode->append(new Instr_xorwf(val2,0)); break;
1326 			default: break;
1327 		}
1328 
1329 	}
1330 }*/
1331 ///comment end and the new function is given bellow -- new code is working well
1332 // TODO - One error with OR operation if A OR 255 result in segebentation fault
1333 //*****************modified to make the bit operation works***************************/
bitwise(Expression::Operation op,const QString & r_val1,const QString & val2,LocationType val1Type,LocationType val2Type)1334 void PIC14::bitwise( Expression::Operation op,const QString & r_val1, const QString & val2, LocationType val1Type, LocationType val2Type)
1335 {
1336 	QString val1 = r_val1;
1337 	if( op == Expression::bwnot ) val1 = "0xFF";
1338 	switch(val1Type)
1339 	{
1340 		case num: m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); break;
1341 		case work: break;
1342 		case var: m_pCode->append(new Instr_movf(val1,0)); break;
1343 	}
1344 	switch(val2Type)
1345 	{
1346 		case num:
1347 		{
1348 			switch(op)
1349 			{
1350 				case Expression::bwand: m_pCode->append(new Instr_andlw(val2.toInt( nullptr, 0 ))); break;
1351 				case Expression::bwor:  m_pCode->append(new Instr_iorlw(val2.toInt( nullptr, 0 ))); break;
1352 				case Expression::bwxor: m_pCode->append(new Instr_xorlw(val2.toInt( nullptr, 0 ))); break;
1353 				case Expression::bwnot: m_pCode->append(new Instr_xorlw(val2.toInt( nullptr, 0 ))); break;
1354 				default: break;
1355 		}
1356 		}
1357 		case work: break;
1358 		case var:
1359 		{
1360 			switch(op)
1361 			{
1362 				case Expression::bwand: m_pCode->append(new Instr_andwf(val2,0)); break;
1363 				case Expression::bwor:  m_pCode->append(new Instr_iorwf(val2,0)); break;
1364 				case Expression::bwxor: m_pCode->append(new Instr_xorwf(val2,0)); break;
1365 				case Expression::bwnot: m_pCode->append(new Instr_xorwf(val2,0)); break;
1366 				default: break;
1367 			}
1368 
1369 		}
1370 	}
1371 
1372 }//***************************************modification ends*****************************
SincVar(const QString & var)1373 void PIC14::SincVar( const QString &var )
1374 {
1375 	m_pCode->append(new Instr_incf(var,1) );
1376 }
1377 
SdecVar(const QString & var)1378 void PIC14::SdecVar( const QString &var )
1379 {
1380 	m_pCode->append(new Instr_decf(var,1) );
1381 }
1382 
SrotlVar(const QString & var)1383 void PIC14::SrotlVar( const QString &var )
1384 {
1385 	m_pCode->append(new Instr_rlf(var,1));
1386 }
1387 
SrotrVar(const QString & var)1388 void PIC14::SrotrVar( const QString &var )
1389 {
1390 	m_pCode->append(new Instr_rrf(var,1));
1391 }
1392 
Stristate(const QString & port)1393 void PIC14::Stristate(const QString &port)
1394 {
1395 //modification pic type is checked here
1396 	m_pCode->append( new Instr_bsf("STATUS","5") );//commented
1397 	if(pic_type== "P16C84" || pic_type =="P16F84"||pic_type =="P16F627")
1398 	{
1399 		if( port == "trisa" || port == "TRISA" )
1400 			saveResultToVar( "TRISA" );
1401 		else	saveResultToVar( "TRISB" );
1402 	}
1403 	if(pic_type =="P16F877")
1404 	{
1405 		if( port == "trisa" || port == "TRISA" )
1406 			saveResultToVar( "TRISA" );
1407 		else if( port == "trisb" || port == "TRISB" )
1408 			saveResultToVar( "TRISB" );
1409 		else if( port == "trisc" || port == "TRISC" )
1410 			saveResultToVar( "TRISC" );
1411 		else if( port == "trisd" || port == "TRISD" )
1412 			saveResultToVar( "TRISD" );
1413 		else	saveResultToVar( "TRISE" );
1414 
1415 	}
1416 	m_pCode->append( new Instr_bcf(Register("STATUS"),"5") );//commented
1417 }
1418 
Sasm(const QString & raw)1419 void PIC14::Sasm(const QString &raw)
1420 {
1421 	m_pCode->append(new Instr_asm(raw));
1422 }
1423 
1424 //BEGIN class PortPin
PortPin(const QString & port,int pin)1425 PortPin::PortPin( const QString & port, int pin )
1426 {
1427 	m_port = port.toUpper();
1428 	m_pin = pin;
1429 }
1430 
1431 
PortPin()1432 PortPin::PortPin()
1433 {
1434 	m_port = ' ';
1435 	m_pin = -1;
1436 }
1437 
1438 
portPosition() const1439 int PortPin::portPosition() const
1440 {
1441 	if ( m_port.isEmpty() )
1442 		return 0;
1443 	return uchar( m_port[ m_port.length() - 1 ].toLatin1() ) - 'A';
1444 }
1445 
1446 //END class PortPin
1447 
1448