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