File indexing completed on 2025-02-16 05:15:12
0001 /*************************************************************************** 0002 * Copyright (C) 2004-2005 by Daniel Clarke * 0003 * daniel.jc@gmail.com * 0004 * * 0005 * 24-04-2007 * 0006 * Modified to add pic 16f877,16f627 and 16f628 * 0007 * by george john george@space-kerala.org * 0008 * supported by SPACE www.space-kerala.org * 0009 * * 0010 * This program is free software; you can redistribute it and/or modify * 0011 * it under the terms of the GNU General Public License as published by * 0012 * the Free Software Foundation; either version 2 of the License, or * 0013 * (at your option) any later version. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program; if not, write to the * 0022 * Free Software Foundation, Inc., * 0023 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0024 ***************************************************************************/ 0025 0026 0027 #include "instruction.h" 0028 #include "parser.h" 0029 #include "pic14.h" 0030 0031 #include <QDebug> 0032 0033 #include <cassert> 0034 #include <iostream> 0035 using namespace std; 0036 QString pic_type; 0037 bool LEDSegTable[][7] = { 0038 { 1, 1, 1, 1, 1, 1, 0 }, 0039 { 0, 1, 1, 0, 0, 0, 0 }, // 1 0040 { 1, 1, 0, 1, 1, 0, 1 }, // 2 0041 { 1, 1, 1, 1, 0, 0, 1 }, // 3 0042 { 0, 1, 1, 0 ,0, 1, 1 }, // 4 0043 { 1, 0, 1, 1, 0, 1, 1 }, // 5 0044 { 1, 0, 1, 1, 1, 1, 1 }, // 6 0045 { 1, 1, 1, 0, 0, 0, 0 }, // 7 0046 { 1, 1, 1, 1, 1, 1, 1 }, // 8 0047 { 1, 1, 1, 0, 0, 1, 1 }, // 9 0048 { 1, 1, 1, 0, 1, 1, 1 }, // A 0049 { 0, 0, 1, 1, 1, 1, 1 }, // b 0050 { 1, 0, 0, 1, 1, 1, 0 }, // C 0051 { 0, 1, 1, 1, 1, 0, 1 }, // d 0052 { 1, 0, 0, 1, 1, 1, 1 }, // E 0053 { 1, 0, 0, 0, 1, 1, 1 } // F 0054 }; 0055 0056 0057 0058 PIC14::PIC14( MicrobeApp * master, Type type ) 0059 { 0060 mb = master; 0061 m_pCode = nullptr; 0062 m_type = type; 0063 0064 } 0065 0066 0067 PIC14::~PIC14() 0068 { 0069 } 0070 0071 PortPin PIC14::toPortPin( const QString & portPinString ) 0072 { 0073 QString port,holdport; 0074 int pin = -1; 0075 /*****************************modified *********************************************/ 0076 //inorder to support RB.3=high/1 0077 0078 if ( portPinString.length() == 3 ) 0079 { 0080 port = QString("PORT%1").arg( portPinString[1].toUpper() ); 0081 pin = QString( portPinString[2] ).toInt(); 0082 } 0083 // In form e.g. RB.3 0084 else if ( portPinString.length() == 4 )//modification change ==3 to ==4 0085 { 0086 port = QString("PORT%1").arg( portPinString[1].toUpper() ); 0087 pin = QString( portPinString[3] ).toInt();//modification change 2 to 3 0088 } 0089 else 0090 { 0091 int dotpos = portPinString.indexOf("."); 0092 if ( dotpos == -1 ) 0093 return PortPin(); 0094 0095 port = portPinString.left(dotpos); 0096 //modified checking is added in the case of Register also 0097 //now INTCON.GIE is high ,and INTCON.GIE=1/high works 0098 if(isValidRegister( port)) 0099 { 0100 0101 RegisterBit REG(portPinString.mid(dotpos+1)); 0102 pin=REG.bitPos(); 0103 Register Reg(REG.registerType()); 0104 holdport=Reg.name(); 0105 if(holdport!=port) 0106 cerr << QString(" ERROR: %1 is not a Register bit\n").arg(portPinString ).toStdString(); 0107 } 0108 else 0109 pin = portPinString.mid(dotpos+1).toInt(); 0110 0111 0112 //***************************Modification ends******************************** 0113 } 0114 0115 PortPin portPin( port, pin ); 0116 0117 if ( isValidPortPin( portPin ) ) 0118 return portPin; 0119 //**************************Modification start ******************************** 0120 else if(isValidRegister(port)) 0121 return portPin; 0122 //**************************Modification ends ******************************** 0123 else 0124 { 0125 cerr << QString("ERROR: %1 is not a Port/Register bit\n").arg(portPinString ).toStdString(); 0126 return PortPin(); 0127 } 0128 } 0129 0130 0131 void PIC14::mergeCode( Code * code ) 0132 { 0133 m_pCode->merge( code ); 0134 } 0135 0136 0137 uchar PIC14::gprStart() const 0138 { 0139 switch ( m_type ) 0140 { 0141 case P16C84: 0142 case P16F84: 0143 return 0xc; 0144 0145 case P16F627: 0146 case P16F628: 0147 case P16F877: 0148 return 0x20; 0149 0150 case unknown: 0151 break; 0152 } 0153 0154 qCritical() << Q_FUNC_INFO << "Unknown PIC type = " << m_type; 0155 return 0xc; 0156 } 0157 0158 0159 PIC14::Type PIC14::toType( const QString & _text ) 0160 { 0161 QString text = _text.toUpper().simplified().remove('P'); 0162 0163 if ( text == "16C84" ) 0164 { 0165 pic_type="P16C84"; 0166 return P16C84; 0167 } 0168 if ( text == "16F84" ) 0169 { 0170 pic_type="P16F84"; 0171 return P16F84; 0172 } 0173 if ( text == "16F627" ) 0174 { 0175 pic_type="P16F627"; 0176 return P16F627; 0177 } 0178 0179 if ( text == "16F628" ) 0180 { 0181 pic_type="P16F627"; 0182 return P16F628; 0183 } 0184 //modified checking of 16F877 is included 0185 if ( text == "16F877" ) 0186 { 0187 pic_type="P16F877"; 0188 return P16F877; 0189 } 0190 0191 cerr << QString("%1 is not a known PIC identifier\n").arg(_text).toStdString(); 0192 return unknown; 0193 } 0194 0195 0196 QString PIC14::minimalTypeString() const 0197 { 0198 switch ( m_type ) 0199 { 0200 case P16C84: 0201 return "16C84"; 0202 0203 case P16F84: 0204 return "16F84"; 0205 0206 case P16F627: 0207 return "16F627"; 0208 0209 case P16F628: 0210 return "16F628"; 0211 0212 //modified checking of 16F877 is included 0213 0214 case P16F877: 0215 return "16F877"; 0216 0217 case unknown: 0218 break; 0219 } 0220 0221 qCritical() << Q_FUNC_INFO << "Unknown PIC type = " << m_type; 0222 return nullptr;; 0223 } 0224 0225 0226 void PIC14::postCompileConstruct( const QStringList &interrupts ) 0227 { 0228 m_pCode->append( new Instr_raw("\n\tEND\n"), Code::Subroutine ); 0229 0230 if ( interrupts.isEmpty() ) 0231 { 0232 // If there are no ISRs then we don't need to put in any handler code. 0233 // Instead, just insert the goto start instruction in case we need to 0234 // jump past any lookup tabes (and if there are none, then the optimizer 0235 // will remove the goto instruction). 0236 m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler); 0237 m_pCode->queueLabel( "_start", Code::LookupTable ); 0238 return; 0239 } 0240 0241 /* 0242 INTCON register: 0243 7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0 0244 0245 E: enable 0246 F: flag 0247 Flag bits must be cleared manually before reactivating GIE, 0248 but we do this in each individual interrupt handler 0249 */ 0250 0251 // The bizarre dance with swap is to ensure the status bits 0252 // are preserved properly 0253 m_pCode->append(new Instr_goto("_start"), Code::InterruptHandler); 0254 0255 m_pCode->append(new Instr_raw("ORG 0x4"), Code::InterruptHandler); 0256 // When we arrive here: 0257 // Return address on stack, 0258 // GIE flag cleared (globally interrupts disabled) 0259 // W or STATUS not preserved by processor. 0260 m_pCode->append(new Instr_movwf("W_TEMP"), Code::InterruptHandler); 0261 m_pCode->append(new Instr_swapf("STATUS",0), Code::InterruptHandler); 0262 m_pCode->append(new Instr_movwf("STATUS_TEMP"), Code::InterruptHandler); 0263 0264 QStringList::ConstIterator interruptsEnd = interrupts.end(); 0265 for( QStringList::ConstIterator it = interrupts.begin(); it != interruptsEnd; ++it ) 0266 { 0267 // Is the interrupt's flag bit set? 0268 m_pCode->append(new Instr_btfsc("INTCON",QString::number(interruptNameToBit((*it), true))), Code::InterruptHandler); 0269 m_pCode->append(new Instr_goto("_interrupt_" + (*it)), Code::InterruptHandler); // Yes, do its handler routine 0270 // Otherwise fall through to the next. 0271 } 0272 0273 // If there was "somehow" a suprious interrupt there isn't really 0274 // much we can do about that (??) so just fall through and hope for the worst. 0275 0276 m_pCode->queueLabel( "_interrupt_end", Code::InterruptHandler ); 0277 m_pCode->append(new Instr_swapf("STATUS_TEMP",0), Code::InterruptHandler ); 0278 m_pCode->append(new Instr_movwf("STATUS"), Code::InterruptHandler ); 0279 m_pCode->append(new Instr_swapf("W_TEMP",1), Code::InterruptHandler ); 0280 m_pCode->append(new Instr_swapf("W_TEMP",0), Code::InterruptHandler ); 0281 m_pCode->append(new Instr_retfie()); // Returns and renables globally interrupts. 0282 0283 m_pCode->queueLabel( "_start", Code::LookupTable ); 0284 } 0285 0286 int PIC14::interruptNameToBit(const QString &name, bool flag) 0287 { 0288 // 7 --- GIE EEIE T0IE INTE RBIE T0IF INTF RBIF --- 0 0289 0290 if( name == "change" ) // RB 0291 { 0292 if(flag) return 0; 0293 else return 3; 0294 } 0295 else if( name == "timer" ) 0296 { 0297 if(flag) return 2; 0298 else return 5; 0299 } 0300 else if( name == "external" ) 0301 { 0302 if(flag) return 1; 0303 else return 4; 0304 } 0305 0306 return -1; 0307 } 0308 0309 0310 bool PIC14::isValidPort( const QString & portName ) const 0311 { 0312 0313 if(pic_type =="P16F84"||pic_type =="P16C84"||pic_type =="P16F627"||pic_type =="P16F628") 0314 return ( portName == "PORTA" || portName == "PORTB"); 0315 0316 if(pic_type=="P16F877") 0317 return ( portName == "PORTA" ||portName == "PORTB"||portName == "PORTC" ||portName == "PORTD"||portName == "PORTE"); 0318 0319 return false; 0320 } 0321 0322 0323 bool PIC14::isValidPortPin( const PortPin & portPin ) const 0324 { 0325 0326 if(pic_type == "P16F84" ||pic_type =="P16C84") 0327 { 0328 if ( portPin.port() == "PORTA" ) 0329 return (portPin.pin() >= 0) && (portPin.pin() <= 4); 0330 0331 if ( portPin.port() == "PORTB" ) 0332 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0333 } 0334 if(pic_type == "P16F627" ||pic_type =="P16F628") 0335 { 0336 if ( portPin.port() == "PORTA" ) 0337 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0338 0339 if ( portPin.port() == "PORTB" ) 0340 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0341 } 0342 0343 if(pic_type=="P16F877") 0344 { 0345 if ( portPin.port() == "PORTA" ) 0346 return (portPin.pin() >= 0) && (portPin.pin() <= 5); 0347 0348 if ( portPin.port() == "PORTB" ) 0349 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0350 if ( portPin.port() == "PORTC" ) 0351 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0352 0353 if ( portPin.port() == "PORTD" ) 0354 return (portPin.pin() >= 0) && (portPin.pin() <= 7); 0355 0356 if ( portPin.port() == "PORTE" ) 0357 return (portPin.pin() >= 0) && (portPin.pin() <= 2); 0358 } 0359 0360 return false; 0361 } 0362 0363 0364 bool PIC14::isValidTris( const QString & trisName ) const 0365 { 0366 if(pic_type =="P16F84"||pic_type =="P16C84"||pic_type =="P16F627"||pic_type =="P16F628") 0367 return ( trisName == "TRISA" || trisName == "TRISB"); 0368 0369 if(pic_type=="P16F877") 0370 return ( trisName =="TRISA"|| trisName =="TRISB"||trisName =="TRISC"||trisName == "TRISD"||trisName == "TRISE" ); 0371 0372 return false; 0373 } 0374 0375 //*****************Modified ****************************// 0376 //New function isValiedRegister is added to check whether a register is valied or not 0377 bool PIC14::isValidRegister( const QString & registerName)const 0378 { 0379 if(pic_type=="P16F84"||pic_type=="P16C84") 0380 return ( registerName == "TMR0" 0381 || registerName == "PCL" 0382 || registerName == "STATUS" 0383 || registerName == "FSR" 0384 || registerName == "EEDATH" 0385 || registerName == "EEADR" 0386 || registerName == "PCLATH" 0387 || registerName == "INTCON" 0388 || registerName == "EECON1" 0389 || registerName == "EECON2" 0390 || registerName == "OPTION_REG"); 0391 0392 if(pic_type=="P16F877") 0393 return ( registerName == "TMR0" 0394 || registerName == "PCL" 0395 || registerName == "STATUS" 0396 || registerName == "FSR" 0397 || registerName == "PCLATH" 0398 || registerName == "INTCON" 0399 || registerName == "PIR1" 0400 || registerName == "PIR2" 0401 || registerName == "TMR1L" 0402 || registerName == "TMR1H" 0403 || registerName == "T1CON" 0404 || registerName == "TMR2" 0405 || registerName == "T2CON" 0406 || registerName == "SSPBUF" 0407 || registerName == "SSPCON" 0408 || registerName == "CCPR1L" 0409 || registerName == "CCPR1H" 0410 || registerName == "CCP1CON" 0411 || registerName == "RCSTA" 0412 || registerName == "TXREG" 0413 || registerName == "RCREG" 0414 || registerName == "CCPR2L" 0415 || registerName == "CCPR2H" 0416 || registerName == "CCP2CON" 0417 || registerName == "ADRESH" 0418 || registerName == "ADCON0" /*bank0ends*/ 0419 || registerName == "OPTION_REG" 0420 || registerName == "PIE1" 0421 || registerName == "PIE2" 0422 || registerName == "PCON" 0423 || registerName == "SSPCON2" 0424 || registerName == "PR2" 0425 || registerName == "SSPADD" 0426 || registerName == "SSPSTAT" 0427 || registerName == "TXSTA" 0428 || registerName == "SPBRG" 0429 || registerName == "ADRESL" 0430 || registerName == "ADCON1" /*bank1ends*/ 0431 || registerName == "EEDATA" 0432 || registerName == "EEADR" 0433 || registerName == "EEDATH" 0434 || registerName == "EEADRH" /*bank2ends*/ 0435 || registerName == "EECON1" 0436 || registerName == "EECON2" /*bank3ends*/ ); 0437 0438 if(pic_type=="P16F627"||pic_type=="P16F628") 0439 return ( registerName == "TMR0" 0440 || registerName == "PCL" 0441 || registerName == "STATUS" 0442 || registerName == "FSR" 0443 || registerName == "PCLATH" 0444 || registerName == "INTCON" 0445 || registerName == "PIR1" 0446 || registerName == "TMR1L" 0447 || registerName == "TMR1H" 0448 || registerName == "T1CON" 0449 || registerName == "TMR2" 0450 || registerName == "T2CON" 0451 || registerName == "CCPR1L" 0452 || registerName == "CCPR1H" 0453 || registerName == "CCP1CON" 0454 || registerName == "RCSTA" 0455 || registerName == "TXREG" 0456 || registerName == "RCREG" 0457 || registerName == "CMCON"/*bank0ends*/ 0458 || registerName == "OPTION_REG" 0459 || registerName == "PIE1" 0460 || registerName == "PCON" 0461 || registerName == "PR2" 0462 || registerName == "TXSTA" 0463 || registerName == "SPBRG" 0464 || registerName == "EEDATA" 0465 || registerName == "EEADR" 0466 || registerName == "EECON1" 0467 || registerName == "EECON2" 0468 || registerName == "VRCON"/*bank1ends*/ ); 0469 0470 return false; 0471 } 0472 0473 //****************************modifications ends******************************************** 0474 0475 bool PIC14::isValidInterrupt( const QString & interruptName ) const 0476 { 0477 if(pic_type == "P16F84" ||pic_type =="P16C84"||pic_type =="P16F877"||pic_type=="P16F627"||pic_type=="P16F628") 0478 return ( interruptName == "change" || 0479 interruptName == "timer" || 0480 interruptName == "external" ); 0481 0482 return false; 0483 } 0484 0485 0486 void PIC14::setConditionalCode( Code * ifCode, Code * elseCode ) 0487 { 0488 m_ifCode = ifCode; 0489 m_elseCode = elseCode; 0490 } 0491 0492 void PIC14::Sgoto(const QString &label) 0493 { 0494 m_pCode->append( new Instr_goto(label) ); 0495 } 0496 0497 void PIC14::Slabel(const QString &label) 0498 { 0499 // std::cout << Q_FUNC_INFO << "label="<<label<<'\n'; 0500 m_pCode->queueLabel( label, Code::Middle ); 0501 } 0502 0503 void PIC14::Send() 0504 { 0505 m_pCode->append( new Instr_sleep() ); 0506 } 0507 0508 void PIC14::Ssubroutine( const QString &procName, Code * subCode ) 0509 { 0510 m_pCode->queueLabel( procName, Code::Subroutine ); 0511 m_pCode->merge( subCode, Code::Subroutine ); 0512 m_pCode->append( new Instr_return(), Code::Subroutine ); 0513 } 0514 0515 void PIC14::Sinterrupt( const QString &procName, Code * subCode ) 0516 { 0517 m_pCode->queueLabel( "_interrupt_" + procName, Code::Subroutine ); 0518 0519 // Clear the interrupt flag for this particular interrupt source 0520 m_pCode->append( new Instr_bcf("INTCON",QString::number(interruptNameToBit(procName,true))) ); 0521 m_pCode->merge( subCode, Code::Subroutine ); 0522 0523 m_pCode->append( new Instr_goto("_interrupt_end"), Code::Subroutine ); 0524 } 0525 0526 0527 void PIC14::Scall(const QString &name) 0528 { 0529 m_pCode->append( new Instr_call(name) ); 0530 } 0531 0532 0533 void PIC14::Ssetlh( const PortPin & portPin, bool high) 0534 { 0535 if(high) 0536 m_pCode->append( new Instr_bsf( portPin.port(),QString::number(portPin.pin()) ) ); 0537 else 0538 m_pCode->append( new Instr_bcf( portPin.port(), QString::number(portPin.pin()) ) ); 0539 } 0540 0541 void PIC14::rearrangeOpArguments( QString * val1, QString * val2, LocationType * val1Type, LocationType * val2Type) 0542 { 0543 if( *val2Type == work && *val1Type != work ) 0544 { 0545 LocationType tempType = *val2Type; 0546 QString tempVal = *val2; 0547 0548 *val2Type = *val1Type; 0549 *val2 = *val1; 0550 0551 *val1Type = tempType; 0552 *val1 = tempVal; 0553 } 0554 } 0555 0556 void PIC14::add( QString val1, QString val2, LocationType val1Type, LocationType val2Type ) 0557 { 0558 rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type ); 0559 0560 switch(val1Type) 0561 { 0562 case num: m_pCode->append(new Instr_movlw( val1.toInt( nullptr, 0 ) )); break; 0563 case work: break; 0564 case var: m_pCode->append(new Instr_movf(val1,0)); break; 0565 } 0566 0567 switch(val2Type) 0568 { 0569 case num: m_pCode->append(new Instr_addlw(val2.toInt( nullptr, 0 ))); break; 0570 case work: break; 0571 case var: m_pCode->append(new Instr_addwf(val2,0)); break; 0572 } 0573 } 0574 0575 void PIC14::subtract( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type ) 0576 { 0577 switch(val2Type) 0578 { 0579 case num: m_pCode->append(new Instr_movlw( val2.toInt( nullptr, 0 ) )); break; 0580 case work: break; 0581 case var: m_pCode->append(new Instr_movf(val2,0)); break; 0582 } 0583 switch(val1Type) 0584 { 0585 case num: m_pCode->append(new Instr_sublw(val1.toInt( nullptr, 0 ))); break; 0586 case work: break; 0587 case var: m_pCode->append(new Instr_subwf(val1,0)); break; 0588 } 0589 } 0590 0591 void PIC14::assignNum(const QString & val) 0592 { 0593 m_pCode->append(new Instr_movlw(val.toInt( nullptr, 0 ))); 0594 } 0595 0596 void PIC14::assignVar(const QString &val) 0597 { 0598 m_pCode->append(new Instr_movf(val,0)); 0599 } 0600 0601 void PIC14::saveToReg(const QString &dest) 0602 { 0603 m_pCode->append(new Instr_movwf(dest)); 0604 } 0605 0606 void PIC14::saveResultToVar( const QString & var ) 0607 { 0608 m_pCode->append( new Instr_movwf( var ) ); 0609 } 0610 0611 void PIC14::mul(QString val1, QString val2, LocationType val1Type, LocationType val2Type) 0612 { 0613 multiply(); 0614 0615 rearrangeOpArguments( &val1, &val2, &val1Type, &val2Type ); 0616 0617 // First, set _i argument 0618 switch(val1Type) 0619 { 0620 case num: m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); break; 0621 case work: break; 0622 case var: m_pCode->append(new Instr_movf(val1,0)); break; 0623 } 0624 0625 m_pCode->append(new Instr_movwf("__i")); 0626 0627 // Then set _j argument 0628 switch(val2Type) 0629 { 0630 case num: m_pCode->append(new Instr_movlw(val2.toInt( nullptr, 0 ))); break; 0631 case work: break; 0632 case var: m_pCode->append(new Instr_movf(val2,0)); break; 0633 } 0634 0635 m_pCode->append(new Instr_movwf("__j")); 0636 m_pCode->append(new Instr_call("__picfunc_multiply")); 0637 m_pCode->append(new Instr_movf("__result",0)); 0638 } 0639 0640 0641 void PIC14::multiply() 0642 { 0643 if ( m_pCode->instruction("__picfunc_multiply") ) 0644 return; 0645 0646 m_pCode->queueLabel( "__picfunc_multiply", Code::Subroutine ); 0647 m_pCode->append(new Instr_clrf("__result"), Code::Subroutine ); //result+=m_pCode->appenduction("clrf __result"); 0648 0649 m_pCode->queueLabel( "__picfunc_multiply_loop", Code::Subroutine ); 0650 m_pCode->append(new Instr_movf("__i",0), Code::Subroutine ); //result+=m_pCode->appenduction("movf __i,0"); 0651 m_pCode->append(new Instr_btfsc("__j","0"), Code::Subroutine ); //result+=m_pCode->appenduction("btfsc __j,0"); 0652 m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine ); //result+=m_pCode->appenduction("addwf __result,1"); 0653 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C"); 0654 m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("rrf __j,1"); 0655 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); //result+=m_pCode->appenduction("bcf STATUS,C"); 0656 m_pCode->append(new Instr_rlf("__i",1), Code::Subroutine ); //result+=m_pCode->appenduction("rlf __i,1"); 0657 m_pCode->append(new Instr_movf("__j",1), Code::Subroutine ); //result+=m_pCode->appenduction("movf __j,1"); 0658 m_pCode->append(new Instr_btfss("STATUS","Z"), Code::Subroutine ); //result+=m_pCode->appenduction("btfss STATUS,Z"); 0659 m_pCode->append(new Instr_goto("__picfunc_multiply_loop"), Code::Subroutine ); //result+=m_pCode->appenduction("goto __picfunc_multiply_loop"); 0660 m_pCode->append(new Instr_return(), Code::Subroutine ); //result+=m_pCode->appenduction("return"); 0661 } 0662 0663 0664 void PIC14::div( const QString & val1, const QString & val2, LocationType val1Type, LocationType val2Type) 0665 { 0666 divide(); 0667 0668 // NOO - "x / 2" is NOT the same as "2 / x" 0669 // rearrangeOpArguments( val1, val2, val1Type, val2Type ); 0670 0671 // First, set _i argument 0672 switch(val1Type) 0673 { 0674 case num: m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); break; 0675 case work: break; 0676 case var: m_pCode->append(new Instr_movf(val1,0)); break; 0677 } 0678 0679 m_pCode->append(new Instr_movwf("__i")); 0680 0681 // Then set _j argument 0682 switch(val2Type) 0683 { 0684 case num: m_pCode->append(new Instr_movlw(val2.toInt( nullptr, 0 ))); break; 0685 case work: break; 0686 case var: m_pCode->append(new Instr_movf(val2,0)); break; 0687 } 0688 0689 m_pCode->append(new Instr_movwf("__j")); 0690 0691 m_pCode->append(new Instr_call("__picfunc_divide"));//result+=instruction("call __picfunc_divide"); 0692 m_pCode->append(new Instr_movf("__result",0));//result+=instruction("movf __result,0"); 0693 } 0694 0695 void PIC14::divide() 0696 { 0697 m_pCode->queueLabel( "__picfunc_divide", Code::Subroutine ); 0698 m_pCode->append(new Instr_movf("__j",1), Code::Subroutine ); 0699 m_pCode->append(new Instr_btfsc("STATUS","2"), Code::Subroutine ); 0700 m_pCode->append(new Instr_return(), Code::Subroutine ); 0701 m_pCode->append(new Instr_clrf("__result"), Code::Subroutine ); 0702 m_pCode->append(new Instr_movlw(1), Code::Subroutine ); 0703 m_pCode->append(new Instr_movwf("__k"), Code::Subroutine ); 0704 0705 m_pCode->queueLabel( "__divide_shift", Code::Subroutine ); 0706 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); 0707 m_pCode->append(new Instr_rlf("__k",1), Code::Subroutine ); 0708 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); 0709 m_pCode->append(new Instr_rlf("__j",1), Code::Subroutine ); 0710 m_pCode->append(new Instr_btfss("__j","7"), Code::Subroutine ); 0711 m_pCode->append(new Instr_goto("__divide_shift"), Code::Subroutine ); 0712 0713 m_pCode->queueLabel( "__divide_loop", Code::Subroutine ); 0714 m_pCode->append(new Instr_movf("__j",0), Code::Subroutine ); 0715 m_pCode->append(new Instr_subwf("__i",1), Code::Subroutine ); 0716 m_pCode->append(new Instr_btfsc("STATUS","C"), Code::Subroutine ); 0717 m_pCode->append(new Instr_goto("__divide_count"), Code::Subroutine ); 0718 m_pCode->append(new Instr_addwf("__i",1), Code::Subroutine ); 0719 m_pCode->append(new Instr_goto("__divide_final"), Code::Subroutine ); 0720 0721 m_pCode->queueLabel( "__divide_count", Code::Subroutine ); 0722 m_pCode->append(new Instr_movf("__k",0), Code::Subroutine ); 0723 m_pCode->append(new Instr_addwf("__result",1), Code::Subroutine ); 0724 0725 m_pCode->queueLabel( "__divide_final", Code::Subroutine ); 0726 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); 0727 m_pCode->append(new Instr_rrf("__j",1), Code::Subroutine ); 0728 m_pCode->append(new Instr_bcf("STATUS","C"), Code::Subroutine ); 0729 m_pCode->append(new Instr_rrf("__k",1), Code::Subroutine ); 0730 m_pCode->append(new Instr_btfss("STATUS","C"), Code::Subroutine ); 0731 m_pCode->append(new Instr_goto("__divide_loop"), Code::Subroutine ); 0732 m_pCode->append(new Instr_return(), Code::Subroutine ); 0733 } 0734 0735 0736 Code * PIC14::ifCode() 0737 { 0738 return m_ifCode; 0739 } 0740 0741 0742 Code * PIC14::elseCode() 0743 { 0744 return m_elseCode; 0745 } 0746 0747 0748 void PIC14::ifInitCode( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0749 { 0750 // NOO - "x < 2" is NOT the same as "2 < x" 0751 // rearrangeOpArguments( val1, val2, val1Type, val2Type ); 0752 0753 switch(val1Type) 0754 { 0755 case num: 0756 m_pCode->append(new Instr_movlw(val1.toInt( nullptr, 0 ))); 0757 break; 0758 0759 case work: 0760 break; // Nothing to do 0761 0762 case var: 0763 m_pCode->append(new Instr_movf(val1,0)); 0764 break; 0765 } 0766 0767 switch(val2Type) 0768 { 0769 case num: 0770 m_pCode->append(new Instr_sublw(val2.toInt( nullptr, 0 ))); 0771 break; 0772 0773 case work: 0774 qCritical() << Q_FUNC_INFO << "Cannot subtract working from working!"; 0775 break; 0776 0777 case var: 0778 m_pCode->append(new Instr_subwf(val2,0)); 0779 break; 0780 } 0781 } 0782 0783 void PIC14::equal( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0784 { 0785 ifInitCode( val1, val2, val1Type, val2Type ); 0786 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0787 const QString labelFalse = mb->uniqueLabel()+"_case_false"; 0788 0789 m_pCode->append(new Instr_btfss("STATUS","2")); 0790 m_pCode->append(new Instr_goto(labelFalse)); 0791 0792 mergeCode( ifCode() ); 0793 0794 m_pCode->append(new Instr_goto(labelEnd)); 0795 0796 m_pCode->queueLabel( labelFalse ); 0797 mergeCode( elseCode() ); 0798 m_pCode->queueLabel( labelEnd ); 0799 } 0800 0801 void PIC14::notEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0802 { 0803 ifInitCode( val1, val2, val1Type, val2Type ); 0804 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0805 const QString labelFalse = mb->uniqueLabel()+"_case_false"; 0806 0807 m_pCode->append(new Instr_btfsc("STATUS","2")); 0808 m_pCode->append(new Instr_goto(labelFalse)); 0809 0810 mergeCode( ifCode() ); 0811 0812 m_pCode->append(new Instr_goto(labelEnd)); 0813 0814 m_pCode->queueLabel( labelFalse ); 0815 mergeCode( elseCode() ); 0816 m_pCode->queueLabel( labelEnd ); 0817 } 0818 0819 void PIC14::greaterThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0820 { 0821 ifInitCode( val1, val2, val1Type, val2Type ); 0822 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0823 const QString labelFalse = mb->uniqueLabel()+"_case_false"; 0824 0825 m_pCode->append(new Instr_btfsc("STATUS","0")); 0826 m_pCode->append(new Instr_goto(labelFalse)); 0827 0828 mergeCode( ifCode() ); 0829 m_pCode->append(new Instr_goto(labelEnd)); 0830 0831 m_pCode->queueLabel( labelFalse ); 0832 mergeCode( elseCode() ); 0833 m_pCode->queueLabel( labelEnd ); 0834 } 0835 0836 void PIC14::lessThan( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0837 { 0838 cout << Q_FUNC_INFO << endl; 0839 ifInitCode( val1, val2, val1Type, val2Type ); 0840 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0841 const QString labelFalse = mb->uniqueLabel()+"_case_false"; 0842 0843 m_pCode->append(new Instr_btfss("STATUS","0")); 0844 m_pCode->append(new Instr_goto(labelFalse)); 0845 m_pCode->append(new Instr_btfsc("STATUS","2")); 0846 m_pCode->append(new Instr_goto(labelFalse)); 0847 0848 mergeCode( ifCode() ); 0849 0850 m_pCode->append(new Instr_goto(labelEnd)); 0851 0852 m_pCode->queueLabel( labelFalse ); 0853 mergeCode( elseCode() ); 0854 m_pCode->queueLabel( labelEnd ); 0855 } 0856 0857 void PIC14::greaterOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0858 { 0859 ifInitCode( val1, val2, val1Type, val2Type ); 0860 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0861 const QString labelTrue = mb->uniqueLabel()+"_case_true"; // Note that unlike the others, this is labelTrue, not labelFalse 0862 0863 m_pCode->append(new Instr_btfsc("STATUS","2")); 0864 m_pCode->append(new Instr_goto(labelTrue)); 0865 m_pCode->append(new Instr_btfss("STATUS","0")); 0866 m_pCode->append(new Instr_goto(labelTrue)); 0867 0868 mergeCode( elseCode() ); 0869 0870 m_pCode->append(new Instr_goto(labelEnd)); 0871 0872 m_pCode->queueLabel( labelTrue ); 0873 mergeCode( ifCode() ); 0874 m_pCode->queueLabel( labelEnd ); 0875 } 0876 0877 void PIC14::lessOrEqual( const QString &val1, const QString &val2, LocationType val1Type, LocationType val2Type ) 0878 { 0879 ifInitCode( val1, val2, val1Type, val2Type ); 0880 const QString labelEnd = mb->uniqueLabel()+"_endif"; 0881 const QString labelFalse = mb->uniqueLabel()+"_case_false"; 0882 0883 m_pCode->append(new Instr_btfss("STATUS","0")); 0884 m_pCode->append(new Instr_goto(labelFalse)); 0885 0886 mergeCode( ifCode() ); 0887 m_pCode->append(new Instr_goto(labelEnd)); 0888 0889 m_pCode->queueLabel( labelFalse ); 0890 mergeCode( elseCode() ); 0891 m_pCode->queueLabel( labelEnd ); 0892 } 0893 0894 0895 void PIC14::Swhile( Code * whileCode, const QString &expression) 0896 { 0897 QString result; 0898 QString ul = mb->uniqueLabel(); 0899 0900 whileCode->append( new Instr_goto(ul) ); 0901 0902 m_pCode->queueLabel( ul, Code::Middle ); 0903 0904 // If the condition is not true, just fall through 0905 m_parser->compileConditionalExpression( expression, whileCode, nullptr ); 0906 } 0907 0908 0909 void PIC14::Srepeat( Code * repeatCode, const QString &expression) 0910 { 0911 QString result; 0912 QString ul = mb->uniqueLabel(); 0913 0914 Code * elseCode = new Code; 0915 elseCode->append( new Instr_goto(ul) ); 0916 0917 m_pCode->queueLabel( ul ); 0918 m_pCode->merge( repeatCode ); 0919 0920 // If the condition is true, just fall through 0921 m_parser->compileConditionalExpression( expression, nullptr, elseCode ); 0922 } 0923 0924 void PIC14::Sif( Code * ifCode, Code * elseCode, const QString &expression) 0925 { 0926 m_parser->compileConditionalExpression( expression, ifCode, elseCode ); 0927 } 0928 0929 0930 void PIC14::Sfor( Code * forCode, Code * initCode, const QString &expression, const QString &variable, const QString &step, bool stepPositive) 0931 { 0932 QString ul = mb->uniqueLabel(); 0933 0934 if ( step == "1" ) 0935 { 0936 if (stepPositive) 0937 forCode->append(new Instr_incf(variable,1)); 0938 else 0939 forCode->append(new Instr_decf(variable,1)); 0940 } 0941 else 0942 { 0943 forCode->append(new Instr_movlw(step.toInt( nullptr, 0 ))); 0944 if (stepPositive) 0945 forCode->append(new Instr_addwf(variable,1)); 0946 else 0947 forCode->append(new Instr_subwf(variable,1)); 0948 } 0949 forCode->append(new Instr_goto(ul)); 0950 0951 m_pCode->merge( initCode ); 0952 0953 m_pCode->queueLabel( ul ); 0954 0955 m_parser->compileConditionalExpression( expression, forCode, nullptr ); 0956 } 0957 0958 0959 void PIC14::Spin( const PortPin & portPin, bool NOT) 0960 { 0961 QString lowLabel, highLabel, postLabel; 0962 lowLabel = mb->uniqueLabel(); 0963 highLabel = mb->uniqueLabel(); 0964 postLabel = mb->uniqueLabel(); 0965 /*result += indent + "goto\t" + lowLabel; 0966 result += indent + "movlw\t1" + "goto\t"+postLabel+; 0967 result += lowLabel + + indent + "movlw\t0" + indent; 0968 result += postLabel + ;*/ 0969 0970 if(NOT) 0971 m_pCode->append(new Instr_btfsc( portPin.port(), QString::number( portPin.pin() ) )); 0972 //result +=instruction((QString)(NOT?"btfsc":"btfss")+"\t"+port+","+pin); 0973 else 0974 m_pCode->append(new Instr_btfss( portPin.port(), QString::number( portPin.pin() ) )); 0975 0976 m_pCode->append(new Instr_goto(lowLabel));//result += instruction("goto\t" + lowLabel); 0977 mergeCode( ifCode() ); 0978 m_pCode->append(new Instr_goto(postLabel));//result += instruction("goto\t"+postLabel); 0979 0980 m_pCode->queueLabel( lowLabel ); 0981 mergeCode( elseCode() ); 0982 0983 m_pCode->queueLabel( postLabel ); 0984 } 0985 0986 0987 void PIC14::Sdelay( unsigned length_us, Code::InstructionPosition pos ) 0988 { 0989 if ( length_us == 0 ) 0990 return; 0991 0992 if ( length_us > 50070524 ) 0993 { 0994 length_us += 50267642; 0995 int l = length_us/50070530; 0996 length_us -= l * 50070530; 0997 int k = length_us/196355; 0998 0999 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 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 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 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***************************/ 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***************************** 1373 void PIC14::SincVar( const QString &var ) 1374 { 1375 m_pCode->append(new Instr_incf(var,1) ); 1376 } 1377 1378 void PIC14::SdecVar( const QString &var ) 1379 { 1380 m_pCode->append(new Instr_decf(var,1) ); 1381 } 1382 1383 void PIC14::SrotlVar( const QString &var ) 1384 { 1385 m_pCode->append(new Instr_rlf(var,1)); 1386 } 1387 1388 void PIC14::SrotrVar( const QString &var ) 1389 { 1390 m_pCode->append(new Instr_rrf(var,1)); 1391 } 1392 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 1419 void PIC14::Sasm(const QString &raw) 1420 { 1421 m_pCode->append(new Instr_asm(raw)); 1422 } 1423 1424 //BEGIN class PortPin 1425 PortPin::PortPin( const QString & port, int pin ) 1426 { 1427 m_port = port.toUpper(); 1428 m_pin = pin; 1429 } 1430 1431 1432 PortPin::PortPin() 1433 { 1434 m_port = ' '; 1435 m_pin = -1; 1436 } 1437 1438 1439 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