mirror of
				https://github.com/Oleg-Stepanenko-owo/IEBUS
				synced 2025-10-30 18:07:11 +00:00 
			
		
		
		
	Added loger + update logic
This commit is contained in:
		
							parent
							
								
									406d68ab92
								
							
						
					
					
						commit
						87b9851a29
					
				| @ -570,8 +570,6 @@ void AVCLanDrv::printMessage(bool incoming) | |||||||
| byte AVCLanDrv::getActionID(const AvcInCmdTable messageTable[], byte mtSize) | byte AVCLanDrv::getActionID(const AvcInCmdTable messageTable[], byte mtSize) | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| { | { | ||||||
|   // Serial.print( "="); Serial.println( pgm_read_byte_near(&messageTable[msg].prefix[i]) );
 |  | ||||||
| 
 |  | ||||||
|   if ( ((slaveAddress != deviceAddress) && (slaveAddress != 0x0FFF)) |   if ( ((slaveAddress != deviceAddress) && (slaveAddress != 0x0FFF)) | ||||||
|        || (( dataSize < 8) || (dataSize > 10 )) ) { |        || (( dataSize < 8) || (dataSize > 10 )) ) { | ||||||
|     return ACT_NONE; |     return ACT_NONE; | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
|  | #include "limits.h" | ||||||
| #include <EEPROM.h> | #include <EEPROM.h> | ||||||
| #include "AVCLanDrv.h" | #include "AVCLanDrv.h" | ||||||
| #include "AVCLanHonda.h" | #include "AVCLanHonda.h" | ||||||
| @ -62,9 +63,9 @@ void AVCLanHonda::begin() | |||||||
|   bShowHondaDisp = false; |   bShowHondaDisp = false; | ||||||
|   isHondaDisLast = false; |   isHondaDisLast = false; | ||||||
|   bShowRearCam =  false; |   bShowRearCam =  false; | ||||||
|  |   bFirstStart_20 = true; | ||||||
| 
 | 
 | ||||||
|   setWaitTime( 0L ); |   setWaitTime( 0L ); | ||||||
|   setLockTime( 0L ); |  | ||||||
| 
 | 
 | ||||||
|   // timer1 setup, prescaler factor - 1024
 |   // timer1 setup, prescaler factor - 1024
 | ||||||
|   TCCR1A = 0;       // normal mode
 |   TCCR1A = 0;       // normal mode
 | ||||||
| @ -86,14 +87,14 @@ void AVCLanHonda::setWaitTime( const unsigned long mTime ) | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //--------------------------------------------------------------------------------
 | ////--------------------------------------------------------------------------------
 | ||||||
| void AVCLanHonda::setLockTime( const unsigned long mTime ) | //void AVCLanHonda::setLockTime( const unsigned long mTime )
 | ||||||
| //--------------------------------------------------------------------------------
 | ////--------------------------------------------------------------------------------
 | ||||||
| { | //{
 | ||||||
|   lockTime = mTime; | //  lockTime = mTime;
 | ||||||
|   bLock = true; | //  bLock = true;
 | ||||||
|   setWaitTime(0L); | //  setWaitTime(0L);
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
| // Use the last received message to determine the corresponding action ID, store it in avclan object
 | // Use the last received message to determine the corresponding action ID, store it in avclan object
 | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| @ -105,24 +106,26 @@ void AVCLanHonda::getActionID() | |||||||
| 
 | 
 | ||||||
| // process action
 | // process action
 | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| void AVCLanHonda::processAction(AvcActionID ActionID) | void AVCLanHonda::processAction( AvcActionID ActionID ) | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| { | { | ||||||
|   if ( (20000 > millis()) && (ACT_CAM_ON == ActionID) ) { |   if ( bFirstStart_20 && (20000 > millis()) && (ACT_CAM_ON == ActionID) ) { | ||||||
|     bShowRearCam = true; |     bShowRearCam = true; | ||||||
|     isHondaDisLast = false; |     isHondaDisLast = false; | ||||||
|     bShowHondaDisp = true; |     bShowHondaDisp = true; | ||||||
|     printAvcAction(ActionID); |  | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if ( bFirstStart_20 && (20000 < millis()) ) bFirstStart_20 = false; | ||||||
|  | 
 | ||||||
|   switch ( ActionID ) { |   switch ( ActionID ) { | ||||||
|     case ACT_BUTTON_PRESS: |     case ACT_BUTTON_PRESS: | ||||||
|       { |       { | ||||||
|         printAvcAction(ActionID); |         if ( !bShowRearCam || !isWait() ) | ||||||
|         if ( !bShowRearCam || !isWait() || !isLockTime() ) |  | ||||||
|         { |         { | ||||||
|  |           if ( ULONG_MAX > (millis() + BUTT_WAIT) ) | ||||||
|             setWaitTime( (unsigned long)((millis() + BUTT_WAIT)) ); |             setWaitTime( (unsigned long)((millis() + BUTT_WAIT)) ); | ||||||
|  |           else setWaitTime( BUTT_WAIT ); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
| @ -130,23 +133,25 @@ void AVCLanHonda::processAction(AvcActionID ActionID) | |||||||
|       bShowRearCam = true; |       bShowRearCam = true; | ||||||
|       isHondaDisLast = isShowHondaDisp(); |       isHondaDisLast = isShowHondaDisp(); | ||||||
|       bShowHondaDisp = true; |       bShowHondaDisp = true; | ||||||
|       printAvcAction(ActionID); |       setWaitTime(0L); | ||||||
|       setLockTime( (unsigned long)(millis() + LOCK_TIME) ); |       //      setLockTime( (unsigned long)(millis() + LOCK_TIME) );
 | ||||||
|       break; |       break; | ||||||
|     case ACT_DISP_OFF: |     case ACT_DISP_OFF: | ||||||
|       if ( !bShowRearCam ) |       if ( !bShowRearCam ) | ||||||
|       { |       { | ||||||
|         bShowHondaDisp = false; |         bShowHondaDisp = false; | ||||||
|         isHondaDisLast = false; |         isHondaDisLast = false; | ||||||
|         printAvcAction(ActionID); |         setWaitTime(0L); | ||||||
|         setLockTime( (unsigned long)(millis() + LOCK_TIME) ); |         //        printAvcAction(ActionID);
 | ||||||
|  |         //        setLockTime( (unsigned long)(millis() + LOCK_TIME) );
 | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     case ACT_CAM_OFF: |     case ACT_CAM_OFF: | ||||||
|       bShowRearCam = false; |       bShowRearCam = false; | ||||||
|       bShowHondaDisp = isHondaDisLast; |       bShowHondaDisp = isHondaDisLast; | ||||||
|       printAvcAction(ActionID); |       setWaitTime(0L); | ||||||
|       setLockTime( (unsigned long)(millis() + LOCK_TIME) ); |       //      printAvcAction(ActionID);
 | ||||||
|  |       //      setLockTime( (unsigned long)(millis() + LOCK_TIME) );
 | ||||||
|       break; |       break; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| @ -171,8 +176,7 @@ bool AVCLanHonda::getCommute() | |||||||
| void AVCLanHonda::tryToShowHondaDisp() | void AVCLanHonda::tryToShowHondaDisp() | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| { | { | ||||||
|   bWait = false; |   //  if ( isLockTime() ) return;
 | ||||||
|   if ( isLockTime() ) return; |  | ||||||
|   bShowHondaDisp = true; |   bShowHondaDisp = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -184,15 +188,15 @@ void AVCLanHonda::falseHondaDis() | |||||||
|   isHondaDisLast = false; |   isHondaDisLast = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //--------------------------------------------------------------------------------
 | ////--------------------------------------------------------------------------------
 | ||||||
| bool AVCLanHonda::isLockTime() | //bool AVCLanHonda::isLockTime()
 | ||||||
| //--------------------------------------------------------------------------------
 | ////--------------------------------------------------------------------------------
 | ||||||
| { | //{
 | ||||||
|   if ( bLock ) { | //  if ( bLock ) {
 | ||||||
|     bLock = ( getLockTime() > millis() ); | //    bLock = ( getLockTime() > millis() );
 | ||||||
|   } | //  }
 | ||||||
|   return bLock; | //  return bLock;
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
| AVCLanHonda avclanHonda; | AVCLanHonda avclanHonda; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ | |||||||
| #define DISABLE_TIMER1_INT (cbi(TIMSK1, TOIE1)); | #define DISABLE_TIMER1_INT (cbi(TIMSK1, TOIE1)); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // адреса eeprom
 | // Р°РТвЂ<EFBFBD>реса eeprom
 | ||||||
| #define E_MASTER1       0 | #define E_MASTER1       0 | ||||||
| #define E_MASTER2       1 | #define E_MASTER2       1 | ||||||
| #define E_READONLY      2 | #define E_READONLY      2 | ||||||
| @ -66,9 +66,9 @@ class AVCLanHonda | |||||||
|     void setWaitTime( const unsigned long mTime ); |     void setWaitTime( const unsigned long mTime ); | ||||||
|     inline unsigned long getWaitTime() const; |     inline unsigned long getWaitTime() const; | ||||||
| 
 | 
 | ||||||
|     void setLockTime( const unsigned long mTime ); |     //    void setLockTime( const unsigned long mTime );
 | ||||||
|     inline unsigned long getLockTime() const; |     //    inline unsigned long getLockTime() const;
 | ||||||
|     bool isLockTime(); |     //    bool isLockTime();
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     inline bool isWait() const; |     inline bool isWait() const; | ||||||
| @ -80,10 +80,11 @@ class AVCLanHonda | |||||||
|     void checkLock(); |     void checkLock(); | ||||||
|     void falseHondaDis(); |     void falseHondaDis(); | ||||||
| 
 | 
 | ||||||
|  |     bool bFirstStart_20; | ||||||
| 
 | 
 | ||||||
|   private: |   private: | ||||||
|     unsigned long waitTime; |     unsigned long waitTime; | ||||||
|     unsigned long lockTime; |     //    unsigned long lockTime;
 | ||||||
| 
 | 
 | ||||||
|     bool bWait; |     bool bWait; | ||||||
|     bool bLock; |     bool bLock; | ||||||
| @ -94,9 +95,9 @@ class AVCLanHonda | |||||||
|     bool isHondaDisLast; |     bool isHondaDisLast; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| unsigned long AVCLanHonda::getLockTime() const { | //unsigned long AVCLanHonda::getLockTime() const {
 | ||||||
|   return lockTime; | //  return lockTime;
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
| unsigned long AVCLanHonda::getWaitTime() const { | unsigned long AVCLanHonda::getWaitTime() const { | ||||||
|   return waitTime; |   return waitTime; | ||||||
|  | |||||||
| @ -42,14 +42,41 @@ void setup() | |||||||
| void loop() | void loop() | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
| { | { | ||||||
|   if ( avclanHonda.isShowRearCam() ) { | 
 | ||||||
|     HONDA_DIS_ON; |   if ( avclanHonda.bFirstStart_20 && (11500 > millis()) ) { | ||||||
|  |     HONDA_DIS_ON;  // initalize
 | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if ( INPUT_IS_SET ) { | ||||||
|  |     byte res = avclan.readMessage(); | ||||||
|  |     if ( !res ) { | ||||||
|  |       avclanHonda.getActionID(); | ||||||
|  |       if ( avclan.actionID != ACT_NONE ) { | ||||||
|  |         avclanHonda.processAction( (AvcActionID)avclan.actionID ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   if ( avclanHonda.isWait() ) { | ||||||
|  |     avclanHonda.checkWait(); | ||||||
|  |     if ( !avclanHonda.isWait() ) avclanHonda.tryToShowHondaDisp(); | ||||||
|  |   } else { | ||||||
|  |     if ( avclanHonda.getCommute() ) { | ||||||
|  |       HONDA_DIS_ON; | ||||||
|  |     } else { | ||||||
|  |       HONDA_DIS_OFF; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   //-------------------------------
 | ||||||
|  | 
 | ||||||
|  |   /*
 | ||||||
|  | 
 | ||||||
|     if ( !avclanHonda.isLockTime() ) |     if ( !avclanHonda.isLockTime() ) | ||||||
|     { |     { | ||||||
| 
 |  | ||||||
|       if ( avclanHonda.isWait() ) { |       if ( avclanHonda.isWait() ) { | ||||||
|         avclanHonda.checkWait(); |         avclanHonda.checkWait(); | ||||||
|         if (avclanHonda.isWait() == false) |         if (avclanHonda.isWait() == false) | ||||||
| @ -89,6 +116,8 @@ void loop() | |||||||
|         HONDA_DIS_OFF; |         HONDA_DIS_OFF; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |   */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //--------------------------------------------------------------------------------
 | //--------------------------------------------------------------------------------
 | ||||||
|  | |||||||
							
								
								
									
										578
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLanDrv.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										578
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLanDrv.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,578 @@ | |||||||
|  | #include "AVCLanDrv.h" | ||||||
|  | #include "BuffSerial.h" | ||||||
|  | 
 | ||||||
|  | // AVCLan driver & timer2 init,
 | ||||||
|  | // char buff[80] = {0};
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | void AVCLanDrv::begin () | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   // AVCLan TX+/TX- 	read line INPUT
 | ||||||
|  |   cbi(DATAIN_DDR,  DATAIN); | ||||||
|  | #ifdef AVCLAN_ST485 | ||||||
|  |   sbi(DATAIN_PORT, DATAIN); | ||||||
|  | #else | ||||||
|  |   cbi(DATAIN_PORT, DATAIN); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   // AVCLan TX+/TX-		write line OUTPUT
 | ||||||
|  | #ifdef AVCLAN_RESISTOR | ||||||
|  |   cbi(DATAOUT_DDR,  DATAOUT); | ||||||
|  |   cbi(DATAOUT_PORT, DATAOUT); | ||||||
|  |   cbi(ADCSRB, ACME);	// Analog Comparator Multiplexer Enable - NO
 | ||||||
|  |   cbi(ACSR, ACIS1);	  // Analog Comparator Interrupt Mode Select
 | ||||||
|  |   cbi(ACSR, ACIS0);   // Comparator Interrupt on Output Toggle
 | ||||||
|  |   cbi(ACSR, ACD); 	  // Analog Comparator Disbale - NO
 | ||||||
|  | #else | ||||||
|  | #ifdef AVCLAN_ST485 | ||||||
|  |   sbi(DATAOUT_DDR,  DATAOUT); | ||||||
|  |   sbi(OUTEN_DDR,  OUTEN); | ||||||
|  |   AVC_OUT_DIS; | ||||||
|  |   OUTPUT_SET_0; | ||||||
|  | #else | ||||||
|  |   //avclan driver on PCA82C250 & LM239N
 | ||||||
|  |   sbi(DATAOUT_DDR,  DATAOUT); | ||||||
|  |   AVC_OUT_DIS; | ||||||
|  |   OUTPUT_SET_0; | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   // timer2 setup, prescaler factor - 8
 | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |   //  ASSR=0x00;
 | ||||||
|  |   TCCR2 = 0x02; | ||||||
|  |   //  TCNT2=0x00;
 | ||||||
|  |   //  OCR2=0x00;
 | ||||||
|  | #else   // ATMega168
 | ||||||
|  |   //  ASSR=0x00;
 | ||||||
|  |   //  TCCR2A=0x00;
 | ||||||
|  |   TCCR2B = 0x02; | ||||||
|  |   //  TCNT2=0x00;
 | ||||||
|  |   //  OCR2A=0x00;
 | ||||||
|  |   //  OCR2B=0x00;
 | ||||||
|  | #endif | ||||||
|  |   headAddress   = 0x0000; | ||||||
|  |   deviceAddress = 0x0000; | ||||||
|  |   //  event         = EV_NONE;
 | ||||||
|  |   actionID      = ACT_NONE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Reads specified number of bits from the AVCLan.
 | ||||||
|  | // nbBits (byte) -> Number of bits to read.
 | ||||||
|  | // Return (word) -> Data value read.
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | word AVCLanDrv::readBits (byte nbBits) | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   word data  = 0; | ||||||
|  |   _parityBit = 0; | ||||||
|  | 
 | ||||||
|  |   while (nbBits-- > 0) { | ||||||
|  |     // Insert new bit
 | ||||||
|  |     data <<= 1; | ||||||
|  |     // Wait until rising edge of new bit.
 | ||||||
|  |     while (INPUT_IS_CLEAR) { | ||||||
|  |       // Reset watchdog.
 | ||||||
|  |       //wdt_reset();
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Reset timer to measure bit length.
 | ||||||
|  |     TCNT2 = 0; | ||||||
|  |     // Wait until falling edge.
 | ||||||
|  |     while (INPUT_IS_SET); | ||||||
|  |     // Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us
 | ||||||
|  |     if (TCNT2 < AVC_BIT_0_HOLD_ON_MIN_LENGTH) { | ||||||
|  |       // Set new bit.
 | ||||||
|  |       data |= 0x0001; | ||||||
|  |       // Adjust parity.
 | ||||||
|  |       _parityBit = !_parityBit; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   while (INPUT_IS_CLEAR && TCNT2 < AVC_NORMAL_BIT_LENGTH); | ||||||
|  | 
 | ||||||
|  |   //  char buff[10] = {0};
 | ||||||
|  |   //  sprintf(buff, "%x", data );
 | ||||||
|  |   //  // bSDLog.logs( buff );
 | ||||||
|  |   return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Read incoming messages on the AVCLan.
 | ||||||
|  | // Return 0 if success.
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | byte AVCLanDrv::_readMessage () | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   uint8_t t = 0; | ||||||
|  |   uint8_t oldSREG = SREG; | ||||||
|  |   cli();             // disable interrupts
 | ||||||
|  | 
 | ||||||
|  |   // Start bit.
 | ||||||
|  |   while (INPUT_IS_CLEAR); | ||||||
|  |   TCCR2B = 0x03;    // prescaler 32
 | ||||||
|  |   TCNT2 = 0; | ||||||
|  |   // Wait until falling edge.
 | ||||||
|  |   while (INPUT_IS_SET) { | ||||||
|  |     t = TCNT2; | ||||||
|  |     if (t > 0xFF) { | ||||||
|  |       TCCR2B = 0x02;    // prescaler 8
 | ||||||
|  |       SREG = oldSREG; | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   TCCR2B = 0x02;    // prescaler 8
 | ||||||
|  | 
 | ||||||
|  |   if (t < AVC_START_BIT_HOLD_ON_MIN_LENGTH) { | ||||||
|  |     //if (t < 0x16){
 | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   broadcast = readBits(1); | ||||||
|  | 
 | ||||||
|  |   masterAddress = readBits(12); | ||||||
|  |   bool p = _parityBit; | ||||||
|  |   if (p != readBits(1)) { | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 3; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   slaveAddress = readBits(12); | ||||||
|  |   p = _parityBit; | ||||||
|  |   if (p != readBits(1)) { | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 4; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool forMe = ( slaveAddress == deviceAddress ); | ||||||
|  | 
 | ||||||
|  |   if (forMe) { | ||||||
|  |     // Send ACK.
 | ||||||
|  |     AVC_OUT_EN; | ||||||
|  |     send1BitWord(0); | ||||||
|  |     AVC_OUT_DIS; | ||||||
|  |   } else { | ||||||
|  |     readBits(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Control
 | ||||||
|  |   readBits(4); | ||||||
|  |   p = _parityBit; | ||||||
|  |   if (p != readBits(1)) { | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 5; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (forMe) { | ||||||
|  |     // Send ACK.
 | ||||||
|  |     AVC_OUT_EN; | ||||||
|  |     send1BitWord(0); | ||||||
|  |     AVC_OUT_DIS; | ||||||
|  |   } else { | ||||||
|  |     readBits(1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   dataSize = readBits(8); | ||||||
|  |   p = _parityBit; | ||||||
|  |   if (p != readBits(1)) { | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 6; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (forMe) { | ||||||
|  |     // Send ACK.
 | ||||||
|  |     AVC_OUT_EN; | ||||||
|  |     send1BitWord(0); | ||||||
|  |     AVC_OUT_DIS; | ||||||
|  |   } else { | ||||||
|  |     readBits(1); | ||||||
|  |   } | ||||||
|  |   if (dataSize > AVC_MAXMSGLEN) { | ||||||
|  |     SREG = oldSREG; | ||||||
|  |     return 7; | ||||||
|  |   } | ||||||
|  |   byte i; | ||||||
|  |   for (i = 0; i < dataSize; i++ ) { | ||||||
|  |     message[i] = readBits(8); | ||||||
|  |     p = _parityBit; | ||||||
|  |     if (p != readBits(1)) { | ||||||
|  |       SREG = oldSREG; | ||||||
|  |       return 8; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (forMe) { | ||||||
|  |       // Send ACK.
 | ||||||
|  |       AVC_OUT_EN; | ||||||
|  |       send1BitWord(0); | ||||||
|  |       AVC_OUT_DIS; | ||||||
|  |     } else { | ||||||
|  |       readBits(1); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   SREG = oldSREG; | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Read incoming messages on the AVCLan, log message through serial port
 | ||||||
|  | // Return true if success.
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | byte AVCLanDrv::readMessage () | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   byte res = avclan._readMessage(); | ||||||
|  |   if (res) | ||||||
|  |   { | ||||||
|  |     while (!avclan.isAvcBusFree()); | ||||||
|  |   } | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Send a start bit to the AVCLan
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void AVCLanDrv::sendStartBit ()
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  // Reset timer to measure bit length.
 | ||||||
|  | //  TCCR2B = 0x03;    // prescaler 32
 | ||||||
|  | //  TCNT2 = 0;
 | ||||||
|  | //  OUTPUT_SET_1;
 | ||||||
|  | //
 | ||||||
|  | //  // Pulse level high duration.
 | ||||||
|  | //  while ( TCNT2 < AVC_START_BIT_HOLD_ON_LENGTH );
 | ||||||
|  | //  OUTPUT_SET_0;
 | ||||||
|  | //
 | ||||||
|  | //  // Pulse level low duration until ~185 us.
 | ||||||
|  | //  while ( TCNT2 < AVC_START_BIT_LENGTH );
 | ||||||
|  | //  TCCR2B = 0x02;    // prescaler 8
 | ||||||
|  | //
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | // Send a 1 bit word to the AVCLan
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | void AVCLanDrv::send1BitWord (bool data) | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   // Reset timer to measure bit length.
 | ||||||
|  |   TCNT2 = 0; | ||||||
|  |   OUTPUT_SET_1; | ||||||
|  | 
 | ||||||
|  |   if (data) { | ||||||
|  |     while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH); | ||||||
|  |   } else { | ||||||
|  |     while (TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   OUTPUT_SET_0; | ||||||
|  |   while (TCNT2 <  AVC_NORMAL_BIT_LENGTH); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //// Send a 4 bit word to the AVCLan
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void AVCLanDrv::send4BitWord (byte data)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  _parityBit = 0;
 | ||||||
|  | //
 | ||||||
|  | //  // Most significant bit out first.
 | ||||||
|  | //  for ( char nbBits = 0; nbBits < 4; nbBits++ ) {
 | ||||||
|  | //    // Reset timer to measure bit length.
 | ||||||
|  | //    TCNT2 = 2;
 | ||||||
|  | //    OUTPUT_SET_1;
 | ||||||
|  | //
 | ||||||
|  | //    if (data & 0x8) {
 | ||||||
|  | //      // Adjust parity.
 | ||||||
|  | //      _parityBit = ! _parityBit;
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH );
 | ||||||
|  | //    } else {
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH );
 | ||||||
|  | //    }
 | ||||||
|  | //
 | ||||||
|  | //    OUTPUT_SET_0;
 | ||||||
|  | //    // Hold output low until end of bit.
 | ||||||
|  | //    while ( TCNT2 < AVC_NORMAL_BIT_LENGTH );
 | ||||||
|  | //
 | ||||||
|  | //    // Fetch next bit.
 | ||||||
|  | //    data <<= 1;
 | ||||||
|  | //  }
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | //// Send a 8 bit word to the AVCLan
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void AVCLanDrv::send8BitWord (byte data)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  _parityBit = 0;
 | ||||||
|  | //
 | ||||||
|  | //  // Most significant bit out first.
 | ||||||
|  | //  for ( char nbBits = 0; nbBits < 8; nbBits++ ) {
 | ||||||
|  | //    // Reset timer to measure bit length.
 | ||||||
|  | //    TCNT2 = 2;
 | ||||||
|  | //    OUTPUT_SET_1;
 | ||||||
|  | //
 | ||||||
|  | //    if (data & 0x80) {
 | ||||||
|  | //      // Adjust parity.
 | ||||||
|  | //      _parityBit = ! _parityBit;
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH );
 | ||||||
|  | //    } else {
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH );
 | ||||||
|  | //    }
 | ||||||
|  | //
 | ||||||
|  | //    OUTPUT_SET_0;
 | ||||||
|  | //    // Hold output low until end of bit.
 | ||||||
|  | //    while ( TCNT2 < AVC_NORMAL_BIT_LENGTH );
 | ||||||
|  | //
 | ||||||
|  | //    // Fetch next bit.
 | ||||||
|  | //    data <<= 1;
 | ||||||
|  | //  }
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | //// Send a 12 bit word to the AVCLan
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void AVCLanDrv::send12BitWord (word data)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  _parityBit = 0;
 | ||||||
|  | //
 | ||||||
|  | //  // Most significant bit out first.
 | ||||||
|  | //  for ( char nbBits = 0; nbBits < 12; nbBits++ ) {
 | ||||||
|  | //    // Reset timer to measure bit length.
 | ||||||
|  | //    TCNT2 = 2;
 | ||||||
|  | //    OUTPUT_SET_1;
 | ||||||
|  | //
 | ||||||
|  | //    if (data & 0x0800) {
 | ||||||
|  | //      // Adjust parity.
 | ||||||
|  | //      _parityBit = ! _parityBit;
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH );
 | ||||||
|  | //    } else {
 | ||||||
|  | //      while ( TCNT2 < AVC_BIT_0_HOLD_ON_LENGTH );
 | ||||||
|  | //    }
 | ||||||
|  | //
 | ||||||
|  | //    OUTPUT_SET_0;
 | ||||||
|  | //    // Hold output low until end of bit.
 | ||||||
|  | //    while ( TCNT2 < AVC_NORMAL_BIT_LENGTH );
 | ||||||
|  | //
 | ||||||
|  | //    // Fetch next bit.
 | ||||||
|  | //    data <<= 1;
 | ||||||
|  | //  }
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | //  determine whether the bus is free (no tx/rx).
 | ||||||
|  | //  return TRUE is bus is free.
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | bool AVCLanDrv::isAvcBusFree (void) | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   // Reset timer.
 | ||||||
|  |   TCNT2 = 0; | ||||||
|  | 
 | ||||||
|  |   while (INPUT_IS_CLEAR) { | ||||||
|  |     // We assume the bus is free if anything happens for the length of 1 bit.
 | ||||||
|  |     if (TCNT2 > AVC_NORMAL_BIT_LENGTH) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //// reads the acknowledge bit the AVCLan
 | ||||||
|  | //// return TRUE if ack detected else FALSE.
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //bool AVCLanDrv::readAcknowledge (void)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  // The acknowledge pattern is very tricky: the sender shall drive the bus for the equivalent
 | ||||||
|  | //  // of a bit '1' (20 us) then release the bus and listen. At this point the target shall have
 | ||||||
|  | //  // taken over the bus maintaining the pulse until the equivalent of a bit '0' (32 us) is formed.
 | ||||||
|  | //
 | ||||||
|  | //  // Reset timer to measure bit length.
 | ||||||
|  | //  TCNT2 = 0;
 | ||||||
|  | //  OUTPUT_SET_1;
 | ||||||
|  | //
 | ||||||
|  | //  // Generate bit '0'.
 | ||||||
|  | //  while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH);
 | ||||||
|  | //  OUTPUT_SET_0;
 | ||||||
|  | //
 | ||||||
|  | //  AVC_OUT_DIS;
 | ||||||
|  | //
 | ||||||
|  | //  while (TCNT2 < AVC_BIT_1_HOLD_ON_LENGTH + AVC_1U_LENGTH);
 | ||||||
|  | //  // Measure final resulting bit.
 | ||||||
|  | //  while ( INPUT_IS_SET );
 | ||||||
|  | //
 | ||||||
|  | //  // Sample half-way through bit '0' (26 us) to detect whether the target is acknowledging.
 | ||||||
|  | //  if (TCNT2 > AVC_BIT_0_HOLD_ON_MIN_LENGTH) {
 | ||||||
|  | //    // Slave is acknowledging (ack = 0). Wait until end of ack bit.
 | ||||||
|  | //    while (INPUT_IS_SET );
 | ||||||
|  | //    AVC_OUT_EN;
 | ||||||
|  | //    return true;
 | ||||||
|  | //  }
 | ||||||
|  | //
 | ||||||
|  | //  // No sign of life on the bus.
 | ||||||
|  | //  return false;
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | //// sends ack bit if I am broadcasting otherwise wait and return received ack bit.
 | ||||||
|  | //// return FALSE if ack bit not detected.
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //bool AVCLanDrv::handleAcknowledge (void)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  if (broadcast == AVC_MSG_BROADCAST) {
 | ||||||
|  | //    // Acknowledge.
 | ||||||
|  | //    send1BitWord(0);
 | ||||||
|  | //    return true;
 | ||||||
|  | //  }
 | ||||||
|  | //
 | ||||||
|  | //  // Return acknowledge bit.
 | ||||||
|  | //  return readAcknowledge();
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | //// sends the message in global registers on the AVC LAN bus.
 | ||||||
|  | //// return 0 if successful else error code
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //byte AVCLanDrv::_sendMessage (void)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  uint8_t oldSREG = SREG;
 | ||||||
|  | //  cli();             // disable interrupts
 | ||||||
|  | //  while (!isAvcBusFree());
 | ||||||
|  | //
 | ||||||
|  | //  AVC_OUT_EN;
 | ||||||
|  | //
 | ||||||
|  | //  // Send start bit.
 | ||||||
|  | //  sendStartBit();
 | ||||||
|  | //
 | ||||||
|  | //  // Broadcast bit.
 | ||||||
|  | //  send1BitWord(broadcast);
 | ||||||
|  | //
 | ||||||
|  | //  // Master address = me.
 | ||||||
|  | //  send12BitWord(masterAddress);
 | ||||||
|  | //  send1BitWord(_parityBit);
 | ||||||
|  | //
 | ||||||
|  | //  // Slave address = head unit (HU).
 | ||||||
|  | //  send12BitWord(slaveAddress);
 | ||||||
|  | //  send1BitWord(_parityBit);
 | ||||||
|  | //  if (!handleAcknowledge()) {
 | ||||||
|  | //    AVC_OUT_DIS;
 | ||||||
|  | //    SREG = oldSREG;
 | ||||||
|  | //    return 1;
 | ||||||
|  | //  }
 | ||||||
|  | //
 | ||||||
|  | //  // Control flag + parity.
 | ||||||
|  | //  send4BitWord(AVC_CONTROL_FLAGS);
 | ||||||
|  | //  send1BitWord(_parityBit);
 | ||||||
|  | //  if (!handleAcknowledge()) {
 | ||||||
|  | //    AVC_OUT_DIS;
 | ||||||
|  | //    SREG = oldSREG;
 | ||||||
|  | //    return 2;
 | ||||||
|  | //  }
 | ||||||
|  | //
 | ||||||
|  | //  // Data length + parity.
 | ||||||
|  | //  send8BitWord(dataSize);
 | ||||||
|  | //  send1BitWord(_parityBit);
 | ||||||
|  | //  if (!handleAcknowledge()) {
 | ||||||
|  | //    AVC_OUT_DIS;
 | ||||||
|  | //    SREG = oldSREG;
 | ||||||
|  | //    return 3;
 | ||||||
|  | //  }
 | ||||||
|  | //
 | ||||||
|  | //  for (byte i = 0; i < dataSize; i++) {
 | ||||||
|  | //    send8BitWord(message[i]);
 | ||||||
|  | //    send1BitWord(_parityBit);
 | ||||||
|  | //    if (!handleAcknowledge()) {
 | ||||||
|  | //      AVC_OUT_DIS;
 | ||||||
|  | //      SREG = oldSREG;
 | ||||||
|  | //      return false;
 | ||||||
|  | //    }
 | ||||||
|  | //  }
 | ||||||
|  | //  AVC_OUT_DIS;
 | ||||||
|  | //  SREG = oldSREG;
 | ||||||
|  | //  return 0;
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | // sends the message in global registers on the AVC LAN bus, log message through serial port
 | ||||||
|  | // return 0 if successful else error code
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //byte AVCLanDrv::sendMessage (void)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  byte sc = MAXSENDATTEMP;
 | ||||||
|  | //  byte res;
 | ||||||
|  | //  do {
 | ||||||
|  | //    res = avclan._sendMessage();
 | ||||||
|  | //    if (!res) {
 | ||||||
|  | //      avclan.printMessage(false);
 | ||||||
|  | //    } else {
 | ||||||
|  | //      //      bSerial.print("W");
 | ||||||
|  | //      //      bSerial.printHex4(res);
 | ||||||
|  | //      //      bSerial.println();
 | ||||||
|  | //      while (!avclan.isAvcBusFree());
 | ||||||
|  | //    }
 | ||||||
|  | //    sc--;
 | ||||||
|  | //  } while (sc && res);
 | ||||||
|  | //  return res;
 | ||||||
|  | //}
 | ||||||
|  | //
 | ||||||
|  | // sends the message for given mesage ID on the AVC LAN bus, log message through serial port
 | ||||||
|  | // return 0 if successful else error code
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //byte AVCLanDrv::sendMessage (const AvcOutMessage *msg)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  loadMessage(msg);
 | ||||||
|  | //  return sendMessage();
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | // print message to serial port
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | void AVCLanDrv::printMessage(bool incoming) | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   if (incoming) { | ||||||
|  |     bSerial.print("< "); | ||||||
|  |   } else { | ||||||
|  |     bSerial.print("> "); | ||||||
|  |   } | ||||||
|  |   if (broadcast == AVC_MSG_BROADCAST) { | ||||||
|  |     bSerial.print("b "); | ||||||
|  |   } else { | ||||||
|  |     bSerial.print("d "); | ||||||
|  |   } | ||||||
|  |   bSerial.printHex4(masterAddress >> 8); | ||||||
|  |   bSerial.printHex8(masterAddress); | ||||||
|  |   bSerial.print(" "); | ||||||
|  | 
 | ||||||
|  |   bSerial.printHex4(slaveAddress >> 8); | ||||||
|  |   bSerial.printHex8(slaveAddress); | ||||||
|  |   bSerial.print(" "); | ||||||
|  |   bSerial.printHex8(dataSize); | ||||||
|  | 
 | ||||||
|  |   for (byte i = 0; i < dataSize; i++) { | ||||||
|  |     bSerial.printHex8(message[i]); | ||||||
|  |   } | ||||||
|  |   bSerial.println(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Loads message data for given mesage ID.
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void AVCLanDrv::loadMessage(const AvcOutMessage *msg)
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  broadcast = pgm_read_byte_near(&msg->broadcast);
 | ||||||
|  | //  masterAddress = deviceAddress;
 | ||||||
|  | //
 | ||||||
|  | //  if (broadcast == AVC_MSG_BROADCAST)
 | ||||||
|  | //    slaveAddress = 0x01FF;
 | ||||||
|  | //  else
 | ||||||
|  | //    slaveAddress = headAddress;
 | ||||||
|  | //
 | ||||||
|  | //  dataSize = pgm_read_byte_near( &msg->dataSize );
 | ||||||
|  | //
 | ||||||
|  | //  for (byte i = 0; i < dataSize; i++ ) {
 | ||||||
|  | //    message[i] = pgm_read_byte_near( &msg->data[i] );
 | ||||||
|  | //  }
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | AVCLanDrv avclan; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										143
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLanDrv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLanDrv.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | |||||||
|  | /*
 | ||||||
|  |   AVCLanDrv.h - AVCLan Library for 'duino / Wiring | ||||||
|  |   Created by Kochetkov Aleksey, 04.08.2010 | ||||||
|  |   Version 0.3.1 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef AVCLanDrv_h | ||||||
|  | #define AVCLanDrv_h | ||||||
|  | 
 | ||||||
|  | #include "Arduino.h" | ||||||
|  | #include "config.h" | ||||||
|  | 
 | ||||||
|  | #define AVCLANDRV_VERSION "0.3.1" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef AVCLAN_RESISTOR | ||||||
|  | // avclan driver on resistor
 | ||||||
|  | #define INPUT_IS_SET   (ACSR & _BV(ACO)) | ||||||
|  | #define INPUT_IS_CLEAR (!(ACSR & _BV(ACO))) | ||||||
|  | #define OUTPUT_SET_1   sbi(PORTD, DATAOUT); | ||||||
|  | #define OUTPUT_SET_0   cbi(PORTD, DATAOUT); | ||||||
|  | #define AVC_OUT_EN     sbi(PORTD, DATAOUT); sbi(DDRD, DATAOUT);  sbi(DDRD, DATAIN); sbi(ACSR, ACD); | ||||||
|  | #define AVC_OUT_DIS    cbi(PORTD, DATAOUT); cbi(DDRD, DATAOUT);  cbi(DDRD, DATAIN); cbi(ACSR, ACD); | ||||||
|  | #else | ||||||
|  | #ifdef AVCLAN_ST485 | ||||||
|  | // avclan driver on ST485
 | ||||||
|  | #define INPUT_IS_SET   (bit_is_clear(DATAIN_PIN, DATAIN)) | ||||||
|  | #define INPUT_IS_CLEAR (bit_is_set(DATAIN_PIN, DATAIN)) | ||||||
|  | #define OUTPUT_SET_1   (cbi(DATAOUT_PORT, DATAOUT)); | ||||||
|  | #define OUTPUT_SET_0   (sbi(DATAOUT_PORT, DATAOUT)); | ||||||
|  | #define AVC_OUT_EN     (sbi(OUTEN_PORT, OUTEN));; | ||||||
|  | #define AVC_OUT_DIS    (cbi(OUTEN_PORT, OUTEN));; | ||||||
|  | #else | ||||||
|  | //avclan driver on PCA82C250 & LM239N
 | ||||||
|  | #define INPUT_IS_SET   (bit_is_set(DATAIN_PIN, DATAIN)) | ||||||
|  | #define INPUT_IS_CLEAR (bit_is_clear(DATAIN_PIN, DATAIN)) | ||||||
|  | #define OUTPUT_SET_1   (cbi(DATAOUT_PORT, DATAOUT)); | ||||||
|  | #define OUTPUT_SET_0   (sbi(DATAOUT_PORT, DATAOUT)); | ||||||
|  | #define AVC_OUT_EN; | ||||||
|  | #define AVC_OUT_DIS; | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define AVC_NORMAL_BIT_LENGTH             0x4A  // 37 * (F_CPU / 1000000L / 8)
 | ||||||
|  | #define AVC_BIT_1_HOLD_ON_LENGTH          0x28  // 20 uS * (F_CPU / 1000000L / 8)
 | ||||||
|  | #define AVC_BIT_0_HOLD_ON_LENGTH          0x40  // 32 uS * (F_CPU / 1000000L / 8)
 | ||||||
|  | //#define AVC_BIT_0_HOLD_ON_MIN_LENGTH    0x34  // 26 uS * (F_CPU / 1000000L / 8)    Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us
 | ||||||
|  | #define AVC_BIT_0_HOLD_ON_MIN_LENGTH      0x3C  // 30 uS * (F_CPU / 1000000L / 8)    Compare half way between a '1' (20 us) and a '0' (32 us ): 32 - (32 - 20) /2 = 26 us
 | ||||||
|  | #define AVC_START_BIT_LENGTH              0x5D  // 186 uS  * (F_CPU / 1000000L / 32) ,  prescaler 32
 | ||||||
|  | #define AVC_START_BIT_HOLD_ON_LENGTH      0x54  // 168 uS * (F_CPU / 1000000L / 32)    prescaler 32
 | ||||||
|  | #define AVC_START_BIT_HOLD_ON_MIN_LENGTH  0x16  // 44 uS * (F_CPU / 1000000L / 32)      grater that AVC_NORMAL_BIT_LENGTH,  prescaler 32
 | ||||||
|  | #define AVC_1U_LENGTH                     0x02  // 1 uS * (F_CPU / 1000000L / 8)
 | ||||||
|  | 
 | ||||||
|  | #define AVC_MAXMSGLEN      32 | ||||||
|  | #define AVC_CONTROL_FLAGS  0xF | ||||||
|  | 
 | ||||||
|  | typedef enum | ||||||
|  | { // No this is not a mistake, broadcast = 0!
 | ||||||
|  |   AVC_MSG_DIRECT    = 1, | ||||||
|  |   AVC_MSG_BROADCAST = 0 | ||||||
|  | } AvcTransmissionMode; | ||||||
|  | 
 | ||||||
|  | #define ACT_NONE 0  // no action
 | ||||||
|  | //#define EV_NONE	 0	// no event
 | ||||||
|  | 
 | ||||||
|  | //typedef struct
 | ||||||
|  | //{
 | ||||||
|  | //  byte  actionID;           // Action id
 | ||||||
|  | //  byte  dataSize;           // message size (bytes)
 | ||||||
|  | //  byte  prefixSize;          // prefix size
 | ||||||
|  | //  byte  prefix[6];          // prefix command (const value)
 | ||||||
|  | //  byte  commandSize;         // prefix size
 | ||||||
|  | //  byte  command[4];            // message
 | ||||||
|  | //} AvcInMessageTable;
 | ||||||
|  | 
 | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |   byte  actionID;        // Action id
 | ||||||
|  |   byte  dataSize;        // message size (bytes)
 | ||||||
|  |   byte  command;         // message
 | ||||||
|  | } AvcInCmdTable; | ||||||
|  | 
 | ||||||
|  | //typedef struct
 | ||||||
|  | //{
 | ||||||
|  | //  byte	actionID;           // Action id
 | ||||||
|  | //  byte	dataSize;           // message size (bytes)
 | ||||||
|  | //  byte	data[14];           // message
 | ||||||
|  | //  word	mask;				// mask, set bit = 1 in not checked position (1<<5 or _BV(5) - datap[5] not checked)
 | ||||||
|  | //} AvcInMaskedMessageTable;
 | ||||||
|  | 
 | ||||||
|  | //typedef struct
 | ||||||
|  | //{
 | ||||||
|  | //  AvcTransmissionMode broadcast;          // Transmission mode: normal (1) or broadcast (0).
 | ||||||
|  | //  byte                dataSize;           // message size (bytes)
 | ||||||
|  | //  byte                data[14];           // message
 | ||||||
|  | //} AvcOutMessage;
 | ||||||
|  | 
 | ||||||
|  | #ifndef cbi | ||||||
|  | #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | ||||||
|  | #endif | ||||||
|  | #ifndef sbi | ||||||
|  | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | class AVCLanDrv { | ||||||
|  |   public: | ||||||
|  |     bool  broadcast; | ||||||
|  |     word  masterAddress; | ||||||
|  |     word  slaveAddress; | ||||||
|  |     word  deviceAddress; | ||||||
|  |     word  headAddress; | ||||||
|  |     byte  dataSize; | ||||||
|  |     byte  message[AVC_MAXMSGLEN]; | ||||||
|  |     //    byte  event;
 | ||||||
|  |     byte  actionID; | ||||||
|  |     bool  readonly; | ||||||
|  | 
 | ||||||
|  |     void  begin (); | ||||||
|  |     byte  readMessage (void); | ||||||
|  |     //    byte  sendMessage (void);
 | ||||||
|  |     //    byte  sendMessage (const AvcOutMessage*);
 | ||||||
|  |     void  printMessage (bool incoming); | ||||||
|  |     bool  isAvcBusFree (void); | ||||||
|  |     //    byte	getActionID (const AvcInMaskedMessageTable messageTable[], byte mtSize);
 | ||||||
|  |     //    void  loadMessage (const AvcOutMessage*);
 | ||||||
|  |   private: | ||||||
|  |     bool  _parityBit; | ||||||
|  |     word  readBits (byte nbBits); | ||||||
|  |     byte  _readMessage (void); | ||||||
|  |     //    byte  _sendMessage (void);
 | ||||||
|  |     //    void  sendStartBit (void);
 | ||||||
|  |     void  send1BitWord (bool data); | ||||||
|  |     //    void  send4BitWord (byte data);
 | ||||||
|  |     //    void  send8BitWord (byte data);
 | ||||||
|  |     //    void  send12BitWord (word data);
 | ||||||
|  |     //    bool  readAcknowledge (void);
 | ||||||
|  |     //    bool  handleAcknowledge (void);
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern AVCLanDrv avclan; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										62
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLan_mini.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								AVC_LAN_logger/AVCLan_mini/AVCLan_mini.ino
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | 
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | #include "AVCLanDrv.h" | ||||||
|  | #include "BuffSerial.h" | ||||||
|  | #include "config.h" | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | #define LED_ON   sbi(LED_PORT, LED_OUT); | ||||||
|  | #define LED_OFF   cbi(LED_PORT, LED_OUT); | ||||||
|  | 
 | ||||||
|  | #define HONDA_DIS_ON   sbi(LED_PORT, COMMUT_OUT); | ||||||
|  | #define HONDA_DIS_OFF  cbi(LED_PORT, COMMUT_OUT); | ||||||
|  | 
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | void setup() | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   sbi(LED_DDR,  COMMUT_OUT); | ||||||
|  |   cbi(LED_PORT, COMMUT_OUT); | ||||||
|  | 
 | ||||||
|  |   bSerial.begin(250000); | ||||||
|  |   avclan.begin(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | void loop() | ||||||
|  | //--------------------------------------------------------------------------------
 | ||||||
|  | { | ||||||
|  |   if (INPUT_IS_SET) { | ||||||
|  |     byte res = avclan.readMessage(); | ||||||
|  |     if (!res) { | ||||||
|  |       avclan.printMessage(true); | ||||||
|  |     } else { | ||||||
|  |       bSerial.print("!"); | ||||||
|  |       bSerial.printHex4(res); | ||||||
|  |       bSerial.println(); | ||||||
|  |       while (!avclan.isAvcBusFree()); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //void EERPOM_read_config()
 | ||||||
|  | ////--------------------------------------------------------------------------------
 | ||||||
|  | //{
 | ||||||
|  | //  if (EEPROM.read(E_INIT) != 'T')
 | ||||||
|  | //  {
 | ||||||
|  | //    EEPROM.write(E_MASTER1, 0x01);
 | ||||||
|  | //    EEPROM.write(E_MASTER2, 0x31);
 | ||||||
|  | //    EEPROM.write(E_READONLY, 0);
 | ||||||
|  | //    EEPROM.write(E_INIT, 'T');
 | ||||||
|  | //  }
 | ||||||
|  | //  else
 | ||||||
|  | //  {
 | ||||||
|  | //    avclan.headAddress = (EEPROM.read(E_MASTER1) << 8) + EEPROM.read(E_MASTER2);
 | ||||||
|  | //    avclan.readonly    =  EEPROM.read(E_READONLY);
 | ||||||
|  | //  }
 | ||||||
|  | //}
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										163
									
								
								AVC_LAN_logger/AVCLan_mini/BuffSerial.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								AVC_LAN_logger/AVCLan_mini/BuffSerial.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,163 @@ | |||||||
|  | /*
 | ||||||
|  |   BuffSerial.cpp v.01 - serial with transmit buffer library for Wiring | ||||||
|  |   Created by Kochetkov Aleksey, 03.07.2009 | ||||||
|  | */ | ||||||
|  | #include <stdio.h> | ||||||
|  | 
 | ||||||
|  | #include "BuffSerial.h" | ||||||
|  | 
 | ||||||
|  | // serial init
 | ||||||
|  | void BuffSerial::begin(long speed) { | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |   UCSRB = _BV(RXCIE) | _BV(RXEN) | _BV(TXCIE) | _BV(TXEN);   // enable rx, tx inerrputs
 | ||||||
|  |   UBRRH = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8;       // usart speed
 | ||||||
|  |   UBRRL = ((F_CPU / 16 + speed / 2) / speed - 1); | ||||||
|  | #else | ||||||
|  |   UCSR0B = (_BV(RXCIE0) | _BV(RXEN0) | _BV(TXCIE0) | _BV(TXEN0));  // enable rx, tx inerrputs
 | ||||||
|  |   UBRR0H = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8;            // usart speed
 | ||||||
|  |   UBRR0L = ((F_CPU / 16 + speed / 2) / speed - 1); | ||||||
|  | #endif | ||||||
|  |   rxBegin = rxEnd = 0; | ||||||
|  |   txBegin = txEnd = txOverflow = 0; | ||||||
|  |   txFull  = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //USART Rx Complete
 | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  | SIGNAL(SIG_UART_RECV) | ||||||
|  | #else | ||||||
|  | SIGNAL(USART_RX_vect) | ||||||
|  | #endif | ||||||
|  | { | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |   bSerial.rxBuffer[bSerial.rxEnd] = UDR; | ||||||
|  | #else | ||||||
|  |   bSerial.rxBuffer[bSerial.rxEnd] = UDR0; | ||||||
|  | #endif | ||||||
|  |   if (bSerial.rxEnd < RX_BUFF_SIZE) bSerial.rxEnd++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //USART Tx Complete
 | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  | SIGNAL(SIG_UART_TRANS) | ||||||
|  | #else | ||||||
|  | SIGNAL(USART_TX_vect) | ||||||
|  | #endif | ||||||
|  | { | ||||||
|  |   if (bSerial.txEnd != bSerial.txBegin || bSerial.txFull != 0) { | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |     UDR  = bSerial.txBuffer[bSerial.txBegin];  // Send buffer
 | ||||||
|  | #else | ||||||
|  |     UDR0 = bSerial.txBuffer[bSerial.txBegin];  // Send buffer
 | ||||||
|  | #endif | ||||||
|  |     bSerial.txFull = 0; | ||||||
|  |     bSerial.txBegin++; | ||||||
|  |     if (bSerial.txBegin == TX_BUFF_SIZE) bSerial.txBegin = 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // send byte to serial or buffer if bisy
 | ||||||
|  | void BuffSerial::sendByte(uint8_t data) { | ||||||
|  |   if (txFull) { | ||||||
|  |     txOverflow++; | ||||||
|  |   } else { | ||||||
|  |     uint8_t oldSREG = SREG; | ||||||
|  |     cli(); | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |     if (txEnd != txBegin || (UCSRA & _BV(UDRE)) == 0) { | ||||||
|  | #else | ||||||
|  |     if (txEnd != txBegin || (UCSR0A & _BV(UDRE0)) == 0) { | ||||||
|  | #endif | ||||||
|  |       txBuffer[txEnd] = data; | ||||||
|  |       txEnd++; | ||||||
|  |       if (txEnd == TX_BUFF_SIZE) txEnd = 0; | ||||||
|  |       if (txEnd == txBegin) txFull = 1;          // buffer overflow
 | ||||||
|  |     } else { | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |       UDR  = data; | ||||||
|  | #else | ||||||
|  |       UDR0 = data; | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  |     SREG = oldSREG; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // print string
 | ||||||
|  | void BuffSerial::print(const char *pBuf) { | ||||||
|  |   while (*pBuf)	{ | ||||||
|  |     sendByte(*pBuf++); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::print(const char pBuf) { | ||||||
|  |   sendByte(pBuf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void BuffSerial::println(const char *pBuf) { | ||||||
|  |   print(pBuf); | ||||||
|  |   println(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::println(const char pBuf) { | ||||||
|  |   print(pBuf); | ||||||
|  |   println(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::println(void) { | ||||||
|  |   print("\r\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::printHex4(uint8_t data) { | ||||||
|  |   uint8_t c = data & 0x0f; | ||||||
|  |   c += c < 10 ? '0' : 'A' - 10 ; | ||||||
|  |   sendByte(c); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::printHex8(uint8_t data) { | ||||||
|  |   printHex4(data >> 4); | ||||||
|  |   printHex4(data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void BuffSerial::printDec(uint8_t data) { | ||||||
|  |   uint8_t buf[3]; | ||||||
|  |   uint8_t i = 0; | ||||||
|  |   if (data == 0) { | ||||||
|  |     sendByte('0'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   while (data > 0) { | ||||||
|  |     buf[i++] = data % 10; | ||||||
|  |     data /= 10; | ||||||
|  |   } | ||||||
|  |   for (; i > 0; i--) | ||||||
|  |     sendByte((buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // check rx buffer not empty
 | ||||||
|  | bool BuffSerial::rxEnabled(void) { | ||||||
|  |   return rxEnd; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t BuffSerial::rxRead(void) { | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |   cbi(UCSRB, RXCIE);                           // disable RX complete interrupt
 | ||||||
|  | #else | ||||||
|  |   cbi(UCSR0B, RXCIE0);                         // disable RX complete interrupt
 | ||||||
|  | #endif | ||||||
|  |   uint8_t readkey = rxBuffer[rxBegin];         // read begin of received Buffer
 | ||||||
|  |   rxBegin++; | ||||||
|  |   if (rxBegin == rxEnd) rxBegin = rxEnd = 0;   // if Buffer is empty reset Buffer
 | ||||||
|  | #if defined(__AVR_ATmega8__) | ||||||
|  |   sbi(UCSRB, RXCIE);                           // enable RX complete interrupt
 | ||||||
|  | #else | ||||||
|  |   sbi(UCSR0B, RXCIE0);                         // enable RX complete interrupt
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   return readkey; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BuffSerial bSerial; | ||||||
							
								
								
									
										49
									
								
								AVC_LAN_logger/AVCLan_mini/BuffSerial.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								AVC_LAN_logger/AVCLan_mini/BuffSerial.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | /*
 | ||||||
|  |   BuffSerial.h v.01 - serial with transmit buffer library for Wiring | ||||||
|  |   Created by Kochetkov Aleksey, 03.07.2009 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef BuffSerial_h | ||||||
|  | #define BuffSerial_h | ||||||
|  | 
 | ||||||
|  | #include "Arduino.h" | ||||||
|  | 
 | ||||||
|  | #define TX_BUFF_SIZE		240               // max 65535 
 | ||||||
|  | #define RX_BUFF_SIZE		25                // max 255
 | ||||||
|  | #define TX_BUFF_MAX_LEN		TX_BUFF_SIZE - 1 | ||||||
|  | 
 | ||||||
|  | #ifndef cbi | ||||||
|  | #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | ||||||
|  | #endif | ||||||
|  | #ifndef sbi | ||||||
|  | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | class BuffSerial { | ||||||
|  |   public: | ||||||
|  |     uint8_t		rxBuffer[RX_BUFF_SIZE]; | ||||||
|  |     uint8_t		rxBegin; | ||||||
|  |     uint8_t		rxEnd; | ||||||
|  |     uint8_t		txBuffer[TX_BUFF_SIZE]; | ||||||
|  |     uint16_t	txBegin; | ||||||
|  |     uint16_t	txEnd; | ||||||
|  |     uint8_t		txFull; | ||||||
|  |     uint16_t	txOverflow; | ||||||
|  |     void		begin(long); | ||||||
|  |     void 		sendByte(uint8_t); | ||||||
|  |     void		print(const char*); | ||||||
|  |     void		print(const char); | ||||||
|  |     void		println(const char*); | ||||||
|  |     void		println(const char); | ||||||
|  |     void		println(void); | ||||||
|  |     void		printHex4(uint8_t); | ||||||
|  |     void		printHex8(uint8_t); | ||||||
|  |     void		printDec(uint8_t); | ||||||
|  |     bool		rxEnabled(void); | ||||||
|  |     uint8_t		rxRead(void); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern BuffSerial bSerial; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
							
								
								
									
										48
									
								
								AVC_LAN_logger/AVCLan_mini/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								AVC_LAN_logger/AVCLan_mini/config.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | /*
 | ||||||
|  |   config.h  - AVCLan driver config | ||||||
|  |   Created by Kochetkov Aleksey, 04.08.2010 | ||||||
|  | */ | ||||||
|  | #define IEBUS_VERSION "0.4" | ||||||
|  | 
 | ||||||
|  | // type of AVCLan hardwire driver
 | ||||||
|  | #define AVCLAN_PCA82C250 | ||||||
|  | 
 | ||||||
|  | // maximum number of attempts to send a message
 | ||||||
|  | #define MAXSENDATTEMP   3 | ||||||
|  | 
 | ||||||
|  | //********** arduino & driver based on PCA82C250 **********
 | ||||||
|  | #ifdef AVCLAN_PCA82C250 | ||||||
|  | #define AVCLANDRIVER_TYPE    "Arduino - PCA82C250" | ||||||
|  | // define out pin (pin 8 arduino)
 | ||||||
|  | #define  DATAOUT_DDR    DDRD | ||||||
|  | #define  DATAOUT_PORT   PORTD | ||||||
|  | #define  DATAOUT_PIN    PIND | ||||||
|  | #define  DATAOUT        7 | ||||||
|  | 
 | ||||||
|  | // define in pin (pin 9 arduino)
 | ||||||
|  | #define  DATAIN_DDR  DDRD | ||||||
|  | #define  DATAIN_PORT PORTD | ||||||
|  | #define  DATAIN_PIN  PIND | ||||||
|  | #define  DATAIN      6 | ||||||
|  | 
 | ||||||
|  | // LED connected to digital pin 13
 | ||||||
|  | #define  LED_DDR     DDRC | ||||||
|  | #define  LED_PORT    PORTC | ||||||
|  | #define  LED_PIN     PINC | ||||||
|  | //#define  LED_OUT     5
 | ||||||
|  | 
 | ||||||
|  | // Commutate pin 11
 | ||||||
|  | #define COMMUT_OUT   1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // AZFM board activate
 | ||||||
|  | #define AZFM_INIT | ||||||
|  | #define AZFM_ON | ||||||
|  | #define AZFM_OFF | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user