develop
Katya 2 years ago
parent 5cbd35423f
commit 7b98c2081a

@ -0,0 +1,4 @@
Debug
Release
.vs
desktop.ini

@ -0,0 +1,103 @@
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 16000000UL
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <Arduino.h>
#include "IdiBusSerialLine.h"
#include "IDIBUS_4DC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//IDIBUS MASTER V0.26 beta
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerialLine Serial_Line0;
IdiBusSerialLine Serial_Line1;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup()
{
delay(50); //Power on delay for external periphery
//Arduino Variant
IDIBUS_SERIAL_INIT_TYPEDEF L0Init;
L0Init.USART_NUMBER = IDIBUS_SERIAL_USART2;
L0Init.TIMER_NUMBER = IDIBUS_TIMER_1;
L0Init.CONFIG = IDIBUS_SERIAL_8N2;
L0Init.RS485_DIR_PIN = 6;
L0Init.BAUDRATE_DIPSW_S0_PIN = 9;
L0Init.BAUDRATE_DIPSW_S1_PIN = 8;
L0Init.BAUDRATE_DIPSW_S2_PIN = 7;
Serial_Line0.Init(&L0Init);
Serial_Line0.UpdateBaudrateFromDipSwitch();
Serial_Line0.Start();
// Standard pinout variant
IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF L1Init;
L1Init.USART_NUMBER = IDIBUS_SERIAL_USART1;
L1Init.TIMER_NUMBER = IDIBUS_TIMER_3;
L1Init.CONFIG = IDIBUS_SERIAL_8N2;
L1Init.RS485_DIR_GPIO.PORT = &PORTL;
L1Init.RS485_DIR_GPIO.PIN_NUM = 6;
L1Init.BAUDRATE_DIPSW.S0.PORT = &PORTD;
L1Init.BAUDRATE_DIPSW.S0.PIN_NUM = 1;
L1Init.BAUDRATE_DIPSW.S1.PORT = &PORTD;
L1Init.BAUDRATE_DIPSW.S1.PIN_NUM = 0;
L1Init.BAUDRATE_DIPSW.S2.PORT = &PORTL;
L1Init.BAUDRATE_DIPSW.S2.PIN_NUM = 7;
Serial_Line1.Init(&L1Init);
Serial_Line1.UpdateBaudrateFromDipSwitch();
Serial_Line1.Start();
Serial.begin(SERIAL_8N2);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
volatile uint8_t ErrorCode[10];
IdiBusLongOpData LopData;
IdiBus_4DC_INPVChannel INPV_Data;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void loop()
{
IdiBus_4DC IDB4DC(&Serial_Line1, 122);
/*
//ErrorCode = IDB4DC.c_Init(10);
ErrorCode = IDB4DC.c_Init();
delay(1000);
ErrorCode = IDB4DC.c_AssignGroup(IDIBUS_PSU_CNTRL_DEV, 0, 10);
ErrorCode = IDB4DC.c_AssignGroup(IDIBUS_PSU_CNTRL_DEV, 2, 10);
uint8_t TxData;
IdiBusMMESG Group1(IDIBUS_GROUP_10_ADDR, &TxData, 1);
Group1.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE;
while (1)
{
Serial.write((uint8_t*)"echo", sizeof("echo")-1);
TxData = 0;
Serial_Line1.sendMMESG(&Group1);
delay(2000);
TxData = 1;
Serial_Line1.sendMMESG(&Group1);
delay(2000);
}*/
ErrorCode[0] = IDB4DC.c_Init();
delay(1000);
ErrorCode[1] = IDB4DC.c_WriteSnIPv4IPv6(0xAABBCCDD, 0xA1A2A3A4, 0xA5A6A7A8, 0xB1B2B3B4, 0xB5B6B7B8);
do { ErrorCode[2] = IDB4DC.c_CheckModuleLongOp(); }
while ( (LopData = IDB4DC.getModuleLongOpData()).State == IDILONGOP_STATE_IN_PROC );
ErrorCode[3] = IDB4DC.INPV_DEV.getInputVoltage();
INPV_Data = IDB4DC.INPV_DEV.getChData();
IDB4DC.PSUC_DEV.setAllChVoltage(5000, 6000, 7000, 8000);
IDB4DC.PSUC_DEV.setAllChState(1);
while (1)
{
IDB4DC.PSUC_DEV.setAllChState(0, 1, 0, 1);
delay(2000);
IDB4DC.PSUC_DEV.setAllChState(1, 0, 1, 0);
delay(2000);
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

@ -0,0 +1,29 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_CALLBACK_INTERFACE_H_
#define _IDIBUS_CALLBACK_INTERFACE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusCallbackInterface {
public:
static void USART_Callback_InterruptTX (IdiBusCallbackInterface *inst) { inst->USART_TxInterruptFunc(); }
static void USART_Callback_InterruptRX (IdiBusCallbackInterface *inst) { inst->USART_RxInterruptFunc(); }
static void USART_Callback_InterruptUDRE (IdiBusCallbackInterface *inst) { inst->USART_UdreInterruptFunc(); }
virtual void USART_RxInterruptFunc(void) {}
virtual void USART_TxInterruptFunc(void) {}
virtual void USART_UdreInterruptFunc(void) {}
static void TIM_Callback_InterruptCOMPA (IdiBusCallbackInterface *inst) { inst->TIM_COMPA_InterruptFunc(); }
static void TIM_Callback_InterruptCOMPB (IdiBusCallbackInterface *inst) { inst->TIM_COMPB_InterruptFunc(); }
static void TIM_Callback_InterruptCOMPC (IdiBusCallbackInterface *inst) { inst->TIM_COMPC_InterruptFunc(); }
static void TIM_Callback_InterruptOVF (IdiBusCallbackInterface *inst) { inst->TIM_OVF_InterruptFunc(); }
virtual void TIM_COMPA_InterruptFunc (void) {}
virtual void TIM_COMPB_InterruptFunc (void) {}
virtual void TIM_COMPC_InterruptFunc (void) {}
virtual void TIM_OVF_InterruptFunc (void) {}
};
typedef void (*CallbackTypeFunction)(IdiBusCallbackInterface*);
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_CALLBACK_INTERFACE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,18 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_INTERRUPTS_DISABLE_H_
#define _IDIBUS_INTERRUPTS_DISABLE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_USART0_ISR_DISABLE
//#define IDIBUS_USART1_ISR_DISABLE
//#define IDIBUS_USART2_ISR_DISABLE
//#define IDIBUS_USART3_ISR_DISABLE
#define IDIBUS_TIM0_ISR_DISABLE
//#define IDIBUS_TIM1_ISR_DISABLE
//#define IDIBUS_TIM2_ISR_DISABLE
//#define IDIBUS_TIM3_ISR_DISABLE
//#define IDIBUS_TIM4_ISR_DISABLE
//#define IDIBUS_TIM5_ISR_DISABLE
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_INTERRUPTS_DISABLE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,65 @@
//#############################################################################################################################################################################################################
#include "IdiBusInterruptsList.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct IDIBUS_INTERRUPT_LISTENERS_STR InterruptListenersList;
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#ifndef IDIBUS_USART0_ISR_DISABLE
ISR(USART0_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART0_CallbackInstance); }
ISR(USART0_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART0_CallbackInstance); }
ISR(USART0_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART0_CallbackInstance); }
#endif
#ifndef IDIBUS_USART1_ISR_DISABLE
ISR(USART1_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART1_CallbackInstance); }
ISR(USART1_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART1_CallbackInstance); }
ISR(USART1_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART1_CallbackInstance); }
#endif
#ifndef IDIBUS_USART2_ISR_DISABLE
ISR(USART2_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART2_CallbackInstance); }
ISR(USART2_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART2_CallbackInstance); }
ISR(USART2_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART2_CallbackInstance); }
#endif
#ifndef IDIBUS_USART3_ISR_DISABLE
ISR(USART3_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART3_CallbackInstance); }
ISR(USART3_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART3_CallbackInstance); }
ISR(USART3_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART3_CallbackInstance); }
#endif
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#ifndef IDIBUS_TIM0_ISR_DISABLE
ISR(TIMER0_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM0_CallbackInstance); }
ISR(TIMER0_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM0_CallbackInstance); }
ISR(TIMER0_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM0_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM1_ISR_DISABLE
ISR(TIMER1_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM1_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM2_ISR_DISABLE
ISR(TIMER2_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM2_CallbackInstance); }
ISR(TIMER2_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM2_CallbackInstance); }
ISR(TIMER2_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM2_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM3_ISR_DISABLE
ISR(TIMER3_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM3_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM4_ISR_DISABLE
ISR(TIMER4_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM4_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM5_ISR_DISABLE
ISR(TIMER5_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM5_CallbackInstance); }
#endif
//#############################################################################################################################################################################################################

@ -0,0 +1,48 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_INTERRUPTS_LIST_H_
#define _IDIBUS_INTERRUPTS_LIST_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "IdiBusCallbackInterface.h"
#include "IdiBusInterruptsDisable.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct IDIBUS_INTERRUPT_LISTENERS_STR {
#ifndef IDIBUS_USART0_ISR_DISABLE
IdiBusCallbackInterface *USART0_CallbackInstance;
#endif
#ifndef IDIBUS_USART1_ISR_DISABLE
IdiBusCallbackInterface *USART1_CallbackInstance;
#endif
#ifndef IDIBUS_USART2_ISR_DISABLE
IdiBusCallbackInterface *USART2_CallbackInstance;
#endif
#ifndef IDIBUS_USART3_ISR_DISABLE
IdiBusCallbackInterface *USART3_CallbackInstance;
#endif
#ifndef IDIBUS_TIM0_ISR_DISABLE
IdiBusCallbackInterface *TIM0_CallbackInstance;
#endif
#ifndef IDIBUS_TIM1_ISR_DISABLE
IdiBusCallbackInterface *TIM1_CallbackInstance;
#endif
#ifndef IDIBUS_TIM2_ISR_DISABLE
IdiBusCallbackInterface *TIM2_CallbackInstance;
#endif
#ifndef IDIBUS_TIM3_ISR_DISABLE
IdiBusCallbackInterface *TIM3_CallbackInstance;
#endif
#ifndef IDIBUS_TIM4_ISR_DISABLE
IdiBusCallbackInterface *TIM4_CallbackInstance;
#endif
#ifndef IDIBUS_TIM5_ISR_DISABLE
IdiBusCallbackInterface *TIM5_CallbackInstance;
#endif
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern struct IDIBUS_INTERRUPT_LISTENERS_STR InterruptListenersList;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_INTERRUPTS_LIST_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,57 @@
//#############################################################################################################################################################################################################
#include "IdiBusDateTime.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiDateFormat::IdiDateFormat(uint8_t day, uint8_t month, uint8_t century, uint8_t year99)
{
this->Day = day;
this->Month = month;
this->Century = century;
this->Year99 = year99;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiDateFormat::isValid(void)
{
if ( (this->Day == 0) || (this->Day > 31) ||
(this->Month == 0) || (this->Month > 12) ||
(this->Century > 99) || (this->Year99 > 99) ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiDateFormat::getSize(void) { return IDIDATE_FORMAT_LENGTH; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiDateFormat::getBufForMMES(uint8_t *Data)
{
Data[IDIDATE_FORMAT_DAY_Pos] = this->Day;
Data[IDIDATE_FORMAT_MONTH_Pos] = this->Month;
Data[IDIDATE_FORMAT_CENTURY_Pos] = this->Century;
Data[IDIDATE_FORMAT_YEAR99_Pos] = this->Year99;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiTimeFormat::IdiTimeFormat(uint8_t seconds, uint8_t minutes, uint8_t hours, int8_t timezone)
{
this->Seconds = seconds;
this->Minutes = minutes;
this->Hours = hours;
this->TimeZone = timezone;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiTimeFormat::isValid(void)
{
if ( (this->Seconds > 60) || (this->Minutes > 60) || (this->Hours > 23) ||
(this->TimeZone < IDITIME_FORMAT_TIMEZONE_MIN) || (this->TimeZone > IDITIME_FORMAT_TIMEZONE_MAX) ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiTimeFormat::getSize(void) { return IDITIME_FORMAT_LENGTH; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiTimeFormat::getBufForMMES(uint8_t *Data)
{
Data[IDITIME_FORMAT_SECONDS_Pos] = this->Seconds;
Data[IDITIME_FORMAT_MINUTES_Pos] = this->Minutes;
Data[IDITIME_FORMAT_HOURS_Pos] = this->Hours;
Data[IDITIME_FORMAT_TIMEZONE_Pos] = (uint8_t)this->TimeZone;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,32 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_DATE_TIME_H_
#define _IDIBUS_DATE_TIME_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiDateFormat {
public:
IdiDateFormat(uint8_t day, uint8_t month, uint8_t century, uint8_t year99);
uint8_t Day;
uint8_t Month;
uint8_t Century;
uint8_t Year99;
uint8_t isValid(void);
uint8_t getSize(void);
void getBufForMMES(uint8_t *Data);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiTimeFormat {
public:
IdiTimeFormat(uint8_t seconds, uint8_t minutes, uint8_t hours, int8_t timezone);
uint8_t Seconds;
uint8_t Minutes;
uint8_t Hours;
int8_t TimeZone;
uint8_t isValid(void);
uint8_t getSize(void);
void getBufForMMES(uint8_t *Data);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_DATE_TIME_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,128 @@
//#############################################################################################################################################################################################################
#include "IdiBusMes.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsGroupAddr(void) { return ( (this->SlAddr >= IDIBUS_GROUP_0_ADDR)&&(this->SlAddr <= IDIBUS_GROUP_15_ADDR) ) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsCommand(void) { return ( this->ComFunc >= IDIMMES_COM_START_NUM ) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsModuleError(uint8_t ErrCode) { return ((ErrCode >= IDIER_MODULE_NUM_START)&&(ErrCode <= IDIER_MODULE_NUM_END)) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsModuleCommand(void)
{
switch (this->ComFunc)
{
case(IDIMMES_COM_C_Init) :
case(IDIMMES_COM_C_ShtDown) :
case(IDIMMES_COM_C_Freeze) :
case(IDIMMES_COM_C_Resume) :
case(IDIMMES_COM_C_SetAlarmL12) :
case(IDIMMES_COM_C_SetAlarmL) :
case(IDIMMES_COM_C_SyncRead) :
case(IDIMMES_COM_C_SyncDoChnl) :
case(IDIMMES_COM_C_SyncDo) :
case(IDIMMES_COM_C_SyncClear) :
case(IDIMMES_COM_C_SendTimeDate) :
case(IDIMMES_COM_C_MkTimedMaster) :
case(IDIMMES_COM_C_FmwUpd) :
case(IDIMMES_COM_C_EndFmwUpd) :
case(IDIMMES_COM_C_FmwWrite) :
case(IDIMMES_COM_C_ReadDevFullSN_MS) :
case(IDIMMES_COM_C_WriteSnIPv4IPv6) :
case(IDIMMES_COM_C_WriteSnVerifyDates) :
case(IDIMMES_COM_C_WriteSnAES256) :
case(IDIMMES_COM_C_DummyModule) :
case(IDIMMES_COM_C_CheckModuleLongOp) : { return 1; }
default : {}
}
return 0;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBusMMES::IdiBusMMES (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->DEV.NUM = 0;
this->DEV.ALLCH = 0;
this->CHNL.ALLSAME = 0;
this->CHNL.NUM = 0;
this->ComFunc = 1;
this->TxData = TX_DataP;
this->TxDataLength = TX_DataLength;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusMMES::IdiBusMMES (uint8_t SlAddr)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->DEV.NUM = 0;
this->DEV.ALLCH = 0;
this->CHNL.ALLSAME = 0;
this->CHNL.NUM = 0;
this->ComFunc = IDIMMES_COM_C_Dummy;
this->TxData = NULL;
this->TxDataLength = 0;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMMES::IsValid(void)
{
if ( (this->ComFunc == 0) || this->IsModuleCommand() || this->IsGroupAddr() ) { return 0; }
return 1;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBusMMESG::IdiBusMMESG (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->ComFunc = IDIMMES_COM_C_DummyModule;
this->TxData = TX_DataP;
this->TxDataLength = TX_DataLength;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusMMESG::IdiBusMMESG (uint8_t SlAddr)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->ComFunc = IDIMMES_COM_C_Dummy;
this->TxData = NULL;
this->TxDataLength = 0;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMMESG::IsValid(void)
{
uint8_t isModuleCommand = this->IsModuleCommand();
uint8_t isGroupAddress = this->IsGroupAddr();
if ( this->ComFunc == IDIMMES_NOT_FAST_FUNC ) { return 0; }
if ( isGroupAddress )
{
if ( isModuleCommand != 0 ) { return 0; }
}
else if ( isModuleCommand == 0 ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,50 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_MES_H_
#define _IDIBUS_MES_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMessage {
public :
uint8_t SlAddr;
struct {
uint8_t LongMes : 1;
uint8_t AlarmMes : 1;
uint8_t EncryptedAes : 1;
} MMPS;
uint8_t ComFunc;
uint8_t *TxData;
uint8_t TxDataLength;
uint8_t *RxData;
uint8_t RxDataLength;
uint8_t IsGroupAddr(void);
uint8_t IsModuleCommand(void);
uint8_t IsCommand(void);
uint8_t IsModuleError(uint8_t ErrCode);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMMES : public IdiBusMessage {
public :
IdiBusMMES (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength);
IdiBusMMES (uint8_t SlAddr);
struct {
uint8_t NUM : 5;
uint8_t ALLCH : 1;
} DEV;
struct {
uint8_t NUM : 7;
uint8_t ALLSAME : 1;
} CHNL;
uint8_t IsValid(void);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMMESG : public IdiBusMessage {
public :
IdiBusMMESG (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength);
IdiBusMMESG (uint8_t SlAddr);
uint8_t IsValid(void);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_MES_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,621 @@
//#############################################################################################################################################################################################################
#include "IdiBusSerial.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerial::IdiBusSerial(void)
{
this->RS485_DIR_GPIO.DDR = (uint8_t*)&this->InitProtectionVar;
this->RS485_DIR_GPIO.PIN = (uint8_t*)&this->InitProtectionVar;
this->RS485_DIR_GPIO.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNA = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNB = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNC = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UBRRN = (uint16_t*)&this->InitProtectionVar;
this->USARTN.UDRN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TCCRNA = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TCCRNB = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TIMSKN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TIFRN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.OCRNA = (uint16_t*)&this->InitProtectionVar;
this->TIMN.OCRNB = (uint16_t*)&this->InitProtectionVar;
this->TIMN.TCNTN = (uint16_t*)&this->InitProtectionVar;
this->InitState = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::Init(IDIBUS_SERIAL_INIT_TYPEDEF *InitT)
{
if ( (this->GetGpioParamsArduino(InitT->RS485_DIR_PIN, &this->RS485_DIR_GPIO) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S0_PIN, &this->BAUDRATE_DIPSW.S0_Gpio) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S1_PIN, &this->BAUDRATE_DIPSW.S1_Gpio) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S2_PIN, &this->BAUDRATE_DIPSW.S2_Gpio) == 0) ) { return 0; }
return this->BaseInit(InitT->USART_NUMBER, InitT->TIMER_NUMBER, InitT->CONFIG);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::Init(IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF *InitT)
{
if ( (this->GetGpioParams(&InitT->RS485_DIR_GPIO, &this->RS485_DIR_GPIO) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S0, &this->BAUDRATE_DIPSW.S0_Gpio) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S1, &this->BAUDRATE_DIPSW.S1_Gpio) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S2, &this->BAUDRATE_DIPSW.S2_Gpio) == 0) ) { return 0; }
return this->BaseInit(InitT->USART_NUMBER, InitT->TIMER_NUMBER, InitT->CONFIG);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::BaseInit( enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUM, enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUM, enum IDIBUS_SERIAL_USARTN_CONFIG CONF)
{
// Pointers Init
switch (USART_NUM)
{
case (IDIBUS_SERIAL_USART0) : {
#if defined IDIBUS_USART0_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR0A);
this->USARTN.UCSRNB = &(UCSR0B);
this->USARTN.UCSRNC = &(UCSR0C);
this->USARTN.UBRRN = &(UBRR0);
this->USARTN.UDRN = &(UDR0);
InterruptListenersList.USART0_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART1) : {
#if defined IDIBUS_USART1_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR1A);
this->USARTN.UCSRNB = &(UCSR1B);
this->USARTN.UCSRNC = &(UCSR1C);
this->USARTN.UBRRN = &(UBRR1);
this->USARTN.UDRN = &(UDR1);
InterruptListenersList.USART1_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART2) : {
#if defined IDIBUS_USART2_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR2A);
this->USARTN.UCSRNB = &(UCSR2B);
this->USARTN.UCSRNC = &(UCSR2C);
this->USARTN.UBRRN = &(UBRR2);
this->USARTN.UDRN = &(UDR2);
InterruptListenersList.USART2_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART3) : {
#if defined IDIBUS_USART3_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR3A);
this->USARTN.UCSRNB = &(UCSR3B);
this->USARTN.UCSRNC = &(UCSR3C);
this->USARTN.UBRRN = &(UBRR3);
this->USARTN.UDRN = &(UDR3);
InterruptListenersList.USART3_CallbackInstance = this;
#endif
break; }
default : { return 0; }
}
switch (TIMER_NUM)
{
case (IDIBUS_TIMER_1) : {
#if defined IDIBUS_TIM1_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR1A);
this->TIMN.TCCRNB = &(TCCR1B);
this->TIMN.TIMSKN = &(TIMSK1);
this->TIMN.TIFRN = &(TIFR1);
this->TIMN.OCRNA = &(OCR1A);
this->TIMN.OCRNB = &(OCR1B);
this->TIMN.TCNTN = &(TCNT1);
InterruptListenersList.TIM1_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_3) : {
#if defined IDIBUS_TIM3_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR3A);
this->TIMN.TCCRNB = &(TCCR3B);
this->TIMN.TIMSKN = &(TIMSK3);
this->TIMN.TIFRN = &(TIFR3);
this->TIMN.OCRNA = &(OCR3A);
this->TIMN.OCRNB = &(OCR3B);
this->TIMN.TCNTN = &(TCNT3);
InterruptListenersList.TIM3_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_4) : {
#if defined IDIBUS_TIM4_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR4A);
this->TIMN.TCCRNB = &(TCCR4B);
this->TIMN.TIMSKN = &(TIMSK4);
this->TIMN.TIFRN = &(TIFR4);
this->TIMN.OCRNA = &(OCR4A);
this->TIMN.OCRNB = &(OCR4B);
this->TIMN.TCNTN = &(TCNT4);
InterruptListenersList.TIM4_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_5) : {
#if defined IDIBUS_TIM5_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR5A);
this->TIMN.TCCRNB = &(TCCR5B);
this->TIMN.TIMSKN = &(TIMSK5);
this->TIMN.TIFRN = &(TIFR5);
this->TIMN.OCRNA = &(OCR5A);
this->TIMN.OCRNB = &(OCR5B);
this->TIMN.TCNTN = &(TCNT5);
InterruptListenersList.TIM5_CallbackInstance = this;
#endif
break; }
default : { return 0; }
}
// GPIO Init
uint8_t SREG_Temp = SREG;
cli();
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK;
*this->RS485_DIR_GPIO.DDR |= this->RS485_DIR_GPIO.PIN_MASK;
*this->BAUDRATE_DIPSW.S0_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S0_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S1_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S1_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S2_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S2_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK;
if ( SREG_Temp & (0x01U << SREG_I) ) { sei(); }
// USART Init
*this->USARTN.UBRRN = 0;
*this->USARTN.UCSRNA = (1U<<USARTN_UCSRNA_U2X_Pos);
*this->USARTN.UCSRNB = 0;
this->BAUDRATE = 0;
switch (CONF)
{
case (IDIBUS_SERIAL_8N1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(0U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8N2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(0U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8E1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8E2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8O1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(1U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8O2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(1U<<USARTN_UCSRNC_UPM0); break; }
default : { return 0; }
}
// TIMER Init
*this->TIMN.TCCRNB = 0; // Counter stop
*this->TIMN.TCCRNA = 0; // Normal Mode
*this->TIMN.TIMSKN = 0;
this->InitState = 1;
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::SetBaudrate(enum IDIBUS_SERIAL_BAUDRATE Baudrate)
{
switch ( Baudrate )
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : {
this->SetBaudrateLL(2400);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint32_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : {
this->SetBaudrateLL(9600);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint32_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : {
this->SetBaudrateLL(19200);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : {
this->SetBaudrateLL(115200);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : {
this->SetBaudrateLL(250000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : {
this->SetBaudrateLL(500000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : {
this->SetBaudrateLL(1000000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : {
this->SetBaudrateLL(10000000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
default : { return; }
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::UpdateBaudrateFromDipSwitch(void)
{
uint8_t BaudrateCode = 0;
uint32_t BaudrateCodeValue;
if ( (*this->BAUDRATE_DIPSW.S2_Gpio.PIN & this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x04; }
if ( (*this->BAUDRATE_DIPSW.S1_Gpio.PIN & this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x02; }
if ( (*this->BAUDRATE_DIPSW.S0_Gpio.PIN & this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x01; }
switch (BaudrateCode)
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : { BaudrateCodeValue = 2400U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : { BaudrateCodeValue = 9600U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : { BaudrateCodeValue = 19200U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : { BaudrateCodeValue = 115200U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : { BaudrateCodeValue = 250000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : { BaudrateCodeValue = 500000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : { BaudrateCodeValue = 1000000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : { BaudrateCodeValue = 10000000U; break; }
default : { return; }
}
if ( this->BAUDRATE != BaudrateCodeValue )
{
this->SetBaudrateLL(BaudrateCodeValue);
switch ( BaudrateCode )
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
default : { return; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::SetBaudrateLL(uint32_t Baudrate)
{
uint16_t UBRR_2X;
if ( ((F_CPU / 8U) % Baudrate) < (Baudrate / 2) )
{
UBRR_2X = (uint16_t)( ((uint32_t)F_CPU / 8U) / Baudrate );
if ( UBRR_2X != 0 ) { UBRR_2X--; }
}
else { UBRR_2X = (uint16_t)( ((uint32_t)F_CPU / 8U) / Baudrate ); } //(F_CPU / 8U) / Baudrate + 1 - 1
*this->USARTN.UBRRN = UBRR_2X;
this->BAUDRATE = Baudrate;
if ( this->InitState == 1 ) { this->InitState = 2; }
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiBusSerial::Start(void)
{
*this->USARTN.UCSRNB = (1U<<USARTN_UCSRNB_TXEN_Pos) | (1U<<USARTN_UCSRNB_TXCIE_Pos); // USART TX Periph enable
cli();
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK; // Dir to Tx
sei();
this->TransferComplete = 1; //
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::Stop(void)
{
*this->TIMN.TCCRNB = 0; // Timer Stop
cli();
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK; // Dir to RX
sei();
*this->USARTN.UCSRNB = 0; // USART TX/RX Periph disable
this->TransferComplete = 1; //
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
if ( _TxBufLength_ == 0 ) { this->ERROR_STATUS.BF.TxZerolength = 1; return 0; }
else if ( _TxBufLength_ > IDIBUS_SERIAL_TX_BUF_SIZE ) { this->ERROR_STATUS.BF.TxOverflow = 1; return 0; }
memcpy(this->TxBuf, _TxBuf_, _TxBufLength_);
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_RX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
if ( this->TimerTimeoutCompValue > (0xFFFFU - this->TimerInterFrameCompValue) )
{
*this->TIMN.OCRNB = 0xFFFFU;
this->TimerTimeoutOverflow = (uint16_t)( this->TimerTimeoutCompValue - (0xFFFFU - this->TimerInterFrameCompValue) );
}
else
{
*this->TIMN.OCRNB = (uint16_t)(this->TimerTimeoutCompValue + this->TimerInterFrameCompValue);
this->TimerTimeoutOverflow = 0;
}
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe and Response timeouts
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos) | (1U << USRTN_TIM_TIMSK_OCIEB_Pos);
this->TxBufCounter = 1;
this->TxBufLength = _TxBufLength_;
this->RxBufCounter = 0;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestSync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) { }
if ( this->SendRequestAsync(_TxBuf_, _TxBufLength_) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) { }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
if ( _TxBufLength_ == 0 ) { this->ERROR_STATUS.BF.TxZerolength = 1; return 0; }
else if ( _TxBufLength_ > IDIBUS_SERIAL_TX_BUF_SIZE ) { this->ERROR_STATUS.BF.TxOverflow = 1; return 0; }
this->TransferComplete = 0;
memcpy(this->TxBuf, _TxBuf_, _TxBufLength_);
this->RequestType = _IDIBUS_SERIAL_TX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe Timeout
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos);
this->TxBufCounter = 1;
this->TxBufLength = _TxBufLength_;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteSync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->WriteAsync(_TxBuf_, _TxBufLength_) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t *IdiBusSerial::getTxBufPointer(void)
{
if ( this->TransferComplete ) { return this->TxBuf; }
else { return NULL; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t *IdiBusSerial::getRxBufPointer (void)
{
return this->RxBuf;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestAsync(uint16_t DataLength)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_RX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
if ( this->TimerTimeoutCompValue > (0xFFFFU - this->TimerInterFrameCompValue) )
{
*this->TIMN.OCRNB = 0xFFFFU;
this->TimerTimeoutOverflow = (uint16_t)( this->TimerTimeoutCompValue - (0xFFFFU - this->TimerInterFrameCompValue) );
}
else
{
*this->TIMN.OCRNB = (uint16_t)(this->TimerTimeoutCompValue + this->TimerInterFrameCompValue);
this->TimerTimeoutOverflow = 0;
}
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe and Response timeouts
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos) | (1U << USRTN_TIM_TIMSK_OCIEB_Pos);
this->TxBufCounter = 1;
this->TxBufLength = DataLength;
this->RxBufCounter = 0;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestSync(uint16_t DataLength)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->SendRequestAsync(DataLength) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteAsync(uint16_t DataLength)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe Timeout
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos);
this->TxBufCounter = 1;
this->TxBufLength = DataLength;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteSync(uint16_t DataLength)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->WriteAsync(DataLength) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::IsTransferComplete(void) { return this->TransferComplete; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t IdiBusSerial::GetRxBufCounter(void) { return this->RxBufCounter; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IDIBUS_SERIAL_ERROR_STATUS_TYPE IdiBusSerial::GetErrorStatus(void) { return this->ERROR_STATUS; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint32_t IdiBusSerial::GetBaudrate(void) { return this->BAUDRATE; }
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiBusSerial::USART_RxInterruptFunc (void)
{
*this->TIMN.TCNTN = 0;
if ( (*this->USARTN.UCSRNA & ( (1U<<USARTN_UCSRNA_FE_Pos)|(1U<<USARTN_UCSRNA_DOR_Pos)|(1U<<USARTN_UCSRNA_UPE_Pos)) ) == 0 )
{
if ( this->RxBufCounter < IDIBUS_SERIAL_RX_BUF_SIZE ) { this->RxBuf[this->RxBufCounter++] = *this->USARTN.UDRN; }
else { this->ERROR_STATUS.BF.RxOverflow = 1; (void)*this->USARTN.UDRN; }
}
else { this->ERROR_STATUS.BF.LLComERR = 1; (void)*this->USARTN.UDRN; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::USART_TxInterruptFunc (void)
{
if ( this->TxBufCounter != this->TxBufLength ) { *this->USARTN.UDRN = this->TxBuf[this->TxBufCounter++]; }
else
{
switch (this->RequestType)
{
case (_IDIBUS_SERIAL_TX_RX_) : {
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK;
*this->USARTN.UCSRNB |= (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos);
*this->TIMN.TCCRNB = IDIBUS_SERIAL_TIMER_PR_REG; //Timer Start
break; }
case (_IDIBUS_SERIAL_TX_) : {
*this->TIMN.TCCRNB = IDIBUS_SERIAL_TIMER_PR_REG; //Timer Start
break; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::TIM_COMPA_InterruptFunc (void)
{
switch (this->RequestType)
{
case ( _IDIBUS_SERIAL_TX_RX_ ) : {
if ( this->RxBufCounter != 0 ) // Interframe Timeout < Response < Request Timeout
{
*this->TIMN.TCCRNB = 0; // Timer Stop
*this->USARTN.UCSRNB &= ~( (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos) ); // Rx Periph Stop
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK; // Dir to TX
this->TransferComplete = 1; // Complete
}
break; }
case (_IDIBUS_SERIAL_TX_) : {
*this->TIMN.TCCRNB = 0; // Timer Stop
this->TransferComplete = 1; // Complete
break; }
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::TIM_COMPB_InterruptFunc (void)
{
if ( this->TimerTimeoutOverflow != 0 )
{
*this->TIMN.OCRNB = this->TimerTimeoutOverflow;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFB_Pos);
this->TimerTimeoutOverflow = 0;
}
else
{
*this->TIMN.TCCRNB = 0; //Timer Stop
*this->USARTN.UCSRNB &= ~( (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos) );
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK;
this->ERROR_STATUS.BF.TimeoutERR = 1;
this->TransferComplete = 1;
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSerial::GetGpioParams(IDIBUS_SERIAL_GPIO_INIT *InitSTR, IDIBUS_SERIAL_GPIO *gpio)
{
if ( InitSTR->PIN_NUM > 7 ) { return 0; }
if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTA ) { gpio->PORT = &PORTA; gpio->DDR = &DDRA; gpio->PIN = &PINA; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTB ) { gpio->PORT = &PORTB; gpio->DDR = &DDRB; gpio->PIN = &PINB; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTC ) { gpio->PORT = &PORTC; gpio->DDR = &DDRC; gpio->PIN = &PINC; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTD ) { gpio->PORT = &PORTD; gpio->DDR = &DDRD; gpio->PIN = &PIND; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTE ) { gpio->PORT = &PORTE; gpio->DDR = &DDRE; gpio->PIN = &PINE; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTF ) { gpio->PORT = &PORTF; gpio->DDR = &DDRF; gpio->PIN = &PINF; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTG ) { gpio->PORT = &PORTG; gpio->DDR = &DDRG; gpio->PIN = &PING; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTH ) { gpio->PORT = &PORTH; gpio->DDR = &DDRH; gpio->PIN = &PINH; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTJ ) { gpio->PORT = &PORTJ; gpio->DDR = &DDRJ; gpio->PIN = &PINJ; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTK ) { gpio->PORT = &PORTK; gpio->DDR = &DDRK; gpio->PIN = &PINK; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTL ) { gpio->PORT = &PORTL; gpio->DDR = &DDRL; gpio->PIN = &PINL; }
else { return 0; }
gpio->PIN_MASK = (0x01U << InitSTR->PIN_NUM);
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::GetGpioParamsArduino(uint8_t PinNum, IDIBUS_SERIAL_GPIO *gpio)
{
uint8_t PortCode;
if ( (PinNum >= NUM_DIGITAL_PINS) || ((PortCode = digitalPinToPort(PinNum)) == NOT_A_PIN) ) { return 0; }
gpio->PIN_MASK = digitalPinToBitMask(PinNum);
gpio->PORT = portOutputRegister(PortCode);
gpio->DDR = portModeRegister(PortCode);
gpio->PIN = portInputRegister(PortCode);
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,123 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SERIAL_H_
#define _IDIBUS_SERIAL_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusSerialDefs.h"
#include "IdiBusInterruptsList.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_SERIAL_USARTN_NUMBER {
IDIBUS_SERIAL_USART0,
IDIBUS_SERIAL_USART1,
IDIBUS_SERIAL_USART2,
IDIBUS_SERIAL_USART3
};
enum IDIBUS_SERIAL_TIMER_NUMBER {
IDIBUS_TIMER_1 = 1,
IDIBUS_TIMER_3 = 3,
IDIBUS_TIMER_4,
IDIBUS_TIMER_5
};
enum IDIBUS_SERIAL_USARTN_CONFIG {
IDIBUS_SERIAL_8N1,
IDIBUS_SERIAL_8N2,
IDIBUS_SERIAL_8E1,
IDIBUS_SERIAL_8E2,
IDIBUS_SERIAL_8O1,
IDIBUS_SERIAL_8O2
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUMBER;
enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUMBER;
enum IDIBUS_SERIAL_USARTN_CONFIG CONFIG;
uint8_t RS485_DIR_PIN;
uint8_t BAUDRATE_DIPSW_S0_PIN;
uint8_t BAUDRATE_DIPSW_S1_PIN;
uint8_t BAUDRATE_DIPSW_S2_PIN;
} IDIBUS_SERIAL_INIT_TYPEDEF;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUMBER;
enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUMBER;
enum IDIBUS_SERIAL_USARTN_CONFIG CONFIG;
IDIBUS_SERIAL_GPIO_INIT RS485_DIR_GPIO;
struct {
IDIBUS_SERIAL_GPIO_INIT S0;
IDIBUS_SERIAL_GPIO_INIT S1;
IDIBUS_SERIAL_GPIO_INIT S2;
} BAUDRATE_DIPSW;
} IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusSerial : public IdiBusCallbackInterface {
public :
IdiBusSerial(void);
uint8_t Init(IDIBUS_SERIAL_INIT_TYPEDEF *InitT);
uint8_t Init(IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF *InitT);
void SetBaudrate(enum IDIBUS_SERIAL_BAUDRATE Baudrate);
void UpdateBaudrateFromDipSwitch(void);
void Start (void); // Hold Line
void Stop (void); // TX/RX disable, Release Line
uint8_t SendRequestAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t SendRequestSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t WriteSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t WriteAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t IsTransferComplete(void);
uint16_t GetRxBufCounter(void);
IDIBUS_SERIAL_ERROR_STATUS_TYPE GetErrorStatus(void);
uint32_t GetBaudrate(void);
private :
IDIBUS_SERIAL_USART_HW_TYPE USARTN;
IDIBUS_SERIAL_USARTN_16BIT_TIMER TIMN;
IDIBUS_SERIAL_GPIO RS485_DIR_GPIO;
IDIBUS_SERIAL_BAUDRATE_DIPSW_TYPE BAUDRATE_DIPSW;
uint32_t BAUDRATE;
uint8_t TxBuf[IDIBUS_SERIAL_TX_BUF_SIZE];
uint16_t TxBufLength;
uint16_t TxBufCounter;
uint8_t RxBuf[IDIBUS_SERIAL_RX_BUF_SIZE];
uint16_t RxBufCounter;
IDIBUS_SERIAL_ERROR_STATUS_TYPE ERROR_STATUS;
uint16_t TimerInterFrameCompValue;
uint16_t TimerTimeoutCompValue;
uint16_t TimerTimeoutOverflow;
enum IDIBUS_SERIAL_REQUEST_TYPE RequestType;
volatile uint8_t TransferComplete;
uint16_t InitProtectionVar;
uint8_t InitState;
// Interrupt Vectors Pointers
virtual void USART_RxInterruptFunc(void) override;
virtual void USART_TxInterruptFunc(void) override;
virtual void TIM_COMPA_InterruptFunc(void) override;
virtual void TIM_COMPB_InterruptFunc(void) override;
// Routine
uint8_t BaseInit(enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUM, enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUM, enum IDIBUS_SERIAL_USARTN_CONFIG CONF);
uint8_t GetGpioParams(IDIBUS_SERIAL_GPIO_INIT *InitSTR, IDIBUS_SERIAL_GPIO *gpio);
uint8_t GetGpioParamsArduino(uint8_t PinNum, IDIBUS_SERIAL_GPIO *gpio);
void SetBaudrateLL(uint32_t Baudrate);
protected :
uint8_t *getTxBufPointer (void);
uint8_t *getRxBufPointer (void);
uint8_t SendRequestAsync(uint16_t DataLength);
uint8_t SendRequestSync(uint16_t DataLength);
uint8_t WriteAsync(uint16_t DataLength);
uint8_t WriteSync(uint16_t DataLength);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_SERIAL_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,138 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SERIAL_COMDEFS_H_
#define _IDIBUS_SERIAL_COMDEFS_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#if defined (__AVR_ATmega2560__)
#define USARTN_UCSRNA_RXC_Pos 7U
#define USARTN_UCSRNA_TXC_Pos 6U
#define USARTN_UCSRNA_UDR_Pos 5U
#define USARTN_UCSRNA_FE_Pos 4U
#define USARTN_UCSRNA_DOR_Pos 3U
#define USARTN_UCSRNA_UPE_Pos 2U
#define USARTN_UCSRNA_U2X_Pos 1U
#define USARTN_UCSRNA_MPCM_Pos 0U
#define USARTN_UCSRNB_RXCIE_Pos 7U
#define USARTN_UCSRNB_TXCIE_Pos 6U
#define USARTN_UCSRNB_UDRIE_Pos 5U
#define USARTN_UCSRNB_RXEN_Pos 4U
#define USARTN_UCSRNB_TXEN_Pos 3U
#define USARTN_UCSRNB_UCSZ2_Pos 2U
#define USARTN_UCSRNB_RXB8_Pos 1U
#define USARTN_UCSRNB_TXB8_Pos 0U
#define USARTN_UCSRNC_UMSEL1 7U
#define USARTN_UCSRNC_UMSEL0 6U
#define USARTN_UCSRNC_UPM1 5U
#define USARTN_UCSRNC_UPM0 4U
#define USARTN_UCSRNC_USBS 3U
#define USARTN_UCSRNC_UCSZ1 2U
#define USARTN_UCSRNC_UCSZ0 1U
#define USARTN_UCSRNC_UCPOL 0U
#define USARTN_TIM_TCCRA_WGMN1_Pos 1U
#define USARTN_TIM_TCCRB_PR1 1U
#define USARTN_TIM_TCCRB_PR8 2U
#define USARTN_TIM_TCCRB_PR64 3U
#define USARTN_TIM_TCCRB_PR256 4U
#define USARTN_TIM_TCCRB_PR1024 5U
#define USRTN_TIM_TIMSK_TOIE_Pos 0U
#define USRTN_TIM_TIMSK_OCIEA_Pos 1U
#define USRTN_TIM_TIMSK_OCIEB_Pos 2U
#define USRTN_TIM_TIMSK_OCIEC_Pos 3U
#define USARTN_TIM_TIFR_TOV_Pos 0U
#define USARTN_TIM_TIFR_OCFA_Pos 1U
#define USARTN_TIM_TIFR_OCFB_Pos 2U
#define USARTN_TIM_TIFR_OCFC_Pos 3U
#endif //#if defined (__AVR_ATmega2560__)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_BAUDRATE_DSW_CODE_19200B 0x00
#define IDIBUS_BAUDRATE_DSW_CODE_500K 0x01
#define IDIBUS_BAUDRATE_DSW_CODE_2400B 0x02
#define IDIBUS_BAUDRATE_DSW_CODE_9600B 0x03
#define IDIBUS_BAUDRATE_DSW_CODE_115200B 0x04
#define IDIBUS_BAUDRATE_DSW_CODE_250K 0x05
#define IDIBUS_BAUDRATE_DSW_CODE_1M 0x06
#define IDIBUS_BAUDRATE_DSW_CODE_10M 0x07
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_SERIAL_TIMER_PR_REG USARTN_TIM_TCCRB_PR64
#if IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR1
#define IDIBUS_SERIAL_TIMER_PR_VALUE 1U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR8
#define IDIBUS_SERIAL_TIMER_PR_VALUE 8U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR64
#define IDIBUS_SERIAL_TIMER_PR_VALUE 64U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR256
#define IDIBUS_SERIAL_TIMER_PR_VALUE 256U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR1024
#define IDIBUS_SERIAL_TIMER_PR_VALUE 1024U
#else
#error "Idibus Serial: Incorrect Timer Prescaler value !"
#endif //#if IDIBUS_T_CPU==CPU_ATmega2560
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_SERIAL_TX_BUF_SIZE IDIMMES_MAX_MES_SIZE
#define IDIBUS_SERIAL_RX_BUF_SIZE IDISMES_MAX_MES_SIZE
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_SERIAL_REQUEST_TYPE {
_IDIBUS_SERIAL_TX_RX_,
_IDIBUS_SERIAL_TX_,
//Alarm
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
volatile uint8_t *UCSRNA;
volatile uint8_t *UCSRNB;
volatile uint8_t *UCSRNC;
volatile uint16_t *UBRRN;
volatile uint8_t *UDRN;
} IDIBUS_SERIAL_USART_HW_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
volatile uint8_t *TCCRNA;
volatile uint8_t *TCCRNB;
volatile uint8_t *TIMSKN;
volatile uint8_t *TIFRN;
volatile uint16_t *OCRNA;
volatile uint16_t *OCRNB;
volatile uint16_t *TCNTN;
} IDIBUS_SERIAL_USARTN_16BIT_TIMER;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef union {
uint8_t SumVar;
struct {
uint8_t TimeoutERR : 1;
uint8_t TxOverflow : 1;
uint8_t RxOverflow : 1;
uint8_t LLComERR : 1;
uint8_t TxZerolength : 1;
uint8_t Reserved : 3;
} BF;
} IDIBUS_SERIAL_ERROR_STATUS_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
uint8_t PIN_MASK;
volatile uint8_t *PORT;
volatile uint8_t *DDR;
volatile uint8_t *PIN;
} IDIBUS_SERIAL_GPIO;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
uint8_t PIN_NUM;
volatile uint8_t *PORT;
} IDIBUS_SERIAL_GPIO_INIT;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
IDIBUS_SERIAL_GPIO S0_Gpio;
IDIBUS_SERIAL_GPIO S1_Gpio;
IDIBUS_SERIAL_GPIO S2_Gpio;
} IDIBUS_SERIAL_BAUDRATE_DIPSW_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_SERIAL_COMDEFS_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,122 @@
//#############################################################################################################################################################################################################
#include "IdiBusSerialLine.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerialLine::IdiBusSerialLine(void) : IdiBusSerial()
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerialLine::sendMMES (IdiBusMMES *MMES)
{
if ( MMES->IsValid() == 0 ) { return IDIERMST_INVALID_TX_REQUEST_FORMAT; }
uint8_t *TxMesBuf = this->getTxBufPointer();
if ( TxMesBuf == NULL ) { return IDIERMST_TX_MES; }
uint8_t *RxMesBuf = this->getRxBufPointer();
uint8_t DataPos;
// Fill Header
TxMesBuf[IDIMMES_ADDR_Pos] = MMES->SlAddr;
TxMesBuf[IDIMMES_MMPS_Pos] = (MMES->MMPS.LongMes << IDIMMES_MMPS_LONG_MES_Pos) |
(IDIMMES_MMPS_MES_TYPE_MMES << IDIMMES_MMPS_MES_TYPE_Pos) |
(0x00U << IDIMMES_MMPS_FAST_FUNC_Pos) |
(MMES->MMPS.AlarmMes << IDIMMES_MMPS_ALARM_FRAME_Pos) |
(MMES->MMPS.EncryptedAes << IDIMMES_MMPS_ENCRYPTED_AES_Pos);
TxMesBuf[IDIMMES_DEV_Pos] = (MMES->DEV.NUM << IDIMMES_DEV_NUM_Pos) | (MMES->DEV.ALLCH << IDIMMES_DEV_ALLCH_Pos);
TxMesBuf[IDIMMES_CHNL_Pos] = (MMES->CHNL.NUM << IDIMMES_CHNL_NUM_Pos) | (MMES->CHNL.ALLSAME << IDIMMES_CHNL_ALLSAME_Pos);
DataPos = IDIMMES_CHNL_Pos + 1;
// If Not Fast Function add command/function
if ( MMES->ComFunc < 16 ) { TxMesBuf[IDIMMES_MMPS_Pos] |= (MMES->ComFunc << IDIMMES_MMPS_FAST_FUNC_Pos); }
else { TxMesBuf[DataPos++] = MMES->ComFunc; }
// Fill Data
if ( MMES->TxDataLength != 0 ) { memcpy(&TxMesBuf[DataPos], &MMES->TxData[0], MMES->TxDataLength); }
// Add CRC
uint16_t CRC = MODBUS_CRC16::CRC16_TF(&TxMesBuf[0], (uint16_t)(DataPos + MMES->TxDataLength));
TxMesBuf[DataPos + MMES->TxDataLength] = (uint8_t)(CRC >> 8);
TxMesBuf[DataPos + MMES->TxDataLength + 1] = (uint8_t) CRC;
if ( this->SendRequestSync(DataPos + MMES->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
IDIBUS_SERIAL_ERROR_STATUS_TYPE SerialError = this->GetErrorStatus();
uint16_t RxMessageLength;
if ( SerialError.BF.TimeoutERR != 0 ) { return IDIERMST_RCV_TIMEOUT; }
else if ( (SerialError.SumVar != 0) || ((RxMessageLength = this->GetRxBufCounter()) < IDISMES_MIN_MES_SIZE) ) { return IDIERMST_MES_RX_INTEGRITY; }
else
{
uint16_t CRC = MODBUS_CRC16::CRC16_TF( &RxMesBuf[0], (uint16_t)(RxMessageLength-MODBUS_CRC16_SIZE) );
uint16_t ReceivedCRC = ((uint16_t)RxMesBuf[RxMessageLength-2] << 8) | RxMesBuf[RxMessageLength-1];
if ( CRC != ReceivedCRC ) { return IDIERMST_CRC; }
else if ( RxMesBuf[IDISMES_ADDR_Pos] != MMES->SlAddr ) { return IDIERMST_INVALID_ADDR_NUM; }
else
{
MMES->RxDataLength = RxMessageLength - (IDISMES_ERROR_Pos + MODBUS_CRC16_SIZE);
MMES->RxData = &RxMesBuf[IDISMES_ERROR_Pos];
return IDIER_NOPE;
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerialLine::sendMMESG (IdiBusMMESG *MMESG)
{
if ( MMESG->IsValid() == 0 ) { return IDIERMST_INVALID_TX_REQUEST_FORMAT ; }
uint8_t *TxMesBuf = this->getTxBufPointer();
if ( TxMesBuf == NULL ) { return IDIERMST_TX_MES; }
uint8_t *RxMesBuf = this->getRxBufPointer();
uint8_t DataPos;
// Fill Header
TxMesBuf[IDIMMES_ADDR_Pos] = MMESG->SlAddr;
TxMesBuf[IDIMMES_MMPS_Pos] = (MMESG->MMPS.LongMes << IDIMMES_MMPS_LONG_MES_Pos) |
(IDIMMES_MMPS_MES_TYPE_MMESG << IDIMMES_MMPS_MES_TYPE_Pos) |
(0x00 << IDIMMES_MMPS_FAST_FUNC_Pos) |
(MMESG->MMPS.AlarmMes << IDIMMES_MMPS_ALARM_FRAME_Pos) |
(MMESG->MMPS.EncryptedAes << IDIMMES_MMPS_ENCRYPTED_AES_Pos);
DataPos = IDIMMES_MMPS_Pos + 1;
// If Not Fast Function add command/function
if ( MMESG->ComFunc < 16 ) { TxMesBuf[IDIMMES_MMPS_Pos] |= (MMESG->ComFunc << IDIMMES_MMPS_FAST_FUNC_Pos); }
else { TxMesBuf[DataPos++] = MMESG->ComFunc; }
// Fill Data
if ( MMESG->TxDataLength != 0 ) { memcpy(&TxMesBuf[DataPos], &MMESG->TxData[0], MMESG->TxDataLength); }
// Add CRC
uint16_t CRC = MODBUS_CRC16::CRC16_TF(&TxMesBuf[0], (uint16_t)(DataPos + MMESG->TxDataLength));
TxMesBuf[DataPos + MMESG->TxDataLength] = (uint8_t)(CRC >> 8);
TxMesBuf[DataPos + MMESG->TxDataLength + 1] = (uint8_t) CRC;
if ( MMESG->IsGroupAddr() != 0 )
{
if ( this->WriteSync(DataPos + MMESG->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
return IDIER_NOPE;
}
else //Module commands
{
if ( this->SendRequestSync(DataPos + MMESG->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
uint16_t RxMessageLength;
IDIBUS_SERIAL_ERROR_STATUS_TYPE SerialError = this->GetErrorStatus();
if ( SerialError.BF.TimeoutERR != 0 ) { return IDIERMST_RCV_TIMEOUT; }
else if ( (SerialError.SumVar != 0) || ((RxMessageLength = this->GetRxBufCounter()) < IDISMES_MIN_MES_SIZE) ) { return IDIERMST_TX_MES; }
else
{
uint16_t CRC = MODBUS_CRC16::CRC16_TF( &RxMesBuf[0], (uint16_t)(RxMessageLength-MODBUS_CRC16_SIZE) );
uint16_t ReceivedCRC = ((uint16_t)RxMesBuf[RxMessageLength-2] << 8) | RxMesBuf[RxMessageLength-1];
if ( CRC != ReceivedCRC ) { return IDIERMST_CRC; }
else if ( RxMesBuf[IDISMES_ADDR_Pos] != MMESG->SlAddr ) { return IDIERMST_INVALID_ADDR_NUM; }
{
MMESG->RxDataLength = RxMessageLength - (IDISMES_ERROR_Pos + MODBUS_CRC16_SIZE);
MMESG->RxData = &RxMesBuf[IDISMES_ERROR_Pos];
return IDIER_NOPE;
}
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,17 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_STD_LINE_H_
#define _IDIBUS_STD_LINE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusSerial.h"
#include "IdiBusMes.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusSerialLine : public IdiBusSerial {
public :
IdiBusSerialLine();
uint8_t sendMMES (IdiBusMMES *MMES); // return ErrorCode but not look into [data]
uint8_t sendMMESG (IdiBusMMESG *MMESG);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_STD_LINE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,349 @@
//#############################################################################################################################################################################################################
#include "IdiBusSlave.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSlave::IdiBusSlave( IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress )
{
this->Line = SlaveLine;
this->Address = SlaveAddress;
this->CRC_AVR.CRC_ErrAvrBufCounter = 0;
this->CRC_AVR.CRC_ErrAvrBufPos = 0;
this->CRC_AVR.CRC_ErrAvrBufSum = 0;
this->CRC_MultipleError = 0;
this->ModuleError = IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSlave::IdiBusSlave(void)
{
this->Line = NULL;
this->Address = 1;
this->CRC_AVR.CRC_ErrAvrBufCounter = 0;
this->CRC_AVR.CRC_ErrAvrBufPos = 0;
this->CRC_AVR.CRC_ErrAvrBufSum = 0;
this->CRC_MultipleError = 0;
this->ModuleError = IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::Init(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress)
{
this->Line = SlaveLine;
this->Address = SlaveAddress;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::SendRequestMMES(IdiBusMMES *MMES)
{
if ( this->Line == NULL ) { return IDIERMST_TX_MES; }
uint8_t RequestError = this->Line->sendMMES(MMES);
this->CrcAvrErrorCalc(RequestError);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMES->IsModuleError(MMES->RxData[0]) )
{
if ( MMES->RxDataLength != 1 ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { this->ModuleError = MMES->RxData[0]; return MMES->RxData[0]; }
}
this->ModuleError = IDIER_NOPE;
return IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::SendRequestMMESG(IdiBusMMESG *MMESG)
{
if ( this->Line == NULL ) { return IDIERMST_TX_MES; }
uint8_t RequestError = this->Line->sendMMESG(MMESG);
this->CrcAvrErrorCalc(RequestError);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG->IsGroupAddr() == 0 )
{
if ( MMESG->IsModuleError(MMESG->RxData[0]) )
{
if ( MMESG->RxDataLength != 1 ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { this->ModuleError = MMESG->RxData[0]; return MMESG->RxData[0]; }
}
}
this->ModuleError = IDIER_NOPE;
return IDIER_NOPE;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::SendModuleSimpleSetCommand(uint8_t Command)
{
IdiBusMMESG MMESG(this->Address);
MMESG.ComFunc = Command;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if (MMESG.RxDataLength != 1) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { return MMESG.RxData[0]; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::SendModuleSimpleSetCommand(uint8_t Command, uint8_t *TxData, uint16_t TxDataLength)
{
IdiBusMMESG MMESG(this->Address, TxData, TxDataLength);
MMESG.ComFunc = Command;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if (MMESG.RxDataLength != 1) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { return MMESG.RxData[0]; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::CrcAvrErrorCalc(uint8_t ErrorCode)
{
uint8_t ErrorBufCode;
if ( ErrorCode == IDIERMST_CRC ) { ErrorBufCode = 1; }
else { ErrorBufCode = 0; }
this->CRC_AVR.CRC_ErrAvrBufSum = this->CRC_AVR.CRC_ErrAvrBufSum + ErrorBufCode - this->CRC_AVR.CRC_ErrAvrBuf[this->CRC_AVR.CRC_ErrAvrBufPos];
this->CRC_AVR.CRC_ErrAvrBuf[this->CRC_AVR.CRC_ErrAvrBufPos] = ErrorBufCode;
if ( this->CRC_AVR.CRC_ErrAvrBufPos == (IDIER_MULTIPLE_CRC_AVRBUF_SIZE - 1) ) { this->CRC_AVR.CRC_ErrAvrBufPos = 0; }
else { this->CRC_AVR.CRC_ErrAvrBufPos++; }
if ( this->CRC_AVR.CRC_ErrAvrBufCounter < IDIER_MULTIPLE_CRC_AVRBUF_SIZE ) { this->CRC_AVR.CRC_ErrAvrBufCounter++; }
else
{
if ( this->CRC_AVR.CRC_ErrAvrBufSum >= IDIER_MULTIPLE_CRC_AVRBUF_THR ) { this->CRC_MultipleError = 1; }
else { this->CRC_MultipleError = 0; }
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_Init(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Init); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Init(uint8_t Group) { return (Group > IDIBUS_GROUP_LAST_NUMBER) ? IDIERMST_INVALID_TX_PARAM : this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Init, &Group, 1); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_ShtDown(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_ShtDown); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Freeze(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Freeze); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Resume(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Resume); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_DummyModule(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_DummyModule); }
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_SendTimeDate(IdiTimeFormat Time, IdiDateFormat Date)
{
if ( (Time.isValid() == 0) || (Date.isValid() == 0) ) { return IDIERMST_INVALID_TX_PARAM; }
uint8_t TxData[IDIMMES_C_DATETIME_LENGTH];
Time.getBufForMMES(&TxData[IDIMMES_C_DATETIME_TIME_Pos]);
Date.getBufForMMES(&TxData[IDIMMES_C_DATETIME_DATE_Pos]);
return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_SendTimeDate, TxData, IDIMMES_C_DATETIME_LENGTH );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_ReadDevFullSN_MS(void)
{
IdiBusMMESG MMESG (this->Address);
MMESG.ComFunc = IDIMMES_COM_C_ReadDevFullSN_MS;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG.RxDataLength != (IDISN_FULL_LENGTH - IDISN_VARP_AES256_Length + 2 + 1) ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMESG.RxData[0] != IDIER_NOPE ) { return MMESG.RxData[0]; }
else
{
this->ModuleST.parseSmesDataNoAes(&MMESG.RxData[1]);
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnIPv4IPv6(uint32_t IPv4, uint32_t IPv6_B3, uint32_t IPv6_B2, uint32_t IPv6_B1, uint32_t IPv6_B0)
{
uint8_t TxData[IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length];
TxData[0] = (uint8_t)(IPv4 >> 24);
TxData[1] = (uint8_t)(IPv4 >> 16);
TxData[2] = (uint8_t)(IPv4 >> 8);
TxData[3] = (uint8_t)(IPv4);
TxData[4] = (uint8_t)(IPv6_B3 >> 24);
TxData[5] = (uint8_t)(IPv6_B3 >> 16);
TxData[6] = (uint8_t)(IPv6_B3 >> 8);
TxData[7] = (uint8_t)(IPv6_B3);
TxData[8] = (uint8_t)(IPv6_B2 >> 24);
TxData[9] = (uint8_t)(IPv6_B2 >> 16);
TxData[10] = (uint8_t)(IPv6_B2 >> 8);
TxData[11] = (uint8_t)(IPv6_B2);
TxData[12] = (uint8_t)(IPv6_B1 >> 24);
TxData[13] = (uint8_t)(IPv6_B1 >> 16);
TxData[14] = (uint8_t)(IPv6_B1 >> 8);
TxData[15] = (uint8_t)(IPv6_B1);
TxData[16] = (uint8_t)(IPv6_B0 >> 24);
TxData[17] = (uint8_t)(IPv6_B0 >> 16);
TxData[18] = (uint8_t)(IPv6_B0 >> 8);
TxData[19] = (uint8_t)(IPv6_B0);
uint8_t RequestError = this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnIPv4IPv6, TxData, IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length );
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else
{
memcpy(this->ModuleST.SN.VAR.IPv4, &TxData[0], IDISN_VARP_IPv4_Length);
memcpy(this->ModuleST.SN.VAR.IPv6, &TxData[4], IDISN_VARP_IPv6_Length);
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnVerifyDates(IdiDateFormat VDate, IdiDateFormat VEXPDate)
{
if ( (VDate.isValid() == 0) || (VEXPDate.isValid() == 0) ) { return IDIERMST_INVALID_TX_PARAM; }
uint8_t TxData[IDIDATE_FORMAT_LENGTH * 2];
VDate.getBufForMMES(&TxData[0]);
VEXPDate.getBufForMMES(&TxData[IDIDATE_FORMAT_LENGTH]);
uint8_t RequestError = this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnVerifyDates, TxData, IDIDATE_FORMAT_LENGTH * 2 );
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else
{
this->ModuleST.SN.VAR.VerifDate = VDate;
this->ModuleST.SN.VAR.VerifExpDate = VEXPDate;
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnAES256(uint8_t *AES256_key) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnAES256, AES256_key, IDISN_VARP_AES256_Length); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_CheckModuleLongOp(void)
{
IdiBusMMESG MMESG (this->Address);
MMESG.ComFunc = IDIMMES_COM_C_CheckModuleLongOp;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG.RxDataLength != (IDILONGOP_MES_DATA_LENGTH + 1) ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMESG.RxData[0] != IDIER_NOPE ) { return MMESG.RxData[0]; }
else
{
uint8_t DataPos = 1;
this->ModuleLongOpData.State = MMESG.RxData[DataPos + IDILONGOP_STATE_Pos];
this->ModuleLongOpData.Timeout = ((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 0] << 24) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 1] << 16) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 2] << 8 ) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 3] );
return IDIER_NOPE;
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_Dummy(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.ComFunc = IDIMMES_COM_C_Dummy;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { CHNL->MMES_Error = MMES.RxData[0]; }
return CHNL->MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_AssignGroup(uint8_t Device, uint8_t Channel, uint8_t Group)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
if ( Group > IDIBUS_GROUP_LAST_NUMBER ) { CHNL->MMES_Error = IDIERMST_INVALID_TX_PARAM; }
else
{
IdiBusMMES MMES(this->Address, &Group, 1);
MMES.ComFunc = IDIMMES_COM_C_AssignGroup;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { CHNL->MMES_Error = MMES.RxData[0]; }
}
return CHNL->MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_CheckChannelLongOp(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.ComFunc = IDIMMES_COM_C_CheckChannelLongOp;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != (IDILONGOP_MES_DATA_LENGTH + 1) ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMES.RxData[0] != IDIER_NOPE ) { CHNL->MMES_Error = MMES.RxData[0]; }
else
{
CHNL->MMES_Error = IDIER_NOPE;
uint8_t DataPos = 1;
CHNL->LONG_OP.State = MMES.RxData[DataPos + IDILONGOP_STATE_Pos];
CHNL->LONG_OP.Timeout = ((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 0] << 24) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 1] << 16) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 2] << 8 ) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 3] );
}
return CHNL->MMES_Error;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::getAddress(void) { return this->Address; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::setAes256ToSn(uint8_t *AES256_key) { memcpy(this->ModuleST.SN.VAR.AES, AES256_key, IDISN_VARP_AES256_Length); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusLongOpData IdiBusSlave::getModuleLongOpData(void) { return this->ModuleLongOpData; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusLongOpData IdiBusSlave::getChLongOpData(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( ((DEV = this->getDevice(Device)) != NULL) && ((CHNL = DEV->getChannel(Channel)) != NULL) )
{
return CHNL->LONG_OP;
}
IdiBusLongOpData NewData;
return NewData;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiMsaterState::parseSmesDataNoAes(uint8_t *Data)
{
this->STATE.B0S.StError = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_ST_ERROR_Pos) & 0x01;
this->STATE.B0S.StState = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_ST_STATE_Pos) & IDISTATUS_B0S_ST_STATE_Msk;
this->STATE.B0S.AesSupported = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_AES_SUPPORTED_Pos) & 0x01;
this->STATE.B0S.AesInstalled = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_AES_INSTALLED_Pos) & 0x01;
this->STATE.B0S.SendAlarmL0 = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_SEND_ALARM_L0_Pos) & 0x01;
this->STATE.B0S.SendAlarmL1 = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_SEND_ALARM_L1_Pos) & 0x01;
this->STATE.B1S.ModuleType = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_MODULE_TYPE_Pos) & IDISTATUS_B1S_MODULE_TYPE_Msk;
this->STATE.B1S.BridgeConnected = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_BRIDGE_CONNECTED_Pos) & 0x01;
this->STATE.B1S.SelfInit = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_SELF_INIT_Pos) & 0x01;
this->STATE.B1S.TimeoutLed = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_TIMEOUT_LED_Pos) & 0x01;
this->STATE.B1S.NoMMESTimeout = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_NO_MMES_TIMEOUT_Pos) & 0x01;
this->STATE.B1S.CatchAlarmL0 = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_CATCH_ALARM_L0_Pos) & 0x01;
this->STATE.B1S.CatchAlarmL1 = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_CATCH_ALARM_L1_Pos) & 0x01;
memcpy(this->SN.FIX.GS1_country, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_GS1_COUNTRY_Pos], IDISN_FIXP_GS1_COUNTRY_Length);
memcpy(this->SN.FIX.GS1_company, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_GS1_COMPANY_Pos], IDISN_FIXP_GS1_COMPANY_Length);
memcpy(this->SN.FIX.ModuleType, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_MODULE_TYPE_Pos], IDISN_FIXP_MODULE_TYPE_Length);
memcpy(this->SN.FIX.HW_rev, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_HW_REV_Pos], IDISN_FIXP_HW_REV_Length);
memcpy(this->SN.FIX.Serial, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_SERIAL_Pos], IDISN_FIXP_SERIAL_Length);
memcpy(this->SN.FIX.MAC, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_MAC_Pos], IDISN_FIXP_MAC_Length);
memcpy(this->SN.VAR.SW_rev, &Data[IDISTATUS_SN_Pos + IDISN_VARP_SW_REV_Pos], IDISN_VARP_SW_REV_Length);
memcpy(this->SN.VAR.IPv4, &Data[IDISTATUS_SN_Pos + IDISN_VARP_IPv4_Pos], IDISN_VARP_IPv4_Length);
memcpy(this->SN.VAR.IPv6, &Data[IDISTATUS_SN_Pos + IDISN_VARP_IPv6_Pos], IDISN_VARP_IPv6_Length);
uint8_t *VerifDateP = &Data[IDISTATUS_SN_Pos + IDISN_VARP_VERIF_DATE_Pos];
uint8_t *VerifExpDateP = &Data[IDISTATUS_SN_Pos + IDISN_VARP_EXPIR_DATE_Pos];
IdiDateFormat verifDate(VerifDateP[0], VerifDateP[1], VerifDateP[2], VerifDateP[3]);
IdiDateFormat verifExpDate(VerifExpDateP[0], VerifExpDateP[1], VerifExpDateP[2], VerifExpDateP[3]);
this->SN.VAR.VerifDate = verifDate;
this->SN.VAR.VerifExpDate = verifExpDate;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,121 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SLAVE_H_
#define _IDIBUS_SLAVE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusDateTime.h"
#include "IdiBusMes.h"
#include "IdiBusSerialLine.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiMsaterState {
public :
IDISTATUS_STATE_TYPE STATE;
struct {
struct {
uint8_t GS1_country[3];
uint8_t GS1_company[6];
uint8_t ModuleType[3];
uint8_t HW_rev[2];
uint8_t Serial[7];
uint8_t MAC[6];
} FIX;
struct VAR {
VAR() : VerifDate(0,0,0,0), VerifExpDate(0,0,0,0) {}
uint8_t SW_rev[2];
IdiDateFormat VerifDate;
IdiDateFormat VerifExpDate;
uint8_t IPv4[4];
uint8_t IPv6[16];
uint8_t AES[32];
} VAR;
} SN;
void parseSmesDataNoAes(uint8_t *Data);
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBusLongOpData {
public :
IdiBusLongOpData() { this->State = IDILONGOP_STATE_COMPLETE_NO_ERR; this->Timeout = 0; }
uint8_t State;
uint32_t Timeout;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusChannel {
public :
IdiBusChannel() { this->MMES_Error = IDIER_NOPE; }
IdiBusLongOpData LONG_OP;
uint8_t MMES_Error;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusDevice {
public :
IdiBusDevice (void *ParentModule) { this->Module = ParentModule; }
virtual IdiBusChannel *getChannel(uint8_t Num) { return NULL; }
protected :
void *Module;
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBusSlave {
public :
// Constructors and init
IdiBusSlave(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress);
IdiBusSlave(void);
void Init(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress);
// Standard communication API
uint8_t SendRequestMMES(IdiBusMMES *MMES);
uint8_t SendRequestMMESG(IdiBusMMESG *MMESG);
//Module commands (return ErrorCode)
uint8_t c_Init (void);
uint8_t c_Init (uint8_t Gpoup);
uint8_t c_ShtDown (void);
uint8_t c_Freeze (void);
uint8_t c_Resume (void);
uint8_t c_ReadDevFullSN_MS(void);
uint8_t c_WriteSnIPv4IPv6(uint32_t IPv4, uint32_t IPv6_B3, uint32_t IPv6_B2, uint32_t IPv6_B1, uint32_t IPv6_B0);
uint8_t c_WriteSnVerifyDates(IdiDateFormat VDate, IdiDateFormat VEXPDate);
uint8_t c_WriteSnAES256(uint8_t *AES256_key);
uint8_t c_SendTimeDate(IdiTimeFormat Time, IdiDateFormat Date);
uint8_t c_DummyModule(void);
uint8_t c_CheckModuleLongOp(void);
// Channel Commands
uint8_t c_Dummy(uint8_t Device, uint8_t Channel);
uint8_t c_AssignGroup(uint8_t Device, uint8_t Channel, uint8_t Group);
uint8_t c_CheckChannelLongOp(uint8_t Device, uint8_t Channel);
// Utils
uint8_t getAddress(void);
void setAes256ToSn(uint8_t *AES256_key);
IdiBusLongOpData getModuleLongOpData(void);
IdiBusLongOpData getChLongOpData(uint8_t Device, uint8_t Channel);
// Interface - must be overridden in derived classes
virtual IdiBusDevice *getDevice(uint8_t Num) { return NULL; }
protected :
IdiBusSerialLine *Line;
uint8_t Address;
IdiMsaterState ModuleST;
uint8_t ModuleError;
IdiBusLongOpData ModuleLongOpData;
uint8_t CRC_MultipleError;
struct {
uint8_t CRC_ErrAvrBuf[16];
uint8_t CRC_ErrAvrBufCounter;
uint8_t CRC_ErrAvrBufPos;
uint8_t CRC_ErrAvrBufSum;
} CRC_AVR;
uint8_t SendModuleSimpleSetCommand(uint8_t Command);
uint8_t SendModuleSimpleSetCommand(uint8_t Command, uint8_t *TxData, uint16_t TxDataLength);
void CrcAvrErrorCalc(uint8_t ErrorCode);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_SLAVE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,25 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SYSTEM_H_
#define _IDIBUS_SYSTEM_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "Arduino.h"
#include "pins_arduino.h"
#include <inttypes.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "IdiBusDefs.h"
#include "MODBUS_CRC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#ifndef F_CPU
#error "IdibusSerial: F_CPU not defined!"
#endif
#if defined __AVR_ATmega2560__
#else
#error "IdibusSerial: Unsupported ControllerType!"
#endif
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#ifndef _IDIBUS_SYSTEM_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,446 @@
//#############################################################################################################################################################################################################
#ifndef _INC_IDIBUS_DEFS_H_
#define _INC_IDIBUS_DEFS_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
#include "MODBUS_CRC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_BAUDRATE_DSW_CODE_19200B 0x00
#define IDIBUS_BAUDRATE_DSW_CODE_500K 0x01
#define IDIBUS_BAUDRATE_DSW_CODE_2400B 0x02
#define IDIBUS_BAUDRATE_DSW_CODE_9600B 0x03
#define IDIBUS_BAUDRATE_DSW_CODE_115200B 0x04
#define IDIBUS_BAUDRATE_DSW_CODE_250K 0x05
#define IDIBUS_BAUDRATE_DSW_CODE_1M 0x06
#define IDIBUS_BAUDRATE_DSW_CODE_10M 0x07
// Full timeout will be (InterframeTimeout + ResponseTimeout) for request(Write + Read) or InterframeTimeout for write(Write only)
#define IDIBUS_2400B_INTERFRAME_TIMEOUT_US 16042ULL //11 * 3.5 / Baudrate
#define IDIBUS_9600B_INTERFRAME_TIMEOUT_US 4011ULL
#define IDIBUS_19200B_INTERFRAME_TIMEOUT_US 2006ULL
#define IDIBUS_115200B_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_250K_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_500K_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_1M_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_10M_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_2400B_ALARM_TIMEOUT_US 34375ULL //11 * 3.5 / Baudrate
#define IDIBUS_9600B_ALARM_TIMEOUT_US 8594ULL
#define IDIBUS_19200B_ALARM_TIMEOUT_US 4297ULL
#define IDIBUS_115200B_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_250K_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_500K_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_1M_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_10M_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_2400B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_9600B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_19200B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_115200B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_250K_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_500K_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_1M_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_10M_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_2400B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_2400B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_9600B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_9600B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_19200B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_19200B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_115200B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_115200B_INTERFRAME_TIMEOUT_US)
#define IDIBUS_250K_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_250K_INTERFRAME_TIMEOUT_US )
#define IDIBUS_500K_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_500K_INTERFRAME_TIMEOUT_US )
#define IDIBUS_1M_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_1M_INTERFRAME_TIMEOUT_US )
#define IDIBUS_10M_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_10M_INTERFRAME_TIMEOUT_US )
enum IDIBUS_SERIAL_BAUDRATE {
IDIBUS_BAUDRATE_2400 = IDIBUS_BAUDRATE_DSW_CODE_2400B,
IDIBUS_BAUDRATE_9600 = IDIBUS_BAUDRATE_DSW_CODE_9600B,
IDIBUS_BAUDRATE_19200 = IDIBUS_BAUDRATE_DSW_CODE_19200B,
IDIBUS_BAUDRATE_115200 = IDIBUS_BAUDRATE_DSW_CODE_115200B,
IDIBUS_BAUDRATE_250K = IDIBUS_BAUDRATE_DSW_CODE_250K,
IDIBUS_BAUDRATE_500K = IDIBUS_BAUDRATE_DSW_CODE_500K,
IDIBUS_BAUDRATE_1M = IDIBUS_BAUDRATE_DSW_CODE_1M,
IDIBUS_BAUDRATE_10M = IDIBUS_BAUDRATE_DSW_CODE_10M
};
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_SEC 60U
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_MS ( IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_SEC * 1000U )
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_SEC 15U
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_MS ( IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_SEC * 1000U )
enum IDIBUS_RXTIMER_TIMEOUT_MODE {
IDIBUS_TIMER_MODE_RX_TIMEOUT = 0x00,
IDIBUS_TIMER_MODE_ALARM_TIMEOUT,
IDIBUS_TIMER_MODE_RESPONSE_TIMEOUT
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISN_FIXP_Pos 0U
#define IDISN_FIXP_GS1_COUNTRY_Pos ( IDISN_FIXP_Pos + 0U)
#define IDISN_FIXP_GS1_COUNTRY_Length 3
#define IDISN_FIXP_GS1_COMPANY_Pos ( IDISN_FIXP_GS1_COUNTRY_Pos + IDISN_FIXP_GS1_COUNTRY_Length )
#define IDISN_FIXP_GS1_COMPANY_Length 6
#define IDISN_FIXP_MODULE_TYPE_Pos ( IDISN_FIXP_GS1_COMPANY_Pos + IDISN_FIXP_GS1_COMPANY_Length )
#define IDISN_FIXP_MODULE_TYPE_Length 3
#define IDISN_FIXP_HW_REV_Pos ( IDISN_FIXP_MODULE_TYPE_Pos + IDISN_FIXP_MODULE_TYPE_Length )
#define IDISN_FIXP_HW_REV_Length 2
#define IDISN_FIXP_SERIAL_Pos ( IDISN_FIXP_HW_REV_Pos + IDISN_FIXP_HW_REV_Length )
#define IDISN_FIXP_SERIAL_Length 7
#define IDISN_FIXP_MAC_Pos ( IDISN_FIXP_SERIAL_Pos + IDISN_FIXP_SERIAL_Length )
#define IDISN_FIXP_MAC_Length 6
#define IDISN_FIXP_LENGTH ( IDISN_FIXP_GS1_COUNTRY_Length + IDISN_FIXP_GS1_COMPANY_Length + IDISN_FIXP_MODULE_TYPE_Length + \
IDISN_FIXP_HW_REV_Length + IDISN_FIXP_SERIAL_Length + IDISN_FIXP_MAC_Length )
#define IDISN_VARP_Pos IDISN_FIXP_LENGTH
#define IDISN_VARP_SW_REV_Pos ( IDISN_VARP_Pos + 0U )
#define IDISN_VARP_SW_REV_Length 2U
#define IDISN_VARP_VERIF_DATE_Pos ( IDISN_VARP_SW_REV_Pos + IDISN_VARP_SW_REV_Length )
#define IDISN_VARP_VERIF_DATE_Length 4U
#define IDISN_VARP_EXPIR_DATE_Pos ( IDISN_VARP_VERIF_DATE_Pos + IDISN_VARP_VERIF_DATE_Length )
#define IDISN_VARP_EXPIR_DATE_Length 4U
#define IDISN_VARP_IPv4_Pos ( IDISN_VARP_EXPIR_DATE_Pos + IDISN_VARP_EXPIR_DATE_Length )
#define IDISN_VARP_IPv4_Length 4U
#define IDISN_VARP_IPv6_Pos ( IDISN_VARP_IPv4_Pos + IDISN_VARP_IPv4_Length )
#define IDISN_VARP_IPv6_Length 16U
#define IDISN_VARP_AES256_Pos ( IDISN_VARP_IPv6_Pos + IDISN_VARP_IPv6_Length )
#define IDISN_VARP_AES256_Length 32U
#define IDISN_VARP_LENGTH ( IDISN_VARP_SW_REV_Length + IDISN_VARP_VERIF_DATE_Length + IDISN_VARP_EXPIR_DATE_Length + \
IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length + IDISN_VARP_AES256_Length )
#define IDISN_FULL_LENGTH ( IDISN_FIXP_LENGTH + IDISN_VARP_LENGTH )
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define ISIBUS_MASTER_MAIN_ADDR 255U
#define ISIBUS_MASTER_SPARE_ADDR 254U
#define IDIBUS_SLAVE_ADDR_MIN 1U
#define IDIBUS_SLAVE_ADDR_MAX 229U
#define IDIBUS_DEVELOPER_ADDR_0 250U
#define IDIBUS_DEVELOPER_ADDR_1 251U
#define IDIBUS_DEVELOPER_ADDR_2 252U
#define IDIBUS_DEVELOPER_ADDR_3 253U
#define IDIBUS_GROUP_0_ADDR 230U
#define IDIBUS_GROUP_1_ADDR 231U
#define IDIBUS_GROUP_2_ADDR 232U
#define IDIBUS_GROUP_3_ADDR 233U
#define IDIBUS_GROUP_4_ADDR 234U
#define IDIBUS_GROUP_5_ADDR 235U
#define IDIBUS_GROUP_6_ADDR 236U
#define IDIBUS_GROUP_7_ADDR 237U
#define IDIBUS_GROUP_8_ADDR 238U
#define IDIBUS_GROUP_9_ADDR 239U
#define IDIBUS_GROUP_10_ADDR 240U
#define IDIBUS_GROUP_11_ADDR 241U
#define IDIBUS_GROUP_12_ADDR 242U
#define IDIBUS_GROUP_13_ADDR 243U
#define IDIBUS_GROUP_14_ADDR 244U
#define IDIBUS_GROUP_15_ADDR 245U
#define IDIBUS_GROUPS_NUMBER 16U
#define IDIBUS_GROUP_FIRST_NUMBER 0U
#define IDIBUS_GROUP_LAST_NUMBER 15U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIMMES_ADDR_Pos 00U
#define IDIMMES_MMPS_Pos 01U
#define IDIMMES_MMPS_LONG_MES_Pos 0U
#define IDIMMES_MMPS_LONG_MES_Msk 0x01U
#define IDIMMES_MMPS_MES_TYPE_Pos 1U
#define IDIMMES_MMPS_MES_TYPE_Msk 0x02U
#define IDIMMES_MMPS_MES_TYPE_MMES 0x00U
#define IDIMMES_MMPS_MES_TYPE_MMESG 0x01U
#define IDIMMES_MMPS_FAST_FUNC_Pos 2U
#define IDIMMES_MMPS_FAST_FUNC_Msk 0x3CU
#define IDIMMES_MMPS_ALARM_FRAME_Pos 6U
#define IDIMMES_MMPS_ALARM_FRAME_Msk 0x40U
#define IDIMMES_MMPS_ENCRYPTED_AES_Pos 7U
#define IDIMMES_MMPS_ENCRYPTED_AES_Msk 0x80U
#define IDIMMES_DEV_Pos 02U
#define IDIMMES_DEV_NUM_Pos 0U
#define IDIMMES_DEV_NUM_Msk 0x1FU
#define IDIMMES_DEV_ALLCH_Pos 5U
#define IDIMMES_DEV_ALLCH_Msk 0x20U
#define IDIMMES_CHNL_Pos 03U
#define IDIMMES_CHNL_NUM_Pos 0U
#define IDIMMES_CHNL_NUM_Msk 0x7FU
#define IDIMMES_CHNL_ALLSAME_Pos 7U
#define IDIMMES_CHNL_ALLSAME_Msk 0x80U
#define IDIMMES_DATA_FUNC_COM_DATA_Pos 04U
#define IDIMMES_MAX_HEADER_LENGTH (IDIMMES_DATA_FUNC_COM_DATA_Pos + 1)
#define IDIMMES_MAX_DATA_SIZE 256U
#define IDIMMES_MAX_MES_SIZE (IDIMMES_MAX_DATA_SIZE + IDIMMES_MAX_HEADER_LENGTH + MODBUS_CRC16_SIZE)
#define IDIMMES_MIN_MES_SIZE (IDIMMES_DATA_FUNC_COM_DATA_Pos + MODBUS_CRC16_SIZE)
#define IDIMMESG_DATA_COM_FUNC_Pos 02U
#define IDIMMESG_MAX_HEADER_LENGTH (IDIMMESG_DATA_COM_FUNC_Pos + 1)
#define IDIMMESG_MAX_DATA_SIZE IDIMMES_MAX_DATA_SIZE
#define IDIMMESG_MAX_MES_SIZE (IDIMMESG_MAX_DATA_SIZE + IDIMMESG_MAX_HEADER_LENGTH + MODBUS_CRC16_SIZE)
#define IDIMMESG_MODULE_MIN_MES_SIZE (IDIMMESG_DATA_COM_FUNC_Pos + 1 + MODBUS_CRC16_SIZE)
#define IDIMMESG_GROUP_MIN_MES_SIZE (IDIMMESG_DATA_COM_FUNC_Pos + MODBUS_CRC16_SIZE)
#define IDIMMES_LMES_MSIZE_Pos 0U
#define IDIMMES_LMES_BSIZE_Pos (IDIMMES_LMES_MSIZE_Pos + 4U)
#define IDIMMES_LMES_IDENTIFIER_LENGTH (IDIMMES_LMES_BSIZE_Pos + 1U)
#define IDIMMES_LMES_BSIZE_256B 0U
#define IDIMMES_LMES_BSIZE_1K 1U
#define IDIMMES_LMES_BSIZE_4K 2U
#define IDIMMES_LMES_BSIZE_8K 3U
#define IDIMMES_LMES_BSIZE_16K 4U
#define IDIMMES_LMES_BSIZE_32K 5U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISMES_ADDR_Pos 00U
#define IDISMES_SMPS_Pos 01U
#define IDISMES_SMPS_ERROR_BIT_Pos 0U
#define IDISMES_SMPS_LONG_MES_Pos 1U
#define IDISMES_SMPS_LONG_OP_Pos 2U
#define IDISMES_ERROR_Pos 02U
#define IDISMES_DATA_Pos 03U
#define IDISMES_MAX_DATA_SIZE 256U
#define IDISMES_MIN_MES_SIZE (IDISMES_DATA_Pos + MODBUS_CRC16_SIZE)
#define IDISMES_MAX_MES_SIZE (IDISMES_DATA_Pos + IDISMES_MAX_DATA_SIZE + MODBUS_CRC16_SIZE)
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDILONGOP_STATE_COMPLETE_NO_ERR 0x00U
#define IDILONGOP_STATE_IN_PROC 0x01U
#define IDILONGOP_STATE_COMPLETE_WITH_ERR 0x02U
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDILONGOP_MES_DATA_LENGTH 5U
#define IDILONGOP_STATE_Pos 0U
#define IDILONGOP_REMAIN_TIME_Pos 1U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISTATUS_B0S_Pos 00U
#define IDISTATUS_B0S_ST_ERROR_Pos 0U
#define IDISTATUS_B0S_ST_STATE_Pos 1U
#define IDISTATUS_B0S_ST_STATE_Msk 0x07U
#define IDISTATUS_B0S_ST_STATE_StNoInit 0x00U
#define IDISTATUS_B0S_ST_STATE_StOperate 0x01U
#define IDISTATUS_B0S_ST_STATE_StFreeze 0x02U
#define IDISTATUS_B0S_ST_STATE_StVirtual 0x03U
#define IDISTATUS_B0S_ST_STATE_StFirmwareUpd 0x04U
#define IDISTATUS_B0S_ST_STATE_StReservedMaster 0x05U
#define IDISTATUS_B0S_ST_STATE_StBroken 0x06U
#define IDISTATUS_B0S_ST_STATE_StReserved0 0x07U
#define IDISTATUS_B0S_AES_SUPPORTED_Pos 4U
#define IDISTATUS_B0S_AES_INSTALLED_Pos 5U
#define IDISTATUS_B0S_SEND_ALARM_L0_Pos 6U
#define IDISTATUS_B0S_SEND_ALARM_L1_Pos 7U
#define IDISTATUS_B1S_Pos 01U
#define IDISTATUS_B1S_MODULE_TYPE_Pos 0U
#define IDISTATUS_B1S_MODULE_TYPE_Msk 0x03U
#define IDISTATUS_B1S_MODULE_TYPE_Master 0x00U
#define IDISTATUS_B1S_MODULE_TYPE_SpareMaster 0x01U
#define IDISTATUS_B1S_MODULE_TYPE_Slave 0x02U
#define IDISTATUS_B1S_MODULE_TYPE_Bridge 0x03U
#define IDISTATUS_B1S_BRIDGE_CONNECTED_Pos 2U
#define IDISTATUS_B1S_SELF_INIT_Pos 3U
#define IDISTATUS_B1S_TIMEOUT_LED_Pos 4U
#define IDISTATUS_B1S_NO_MMES_TIMEOUT_Pos 5U
#define IDISTATUS_B1S_CATCH_ALARM_L0_Pos 6U
#define IDISTATUS_B1S_CATCH_ALARM_L1_Pos 7U
#define IDISTATUS_SN_Pos 02U
#define IDISTATUS_LENGTH ( IDISTATUS_SN_Pos + IDISN_FULL_LENGTH )
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIMMES_NOT_FAST_FUNC 0U
#define IDIMMES_MAX_FAST_FUNC_NUM 15U
#define IDIMMES_COM_START_NUM 220U
#define IDIMMES_COM_C_Init 220U
#define IDIMMES_COM_C_ShtDown 221U
#define IDIMMES_COM_C_Freeze 222U
#define IDIMMES_COM_C_Resume 223U
#define IDIMMES_COM_C_Dummy 224U
#define IDIMMES_COM_C_AssignGroup 225U
#define IDIMMES_COM_C_SetAlarmL12 226U
#define IDIMMES_COM_C_SetAlarmL 227U
#define IDIMMES_COM_C_Virtual 228U
#define IDIMMES_COM_C_SyncReadChnl 229U
#define IDIMMES_COM_C_SyncRead 230U
#define IDIMMES_COM_C_SyncDoChnl 231U
#define IDIMMES_COM_C_SyncDo 232U
#define IDIMMES_COM_C_SyncClear 233U
#define IDIMMES_COM_C_BurstReadCnt 234U
#define IDIMMES_COM_C_BurstReadTime 235U
#define IDIMMES_COM_C_SendTimeDate 236U
#define IDIMMES_COM_C_MkTimedMaster 237U
#define IDIMMES_COM_C_FmwUpd 238U
#define IDIMMES_COM_C_EndFmwUpd 239U
#define IDIMMES_COM_C_FmwWrite 240U
#define IDIMMES_COM_C_ReadDevFullSN_MS 241U
#define IDIMMES_COM_C_WriteSnIPv4IPv6 242U
#define IDIMMES_COM_C_WriteSnVerifyDates 243U
#define IDIMMES_COM_C_WriteSnAES256 244U
#define IDIMMES_COM_C_SendLongMessage 245U
#define IDIMMES_COM_C_GetLondMessage 246U
#define IDIMMES_COM_C_DummyModule 247U
#define IDIMMES_COM_C_CheckModuleLongOp 248U
#define IDIMMES_COM_C_CheckChannelLongOp 249U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIER_MODBUS_NUM_START 1U
#define IDIER_MODBUS_NUM_END 9U
#define IDIER_MODULE_MASTER_NUM_START 10U
#define IDIER_MODULE_MASTER_NUM_END 32U
#define IDIER_MODULE_SLAVE_NUM_START 33U
#define IDIER_MODULE_SLAVE_NUM_END 71U
#define IDIER_MODULE_NUM_START IDIER_MODULE_MASTER_NUM_START
#define IDIER_MODULE_NUM_END IDIER_MODULE_SLAVE_NUM_END
#define IDIER_DEVICE_NUM_START 72U
#define IDIER_DEVICE_NUM_END 89U
#define IDIER_NOPE 0U
#define MODBUSER_WRONGFUNC 1U
#define MODBUSER_WRONGADDR 2U
#define MODBUSER_WRONGDATA 3U
#define MODBUSER_BROKE 4U
#define MODBUSER_LONGCOMMAND 5U
#define MODBUSER_BUSY 6U
#define MODBUSER_CANTDOFUNC 7U
#define MODBUSER_EXTMEMORYERROR 8U
#define MODBUSER_RESERVED 9U
#define IDIERMST_INVALID_ADDR_NUM 10U
#define IDIERMST_INVALID_DEV_NUM 11U
#define IDIERMST_INVALID_CHN_NUM 12U
#define IDIERMST_INVALID_FUNC_NUM 13U
#define IDIERMST_INVALID_TX_REQUEST_FORMAT 14U
#define IDIERMST_INVALID_TX_PARAM 15U
#define IDIERMST_TX_MES 16U
#define IDIERMST_RCV_TIMEOUT 17U
#define IDIERMST_MES_RX_INTEGRITY 18U
#define IDIERMST_CRC 19U
#define IDIERMST_MULTIPLE_CRC 20U
#define IDIERMST_INVALID_RX_REQUEST_FORMAT 21U
#define IDIERMST_INVALID_RX_PARAM 22U
#define IDIERMST_RESEVED_23 23U
#define IDIERMST_RESEVED_24 24U
#define IDIERMST_RESEVED_25 25U
#define IDIERMST_RESEVED_26 26U
#define IDIERMST_RESEVED_27 27U
#define IDIERMST_EXTRA_28 28U
#define IDIERMST_EXTRA_29 29U
#define IDIERMST_EXTRA_30 30U
#define IDIERMST_EXTRA_31 31U
#define IDIERMST_EXTRA_32 32U
#define IDIERSLV_RESEVED_33 33U
#define IDIERSLV_ENCRYPTION_NOT_SUPPORTED 34U
#define IDIERSLV_ENCRYPTION_NOT_INSTALLED 35U
#define IDIERSLV_JUMBO_NOT_SUPPORTED 36U
#define IDIERSLV_UNSUPPORTED_FUNC_NUM 37U
#define IDIERSLV_INVALID_RX_REQUEST_FORMAT 38U
#define IDIERSLV_INVALID_RX_PARAM 39U
#define IDIERSLV_IN_FREEZE 40U
#define IDIERSLV_RESERVED_41 41U
#define IDIERSLV_RESERVED_42 42U
#define IDIERSLV_RESERVED_43 43U
#define IDIERSLV_RESERVED_44 44U
#define IDIERSLV_RESERVED_45 45U
#define IDIERSLV_EXTRA_46 46U
#define IDIERSLV_EXTRA_47 47U
#define IDIERSLV_EXTRA_48 48U
#define IDIERSLV_EXTRA_49 49U
#define IDIERSLV_EXTRA_50 50U
#define IDIERSLV_BROKE 51U
#define IDIERSLV_NO_FIRMWARE 52U
#define IDIERSLV_NO_INIT 53U
#define IDIERSLV_OVERHEAT 54U
#define IDIERSLV_INP_VOLTAGE 55U
#define IDIERSLV_BRIDGE_OVERFLOW 56U
#define IDIERSLV_BRIDGE_NOT_CONF 57U
#define IDIERSLV_VERIF_DATE 58U
#define IDIERSLV_RTC 59U
#define IDIERSLV_LONG_OP_IN_PROC 60U
#define IDIERSLV_RESERVED_61 61U
#define IDIERSLV_RESERVED_62 62U
#define IDIERSLV_RESERVED_63 63U
#define IDIERSLV_RESERVED_64 64U
#define IDIERSLV_RESERVED_65 65U
#define IDIERSLV_RESERVED_66 66U
#define IDIERSLV_EXTRA_67 67U
#define IDIERSLV_EXTRA_68 68U
#define IDIERSLV_EXTRA_69 69U
#define IDIERSLV_EXTRA_70 70U
#define IDIERSLV_EXTRA_71 71U
#define IDIERDEV_INVALID_DEV_NUM 72U
#define IDIERDEV_INVALID_CHN_NUM 73U
#define IDIERDEV_INVALID_FUNC_NUM 74U
#define IDIERDEV_LONG_OP_IN_PROC 75U
#define IDIERDEV_RESERVED_76 76U
#define IDIERDEV_PARAM_LOW_ST_TIMEOUT 77U
#define IDIERDEV_PARAM_HIGH_ST_TIMEOUT 78U
#define IDIERDEV_PARAM_NOT_CHANGE_TIMEOUT 79U
#define IDIERDEV_RESERVED_80 80U
#define IDIERDEV_RESERVED_81 81U
#define IDIERDEV_RESERVED_82 82U
#define IDIERDEV_RESERVED_83 83U
#define IDIERDEV_RESERVED_84 84U
#define IDIERDEV_RESERVED_85 85U
#define IDIERDEV_RESERVED_86 86U
#define IDIERDEV_RESERVED_87 87U
#define IDIERDEV_RESERVED_88 88U
#define IDIERDEV_RESERVED_89 89U
#define IDIER_MULTIPLE_CRC_AVRBUF_SIZE 16U
#define IDIER_MULTIPLE_CRC_AVRBUF_THR 5U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIDATE_FORMAT_DAY_Pos 0U
#define IDIDATE_FORMAT_MONTH_Pos 1U
#define IDIDATE_FORMAT_CENTURY_Pos 2U
#define IDIDATE_FORMAT_YEAR99_Pos 3U
#define IDIDATE_FORMAT_LENGTH 4U
#define IDITIME_FORMAT_SECONDS_Pos 0U
#define IDITIME_FORMAT_MINUTES_Pos 1U
#define IDITIME_FORMAT_HOURS_Pos 2U
#define IDITIME_FORMAT_TIMEZONE_Pos 3U
#define IDITIME_FORMAT_LENGTH 4U
#define IDITIME_FORMAT_TIMEZONE_MIN (-12)
#define IDITIME_FORMAT_TIMEZONE_MAX 14
#define IDIMMES_C_DATETIME_TIME_Pos 0
#define IDIMMES_C_DATETIME_DATE_Pos (IDIMMES_C_DATETIME_TIME_Pos + IDIDATE_FORMAT_LENGTH)
#define IDIMMES_C_DATETIME_LENGTH (IDIDATE_FORMAT_LENGTH + IDITIME_FORMAT_LENGTH)
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
typedef struct {
struct {
uint8_t StError : 1;
uint8_t StState : 3;
uint8_t AesSupported : 1;
uint8_t AesInstalled : 1;
uint8_t SendAlarmL0 : 1;
uint8_t SendAlarmL1 : 1;
} B0S;
struct {
uint8_t ModuleType : 2;
uint8_t BridgeConnected : 1;
uint8_t SelfInit : 1;
uint8_t TimeoutLed : 1;
uint8_t NoMMESTimeout : 1;
uint8_t CatchAlarmL0 : 1;
uint8_t CatchAlarmL1 : 1;
} B1S;
} IDISTATUS_STATE_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------s
typedef struct {
IDISTATUS_STATE_TYPE STATE;
uint8_t SN[IDISN_FULL_LENGTH];
} IDISTATUS_SLAVE_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_INC_IDIBUS_DEFS_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,134 @@
//###################################################################################################################################################
#include "MODBUS_CRC.h"
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Table of CRC values for highorder byte FLASH Variant
const uint8_t MODBUS_auchCRCHi_PR[] PROGMEM = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
// Table of CRC values for loworder byte
const uint8_t MODBUS_auchCRCLo_PR[] PROGMEM = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Table of CRC values for highorder byte RAM Variant
uint8_t MODBUS_auchCRCHi_R[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
// Table of CRC values for loworder byte
uint8_t MODBUS_auchCRCLo_R[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_TF(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen)
{
uint8_t MODBUS_uchCRCHi = 0xFF; // high byte of CRC initialized
uint8_t MODBUS_uchCRCLo = 0xFF; // low byte of CRC initialized
uint8_t MODBUS_uIndex;
while (MODBUS_usDataLen--)
{
MODBUS_uIndex = MODBUS_uchCRCLo ^ (*MODBUS_puchMsg++); // calculate the CRC
MODBUS_uchCRCLo = MODBUS_uchCRCHi ^ pgm_read_byte(&MODBUS_auchCRCHi_PR[MODBUS_uIndex]);
MODBUS_uchCRCHi = pgm_read_byte(&MODBUS_auchCRCLo_PR[MODBUS_uIndex]);
}
return ( ((uint16_t)MODBUS_uchCRCHi << 8 ) | MODBUS_uchCRCLo );
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_TR(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen)
{
uint8_t MODBUS_uchCRCHi = 0xFF; // high byte of CRC initialized
uint8_t MODBUS_uchCRCLo = 0xFF; // low byte of CRC initialized
uint8_t MODBUS_uIndex;
while (MODBUS_usDataLen--)
{
MODBUS_uIndex = MODBUS_uchCRCLo ^ (*MODBUS_puchMsg++); // calculate the CRC
MODBUS_uchCRCLo = MODBUS_uchCRCHi ^ MODBUS_auchCRCHi_R[MODBUS_uIndex];
MODBUS_uchCRCHi = MODBUS_auchCRCLo_R[MODBUS_uIndex];
}
return (((uint16_t)MODBUS_uchCRCHi << 8) | MODBUS_uchCRCLo);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_S(uint8_t *MODBUS_buf, uint16_t MODBUS_len)
{
uint16_t MODBUS_crc = 0xFFFF;
for (uint16_t MODBUS_pos = 0; MODBUS_pos < MODBUS_len; MODBUS_pos++)
{
MODBUS_crc ^= MODBUS_buf[MODBUS_pos]; // XOR byte into least sig. byte of crc
for (uint8_t MODBUS_i = 8; MODBUS_i != 0; MODBUS_i--) // Loop over each bit
{
if ((MODBUS_crc & 0x0001) != 0) { MODBUS_crc >>= 1; MODBUS_crc ^= 0xA001; } // If the LSB is set // Shift right and XOR 0xA001
else { MODBUS_crc >>= 1; } // Else LSB is not set // Just shift right
}
}
return MODBUS_crc;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
//###################################################################################################################################################

@ -0,0 +1,20 @@
//###################################################################################################################################################
#ifndef _MODBUS_CRC_H_
#define _MODBUS_CRC_H_
//---------------------------------------------------------------------------------------------------------------------------------------------------
#include "avr/io.h"
#include <avr/pgmspace.h>
#include <inttypes.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------
#define MODBUS_CRC16_SIZE 2
//---------------------------------------------------------------------------------------------------------------------------------------------------
class MODBUS_CRC16 {
public :
static uint16_t CRC16_TF(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen);
static uint16_t CRC16_TR(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen);
static uint16_t CRC16_S(uint8_t *MODBUS_buf, uint16_t MODBUS_len);
private :
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _CRC_MODBUS_
//###################################################################################################################################################

@ -0,0 +1,663 @@
//#############################################################################################################################################################################################################
#include "IDIBUS_4DC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusDevice *IdiBus_4DC::getDevice(uint8_t Num)
{
switch (Num)
{
case ( IDIBUS_PSU_CNTRL_DEV ) : { return &this->PSUC_DEV; }
case ( IDIBUS_INPV_CNTRL_DEV ) : { return &this->INPV_DEV; }
default : { return NULL; }
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBus_4DC_PSUChannel::IdiBus_4DC_PSUChannel(void) : IdiBusChannel()
{
this->TargetVoltage = 0;
this->CurrentLimit = 0;
this->Voltage = 0;
this->Current = 0;
this->STATUS.Enable = 0;
this->STATUS.PowerGood = 0;
this->STATUS.ERRORS.Sum = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusChannel *IdiBus_4DC_PSUCDevice::getChannel(uint8_t Num)
{
if ( Num < IDIBUS_4DC_CH_COUNT ) { return &this->CH[Num]; }
else { return NULL; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBus_4DC_PSUChannel IdiBus_4DC_PSUCDevice::getChData(uint8_t ChNum)
{
if ( ChNum < IDIBUS_4DC_CH_COUNT ) { return this->CH[ChNum]; }
else { IdiBus_4DC_PSUChannel NewData; return NewData; }
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBus_4DC_INPVChannel::IdiBus_4DC_INPVChannel(void) : IdiBusChannel()
{
this->InpVoltage = 0;
this->STATUS.Sum = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusChannel *IdiBus_4DC_INPVCDevice::getChannel(uint8_t Num)
{
if ( Num == 0 ) { return &this->INPV; }
else { return NULL; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBus_4DC_INPVChannel IdiBus_4DC_INPVCDevice::getChData(void)
{
return this->INPV;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_INPVCDevice::getInputVoltage(void)
{
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_INPV_CNTRL_DEV;
MMES.CHNL.NUM = 0;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_GET_INP_VOLTAGE;
uint8_t ChDataSize = IDIBUS_CUSTDEF_PSUINPV_MES_LENGTH;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->INPV.MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->INPV.MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->INPV.MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->INPV.MMES_Error = MMES.RxData[0];
if ( this->INPV.MMES_Error == IDIER_NOPE )
{
uint8_t *Data = &MMES.RxData[1];
if ( (Data[IDIBUS_CUSTDEF_PSUINPV_STATE_Pos] & (1U << IDIBUS_CUSTDEF_PSUINPV_STATE_UV_Pos)) != 0 ) { this->INPV.STATUS.BF.Undervoltage = 1; }
else { this->INPV.STATUS.BF.Undervoltage = 0; }
if ( (Data[IDIBUS_CUSTDEF_PSUINPV_STATE_Pos] & (1U << IDIBUS_CUSTDEF_PSUINPV_STATE_OV_Pos)) != 0 ) { this->INPV.STATUS.BF.Overvoltage = 1; }
else { this->INPV.STATUS.BF.Overvoltage = 0; }
this->INPV.InpVoltage = (uint16_t)( (uint16_t)Data[IDIBUS_CUSTDEF_PSUINPV_VOLTAGE_Pos] << 8 ) | MMES.RxData[IDIBUS_CUSTDEF_PSUINPV_VOLTAGE_Pos + 1];
}
}
return this->INPV.MMES_Error;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::getChOutputVoltage(uint8_t ChNum)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_VOLTAGE;
uint8_t ChDataSize = 4; //int32_t
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE )
{
this->CH[ChNum].Voltage = (int32_t) (
(uint32_t)((uint32_t)MMES.RxData[1] << 24) |
(uint32_t)((uint32_t)MMES.RxData[2] << 16) |
(uint32_t)((uint32_t)MMES.RxData[3] << 8) |
(uint32_t)((uint32_t)MMES.RxData[4]) );
}
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::getAllChOutputVoltage(void)
{
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_VOLTAGE;
uint8_t ChDataSize = 4; //int32_t
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_4DC_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_4DC_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE )
{
this->CH[I].Voltage = (int32_t) (
(uint32_t)((uint32_t)MMES.RxData[DataPos] << 24) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+1] << 16) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+2] << 8) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+3]) );
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::getChOutputCurrent(uint8_t ChNum)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_CURRENT;
uint8_t ChDataSize = 4; //int32_t
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE )
{
this->CH[ChNum].Current = (int32_t) (
(uint32_t)((uint32_t)MMES.RxData[1] << 24) |
(uint32_t)((uint32_t)MMES.RxData[2] << 16) |
(uint32_t)((uint32_t)MMES.RxData[3] << 8) |
(uint32_t)((uint32_t)MMES.RxData[4]) );
}
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::getAllChOutputCurrent(void)
{
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_CURRENT;
uint8_t ChDataSize = 4; //int32_t
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_4DC_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_4DC_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE )
{
this->CH[I].Current = (int32_t) (
(uint32_t)((uint32_t)MMES.RxData[DataPos] << 24) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+1] << 16) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+2] << 8) |
(uint32_t)((uint32_t)MMES.RxData[DataPos+3]) );
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::getChStatus(uint8_t ChNum)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_STATUS;
uint8_t ChDataSize = IDIBUS_CUSTDEF_PSUCH_STBUF_SIZE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->parsePsuChState(&MMES.RxData[1], ChNum); }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::getAllChStatus(void)
{
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_STATUS;
uint8_t ChDataSize = IDIBUS_CUSTDEF_PSUCH_STBUF_SIZE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_4DC_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_4DC_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE )
{
this->parsePsuChState(&MMES.RxData[DataPos], I);
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::getChAllData(uint8_t ChNum)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_ALLDATA;
uint8_t ChDataSize = IDIBUS_CUSTDEF_PSUCH_STALLBUF_SIZE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->parsePsuChAllState(&MMES.RxData[1], ChNum); }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::getAllChAllData(void)
{
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() );
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_ALLDATA;
uint8_t ChDataSize = IDIBUS_CUSTDEF_PSUCH_STALLBUF_SIZE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_4DC_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_4DC_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE )
{
this->parsePsuChAllState(&MMES.RxData[DataPos], I);
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::setChState(uint8_t ChNum, uint8_t State)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
if ( State != 0 ) { State = IDIBUS_CUSTDEF_PSU_CH_STATE_ENABLE; }
else { State = IDIBUS_CUSTDEF_PSU_CH_STATE_DISABLE; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &State, 1);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->CH[ChNum].STATUS.Enable = State; }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChState(uint8_t State)
{
if ( State != 0 ) { State = IDIBUS_CUSTDEF_PSU_CH_STATE_ENABLE; }
else { State = IDIBUS_CUSTDEF_PSU_CH_STATE_DISABLE; }
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &State, 1);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.CHNL.ALLSAME = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].STATUS.Enable = State; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChState(uint8_t Ch1State, uint8_t Ch2State, uint8_t Ch3State, uint8_t Ch4State)
{
uint8_t State[IDIBUS_4DC_CH_COUNT] = { Ch1State, Ch2State, Ch3State, Ch4State };
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++)
{
if ( State[I] != 0 ) { State[I] = IDIBUS_CUSTDEF_PSU_CH_STATE_ENABLE; }
else { State[I] = IDIBUS_CUSTDEF_PSU_CH_STATE_DISABLE; }
}
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &State[0], IDIBUS_4DC_CH_COUNT);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].STATUS.Enable = State[I]; }
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::setChVoltage(uint8_t ChNum, uint16_t TargetVoltage)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
if ( (TargetVoltage < IDIBUS_PSU_CH_TARG_V_MIN_mV) || (TargetVoltage > IDIBUS_PSU_CH_TARG_V_MAX_mV) )
{
this->CH[ChNum].MMES_Error = IDIERMST_INVALID_TX_PARAM;
return IDIERMST_INVALID_TX_PARAM;
}
uint8_t TxData[2];
TxData[0] = (uint8_t)(TargetVoltage >> 8);
TxData[1] = (uint8_t)(TargetVoltage);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_TARGET_VOLTAGE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->CH[ChNum].TargetVoltage = TargetVoltage; }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChVoltage(uint16_t TargetVoltage)
{
if ( (TargetVoltage < IDIBUS_PSU_CH_TARG_V_MIN_mV) || (TargetVoltage > IDIBUS_PSU_CH_TARG_V_MAX_mV) ) { this->setAllPsuChErr(IDIERMST_INVALID_TX_PARAM); return; }
uint8_t TxData[2];
TxData[0] = (uint8_t)(TargetVoltage >> 8);
TxData[1] = (uint8_t)(TargetVoltage);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.CHNL.ALLSAME = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_TARGET_VOLTAGE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].TargetVoltage = TargetVoltage; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChVoltage(uint16_t TV_CH1, uint16_t TV_CH2, uint16_t TV_CH3, uint16_t TV_CH4)
{
uint16_t TargetV[IDIBUS_4DC_CH_COUNT] = { TV_CH1, TV_CH2, TV_CH3, TV_CH4 };
uint8_t TxData[IDIBUS_4DC_CH_COUNT * 2];
for (uint8_t I=0, J=0; I<IDIBUS_4DC_CH_COUNT; I++, J+=2 )
{
TxData[J] = (uint8_t)(TargetV[I] >> 8);
TxData[J+1] = (uint8_t)(TargetV[I]);
}
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], IDIBUS_4DC_CH_COUNT * 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_TARGET_VOLTAGE;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].TargetVoltage = TargetV[I]; }
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::setChCurrentLimit(uint8_t ChNum, uint16_t CurrentLimit)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
if ( (CurrentLimit < IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MIN) || (CurrentLimit > IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MAX) )
{
this->CH[ChNum].MMES_Error = IDIERMST_INVALID_TX_PARAM;
return IDIERMST_INVALID_TX_PARAM;
}
uint8_t TxData[2];
TxData[0] = (uint8_t)(CurrentLimit >> 8);
TxData[1] = (uint8_t)(CurrentLimit);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_CURRENT_LIMIT;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->CH[ChNum].CurrentLimit = CurrentLimit; }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChCurrentLimit(uint16_t CurrentLimit)
{
if ( (CurrentLimit < IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MIN) || (CurrentLimit > IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MAX) ) { this->setAllPsuChErr(IDIERMST_INVALID_TX_PARAM); return; }
uint8_t TxData[2];
TxData[0] = (uint8_t)(CurrentLimit >> 8);
TxData[1] = (uint8_t)(CurrentLimit);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.CHNL.ALLSAME = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_CURRENT_LIMIT;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].CurrentLimit = CurrentLimit; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChCurrentLimit(uint16_t CL_CH1, uint16_t CL_CH2, uint16_t CL_CH3, uint16_t CL_CH4)
{
uint16_t CurrentL[IDIBUS_4DC_CH_COUNT] = { CL_CH1, CL_CH2, CL_CH3, CL_CH4 };
uint8_t TxData[IDIBUS_4DC_CH_COUNT * 2];
for (uint8_t I=0, J=0; I<IDIBUS_4DC_CH_COUNT; I++, J+=2 )
{
TxData[J] = (uint8_t)(CurrentL[I] >> 8);
TxData[J+1] = (uint8_t)(CurrentL[I]);
}
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], IDIBUS_4DC_CH_COUNT * 2);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_CURRENT_LIMIT;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].CurrentLimit = CurrentL[I]; }
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBus_4DC_PSUCDevice::setChVoltageAndCurrentLimit(uint8_t ChNum, uint16_t TargetVoltage, uint16_t CurrentLimit)
{
if ( ChNum >= IDIBUS_4DC_CH_COUNT ) { return IDIERMST_INVALID_CHN_NUM; }
if ( (CurrentLimit < IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MIN) || (CurrentLimit > IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MAX) ||
(TargetVoltage < IDIBUS_PSU_CH_TARG_V_MIN_mV) || (TargetVoltage > IDIBUS_PSU_CH_TARG_V_MAX_mV) )
{
this->CH[ChNum].MMES_Error = IDIERMST_INVALID_TX_PARAM;
return IDIERMST_INVALID_TX_PARAM;
}
uint8_t TxData[4];
TxData[0] = (uint8_t)(TargetVoltage >> 8);
TxData[1] = (uint8_t)(TargetVoltage);
TxData[2] = (uint8_t)(CurrentLimit >> 8);
TxData[3] = (uint8_t)(CurrentLimit);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 4);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_ALL;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE ) { this->CH[ChNum].TargetVoltage = TargetVoltage; this->CH[ChNum].CurrentLimit = CurrentLimit; }
}
return this->CH[ChNum].MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChVoltageAndCurrentLimit(uint16_t TargetVoltage, uint16_t CurrentLimit)
{
if ( (CurrentLimit < IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MIN) || (CurrentLimit > IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MAX) ||
(TargetVoltage < IDIBUS_PSU_CH_TARG_V_MIN_mV) || (TargetVoltage > IDIBUS_PSU_CH_TARG_V_MAX_mV) ) { this->setAllPsuChErr(IDIERMST_INVALID_TX_PARAM); return; }
uint8_t TxData[4];
TxData[0] = (uint8_t)(TargetVoltage >> 8);
TxData[1] = (uint8_t)(TargetVoltage);
TxData[2] = (uint8_t)(CurrentLimit >> 8);
TxData[3] = (uint8_t)(CurrentLimit);
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], 4);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.CHNL.ALLSAME = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_ALL;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].TargetVoltage = TargetVoltage; this->CH[I].CurrentLimit = CurrentLimit; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllChVoltageAndCurrentLimit(uint16_t VCH1, uint16_t CCH1, uint16_t VCH2, uint16_t CCH2, uint16_t VCH3, uint16_t CCH3, uint16_t VCH4, uint16_t CCH4)
{
uint16_t CurrentL[IDIBUS_4DC_CH_COUNT] = { CCH1, CCH2, CCH3, CCH4 };
uint16_t TargetV[IDIBUS_4DC_CH_COUNT] = { VCH1, VCH2, VCH3, VCH4 };
uint8_t TxData[IDIBUS_4DC_CH_COUNT * 4];
for (uint8_t I=0, J=0; I<IDIBUS_4DC_CH_COUNT; I++, J+=4 )
{
TxData[J] = (uint8_t)(TargetV[I] >> 8);
TxData[J+1] = (uint8_t)(TargetV[I]);
TxData[J+2] = (uint8_t)(CurrentL[I] >> 8);
TxData[J+3] = (uint8_t)(CurrentL[I]);
}
IdiBusMMES MMES( static_cast<IdiBusSlave*>(this->Module)->getAddress() , &TxData[0], IDIBUS_4DC_CH_COUNT * 4);
MMES.DEV.NUM = IDIBUS_PSU_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_ALL;
uint8_t RequestError = static_cast<IdiBusSlave*>(this->Module)->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllPsuChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_4DC_CH_COUNT) { this->setAllPsuChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_4DC_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
if ( this->CH[I].MMES_Error == IDIER_NOPE ) { this->CH[I].TargetVoltage = TargetV[I]; this->CH[I].CurrentLimit = CurrentL[I]; }
}
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiBus_4DC_PSUCDevice::parsePsuChState(uint8_t *State, uint8_t ChNum)
{
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_EN_Pos)) != 0 ) { this->CH[ChNum].STATUS.Enable = 1; }
else { this->CH[ChNum].STATUS.Enable = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_PG_Pos)) != 0 ) { this->CH[ChNum].STATUS.PowerGood = 1; }
else { this->CH[ChNum].STATUS.PowerGood = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_PERIPH_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.PeripheryError = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.PeripheryError = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OVERCURRENT_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.OvercurrentError = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.OvercurrentError = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OVERVOLTAGE_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.OvervoltageError = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.OvervoltageError = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OFFSTATELEAKAGE_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.OffStateCurrentLeakage = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.OffStateCurrentLeakage = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_MEMORY_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.MemoryError = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.MemoryError = 0; }
if ( (State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos] & (1U << IDIBUS_CUSTDEF_PSUCH_STBUF_ST_INPV_ERR_Pos)) != 0 ) { this->CH[ChNum].STATUS.ERRORS.BF.InpVoltageError = 1; }
else { this->CH[ChNum].STATUS.ERRORS.BF.InpVoltageError = 0; }
this->CH[ChNum].TargetVoltage = (uint16_t)( (uint16_t)((uint16_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_TARGET_VOLATGE_Pos] << 8) | State[IDIBUS_CUSTDEF_PSUCH_STBUF_TARGET_VOLATGE_Pos + 1] );
this->CH[ChNum].CurrentLimit = (uint16_t)( (uint16_t)((uint16_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_CURRENT_LIMIT_Pos] << 8) | State[IDIBUS_CUSTDEF_PSUCH_STBUF_CURRENT_LIMIT_Pos + 1] );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::parsePsuChAllState(uint8_t *State, uint8_t ChNum)
{
this->parsePsuChState(&State[IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos], ChNum);
this->CH[ChNum].Voltage = (int32_t) (
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos] << 24) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos + 1] << 16) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos + 2] << 8) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos + 3]) );
this->CH[ChNum].Current = (int32_t) (
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos] << 24) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos + 1] << 16) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos + 2] << 8) |
(uint32_t)((uint32_t)State[IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos + 3]) );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBus_4DC_PSUCDevice::setAllPsuChErr(uint8_t ErrCode)
{
for (uint8_t I=0; I<IDIBUS_4DC_CH_COUNT; I++) { this->CH[I].MMES_Error = ErrCode; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,178 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_4DC_H_
#define _IDIBUS_4DC_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSlave.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_CUSTDEF_PSU_CH_STATE_DISABLE 0x00
#define IDIBUS_CUSTDEF_PSU_CH_STATE_ENABLE 0x01
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_STATE 0x01
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_VOLTAGE 0x02
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_CURRENT 0x03
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_STATUS 0x04
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_GET_ALLDATA 0x05
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_TARGET_VOLTAGE 0x06
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_CURRENT_LIMIT 0x07
#define IDIBUS_CUSTDEF_FUNC_CODE_PSU_CH_SET_ALL 0x08
#define IDIBUS_CUSTDEF_FUNC_CODE_GET_INP_VOLTAGE 0x09
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_CUSTDEF_ERCODE_INVALID_DATA 100U
#define IDIBUS_CUSTDEF_ERCODE_NO_ACCESS 101U
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_CUSTDEF_PSUCH_GET_CV_MES_LENGTH 4U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_Pos 00U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_EN_Pos 0U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_PG_Pos 1U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_PERIPH_ERR_Pos 2U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OVERCURRENT_ERR_Pos 3U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OVERVOLTAGE_ERR_Pos 4U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_OFFSTATELEAKAGE_ERR_Pos 5U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_MEMORY_ERR_Pos 6U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_ST_INPV_ERR_Pos 7U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_TARGET_VOLATGE_Pos 01U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_CURRENT_LIMIT_Pos 03U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_SIZE 05U
#define IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos IDIBUS_CUSTDEF_PSUCH_STBUF_SIZE
#define IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos (IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_VOLTAGE_Pos + 4)
#define IDIBUS_CUSTDEF_PSUCH_STALLBUF_SIZE (IDIBUS_CUSTDEF_PSUCH_STBUF_OUTPUT_CURRENT_Pos + 4)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_CUSTDEF_PSUINPV_STATE_Pos 00U
#define IDIBUS_CUSTDEF_PSUINPV_STATE_UV_Pos 0U
#define IDIBUS_CUSTDEF_PSUINPV_STATE_OV_Pos 1U
#define IDIBUS_CUSTDEF_PSUINPV_VOLTAGE_Pos 01U
#define IDIBUS_CUSTDEF_PSUINPV_MES_LENGTH (IDIBUS_CUSTDEF_PSUINPV_VOLTAGE_Pos + 2)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_PSU_CH_TARG_V_MIN_mV 1500UL
#define IDIBUS_PSU_CH_TARG_V_MAX_mV 48000UL
#define IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MAX 10200UL
#define IDIBUS_PSU_CH_AVERAGE_CURRENT_LIMIT_MIN 100UL
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define PSU_INV_UNDERVOLTAGE_ERR_THR 10000U
#define PSU_INV_OVERVOLTAGE_ERR_THR 50000U
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_MODULE_DEVICES_LIST {
IDIBUS_PSU_CNTRL_DEV = 0x00,
IDIBUS_INPV_CNTRL_DEV,
IDIBUS_DEVICES_NUMBER
};
enum {
IDIBUS_4DC_CH1_NUM = 0,
IDIBUS_4DC_CH2_NUM,
IDIBUS_4DC_CH3_NUM,
IDIBUS_4DC_CH4_NUM,
IDIBUS_4DC_CH_COUNT
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBus_4DC_PSUChannel : public IdiBusChannel {
public:
IdiBus_4DC_PSUChannel(void);
int32_t Voltage;
int32_t Current;
uint16_t TargetVoltage;
uint16_t CurrentLimit;
struct {
uint8_t Enable;
uint8_t PowerGood;
union {
uint8_t Sum;
struct {
uint8_t PeripheryError : 1;
uint8_t OvercurrentError : 1;
uint8_t OvervoltageError : 1;
uint8_t OffStateCurrentLeakage : 1;
uint8_t MemoryError : 1;
uint8_t InpVoltageError : 1;
uint8_t Reserved : 2;
} BF;
} ERRORS;
} STATUS;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBus_4DC_PSUCDevice : public IdiBusDevice {
public :
IdiBus_4DC_PSUCDevice(void *ParentModule) : IdiBusDevice (ParentModule) {}
uint8_t getChStatus(uint8_t ChNum);
void getAllChStatus(void);
uint8_t getChOutputVoltage(uint8_t ChNum);
void getAllChOutputVoltage(void);
uint8_t getChOutputCurrent(uint8_t ChNum);
void getAllChOutputCurrent(void);
uint8_t getChAllData(uint8_t ChNum);
void getAllChAllData(void);
uint8_t setChState(uint8_t ChNum, uint8_t State);
void setAllChState(uint8_t State);
void setAllChState(uint8_t Ch1State, uint8_t Ch2State, uint8_t Ch3State, uint8_t Ch4State);
uint8_t setChVoltage(uint8_t ChNum, uint16_t TargetVoltage);
void setAllChVoltage(uint16_t TargetVoltage);
void setAllChVoltage(uint16_t TV_CH1, uint16_t TV_CH2, uint16_t TV_CH3, uint16_t TV_CH4);
uint8_t setChCurrentLimit(uint8_t ChNum, uint16_t CurrentLimit);
void setAllChCurrentLimit(uint16_t CurrentLimit);
void setAllChCurrentLimit(uint16_t CL_CH1, uint16_t CL_CH2, uint16_t CL_CH3, uint16_t CL_CH4);
uint8_t setChVoltageAndCurrentLimit(uint8_t ChNum, uint16_t TargetVoltage, uint16_t CurrentLimit);
void setAllChVoltageAndCurrentLimit(uint16_t TargetVoltage, uint16_t CurrentLimit);
void setAllChVoltageAndCurrentLimit(uint16_t VCH1, uint16_t CCH1, uint16_t VCH2, uint16_t CCH2, uint16_t VCH3, uint16_t CCH3, uint16_t VCH4, uint16_t CCH4);
IdiBus_4DC_PSUChannel getChData(uint8_t ChNum);
protected :
IdiBus_4DC_PSUChannel CH[IDIBUS_4DC_CH_COUNT];
virtual IdiBusChannel *getChannel(uint8_t Num);
void parsePsuChState(uint8_t *State, uint8_t ChNum);
void parsePsuChAllState(uint8_t *State, uint8_t ChNum);
void setAllPsuChErr(uint8_t ErrCode);
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBus_4DC_INPVChannel : public IdiBusChannel {
public:
IdiBus_4DC_INPVChannel(void);
uint16_t InpVoltage;
union {
uint8_t Sum;
struct {
uint8_t Undervoltage : 1;
uint8_t Overvoltage : 1;
uint8_t Reserved : 6;
} BF;
} STATUS;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBus_4DC_INPVCDevice : public IdiBusDevice {
public :
IdiBus_4DC_INPVCDevice (void *ParentModule) : IdiBusDevice (ParentModule) {}
uint8_t getInputVoltage(void);
IdiBus_4DC_INPVChannel getChData(void);
protected :
IdiBus_4DC_INPVChannel INPV;
virtual IdiBusChannel *getChannel(uint8_t Num);
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBus_4DC : public IdiBusSlave {
public:
IdiBus_4DC (IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress) : IdiBusSlave(SlaveLine, SlaveAddress), PSUC_DEV(this), INPV_DEV(this) {}
IdiBus_4DC() : IdiBusSlave(), PSUC_DEV(this), INPV_DEV(this) {}
virtual IdiBusDevice *getDevice(uint8_t Num);
IdiBus_4DC_PSUCDevice PSUC_DEV;
IdiBus_4DC_INPVCDevice INPV_DEV;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_4DC_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents>
<ProjectComponent z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<CApiVersion></CApiVersion>
<CBundle></CBundle>
<CClass>Device</CClass>
<CGroup>Startup</CGroup>
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>2.0.0</CVersion>
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Description></Description>
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\2.0.401\include\</AbsolutePath>
<Attribute></Attribute>
<Category>include</Category>
<Condition>C</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>include/</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\2.0.401\include\avr\iom328pb.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>ciLFjy803ysEAt1ml/dotQ==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iom328pb.h</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\2.0.401\templates\main.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>KjvOcFWd++tbnsEMfVPd/w==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.c</Name>
<SelectString>Main file (.c)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\2.0.401\templates\main.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>jUpFIcLr99QCZJmYGdbF/A==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.cpp</Name>
<SelectString>Main file (.cpp)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\Atmel\ATmega_DFP\2.0.401\gcc\dev\atmega328pb</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>gcc/dev/atmega328pb</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
</Files>
<PackName>ATmega_DFP</PackName>
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/Atmel/ATmega_DFP/2.0.401/Atmel.ATmega_DFP.pdsc</PackPath>
<PackVersion>2.0.401</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATmega328PB</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string></d4p1:string>
</RteComponents>
<Status>Resolved</Status>
<VersionMode>Fixed</VersionMode>
<IsComponentInAtProject>true</IsComponentInAtProject>
</ProjectComponent>
</ProjectComponents>
</Store>

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>{6a6fbffd-b460-4b8d-ac37-72193bed073f}</ProjectGuid>
<avrdevice>ATmega328PB</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>1xGenTest</AssemblyName>
<Name>1xGenTest</Name>
<RootNamespace>1xGenTest</RootNamespace>
<ToolchainFlavour>Native</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<AsfFrameworkConfig>
<framework-data xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.52.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\gcc\dev\atmega328pb"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\gcc\dev\atmega328pb"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\Atmel\ATmega_DFP\2.0.401\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="main.cpp">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

@ -0,0 +1,150 @@
#ifdef F_CPU
#undef F_CPU
#endif
#define F_CPU 16000000UL
#include <Arduino.h>
#include "IdiBusSerialLine.h"
#include "IDIBUS_1xGen.h"
#include "MBOARD_POWER.h"
#include <avr/wdt.h>
IdiBusSerialLine Serial_Line0;
IdiBusSerialLine Serial_Line1;
void setup()
{
MBOARD_POWER_OFF_ON();
delay(50);
IDIBUS_SERIAL_INIT_TYPEDEF L0Init;
L0Init.USART_NUMBER = IDIBUS_SERIAL_USART2; // select USART
L0Init.TIMER_NUMBER = IDIBUS_TIMER_1; // select timer
L0Init.CONFIG = IDIBUS_SERIAL_8N2; // 8 bit, 2 stop
L0Init.RS485_DIR_PIN = 6; // direction pin in-out
L0Init.BAUDRATE_DIPSW_S0_PIN = 9; // speed selector pins
L0Init.BAUDRATE_DIPSW_S1_PIN = 8;
L0Init.BAUDRATE_DIPSW_S2_PIN = 7;
Serial_Line0.Init(&L0Init); // Init line with with config above
Serial_Line0.UpdateBaudrateFromDipSwitch(); // speed setup
Serial_Line0.Start(); // run!
IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF L1Init;
L1Init.USART_NUMBER = IDIBUS_SERIAL_USART1;
L1Init.TIMER_NUMBER = IDIBUS_TIMER_3;
L1Init.CONFIG = IDIBUS_SERIAL_8N2;
L1Init.RS485_DIR_GPIO.PORT = &PORTL;
L1Init.RS485_DIR_GPIO.PIN_NUM = 6;
L1Init.BAUDRATE_DIPSW.S0.PORT = &PORTD;
L1Init.BAUDRATE_DIPSW.S0.PIN_NUM = 1;
L1Init.BAUDRATE_DIPSW.S1.PORT = &PORTD;
L1Init.BAUDRATE_DIPSW.S1.PIN_NUM = 0;
L1Init.BAUDRATE_DIPSW.S2.PORT = &PORTL;
L1Init.BAUDRATE_DIPSW.S2.PIN_NUM = 7;
Serial_Line1.Init(&L1Init);
Serial_Line1.UpdateBaudrateFromDipSwitch();
Serial_Line1.Start();
Serial.begin(115200,SERIAL_8N2); // usart0 for debug
#define BAUD 16000000UL/16/250000UL-1 // BAUD speed = 250000 bod
UBRR3 = (uint16_t)(BAUD); // USART BAUD RATE INIT
UCSR3B = (1<<RXEN3)|(1<<TXEN3); // USART ENABLE TX RX
while (!(UCSR3A & (1<<UDRE3))); // wait for send
UDR3 = 'R'; // send 'R'
while (!(UCSR3A & (1<<UDRE3))); // wait for send
UDR3 = '+'; // send '+'
delay(500); // Power on delay for external periphery
volatile uint8_t ErrorCode; // buffer for error codes
IdiBusLongOpData LopData; // Long operation data (not used in current example)
Inputs Settings;
IdiBus_1xGen TEMP(&Serial_Line0, 2);
ErrorCode = TEMP.c_Init();
delay(1000);
//uint8_t TxData[12] = {0x01, 0x4E, 0x20, 0x28, 0x01, 0x00, 0x01, 0x9C, 0x40, 0x28, 0x01, 0x01};
Settings.first_mode_time = 2;
Settings.first_mode_pwm_value = 40000;
Settings.first_mode_f = 40;
Settings.first_mode_invert = 1; // 0 || 1
Settings.first_mode_R1 = 0; // 0 || 1
Settings.second_mode_time = 2;
Settings.second_mode_pwm_value = 20000;
Settings.second_mode_f = 60;
Settings.second_mode_invert = 1; // 0 || 1
Settings.second_mode_R1 = 1; // 0 || 1
uint8_t TxData[12] = {Settings.first_mode_time,
(uint8_t)((Settings.first_mode_pwm_value >> 8) & 0xFF), (uint8_t)(Settings.first_mode_pwm_value & 0xFF),
Settings.first_mode_f, Settings.first_mode_invert, Settings.first_mode_R1,
Settings.second_mode_time,
(uint8_t)((Settings.second_mode_pwm_value >> 8) & 0xFF), (uint8_t)(Settings.second_mode_pwm_value & 0xFF),
Settings.second_mode_f, Settings.second_mode_invert, Settings.second_mode_R1};
TEMP.start_SPI(TxData);
//TEMP.reset_STM();
Serial_Line1.UpdateBaudrateFromDipSwitch();
}
uint8_t MBOARD_POWER_SET(uint8_t juction, uint8_t set) // power channel ON/OFF
{
Serial3.begin(115200,SERIAL_8N1); // usart3 for 328pb on MBoard
uint8_t string[2];
if((juction==MBOARD_POWER_J89_05V)&&(set==MBOARD_POWER_ON))
{
Serial3.print("5+"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
else if((juction==MBOARD_POWER_J89_05V)&&(set==MBOARD_POWER_OFF))
{
Serial3.print("5-"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
else if((juction==MBOARD_POWER_J89_24V)&&(set==MBOARD_POWER_ON))
{
Serial3.print("J+"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
else if((juction==MBOARD_POWER_J89_24V)&&(set==MBOARD_POWER_OFF))
{
Serial3.print("J-"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
else if((juction==MBOARD_POWER_J67_24V)&&(set==MBOARD_POWER_ON))
{
Serial3.print("R+"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
else if((juction==MBOARD_POWER_J67_24V)&&(set==MBOARD_POWER_OFF))
{
Serial3.print("R-"); delay(10);
Serial3.readBytes(string, 2);
if((string[0]=='O')&&(string[1]=='K')) return MBOARD_POWER_OK;
}
while(Serial3.available()>0) string[0]=Serial3.read();
return MBOARD_POWER_ERR;
}
void MBOARD_POWER_OFF_ON(void) // âûêëþ÷åíèå, ïàóçà è ïîñëåäîâàòåëüíîå âêëþ÷åíèå âñåõ ïèòàíèé
{
MBOARD_POWER_SET(MBOARD_POWER_J89_05V, MBOARD_POWER_OFF);
MBOARD_POWER_SET(MBOARD_POWER_J89_24V, MBOARD_POWER_OFF);
MBOARD_POWER_SET(MBOARD_POWER_J67_24V, MBOARD_POWER_OFF);
delay(1000);wdt_reset();
MBOARD_POWER_SET(MBOARD_POWER_J89_05V, MBOARD_POWER_ON);
delay(500);wdt_reset();
MBOARD_POWER_SET(MBOARD_POWER_J89_24V, MBOARD_POWER_ON);
delay(500);wdt_reset();
MBOARD_POWER_SET(MBOARD_POWER_J67_24V, MBOARD_POWER_ON);
delay(1000);wdt_reset();
return;
}

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "IdiBus_Master", "IDIBUS_MASTER\idiBus_Master\IdiBus_Master.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "ArduinoCore", "IDIBUS_MASTER\ArduinoCore\ArduinoCore.cppproj", "{D2221125-FC2C-43AE-A08A-D2054A122DA5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AVR = Debug|AVR
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
{D2221125-FC2C-43AE-A08A-D2054A122DA5}.Debug|AVR.ActiveCfg = Debug|AVR
{D2221125-FC2C-43AE-A08A-D2054A122DA5}.Debug|AVR.Build.0 = Debug|AVR
{D2221125-FC2C-43AE-A08A-D2054A122DA5}.Release|AVR.ActiveCfg = Release|AVR
{D2221125-FC2C-43AE-A08A-D2054A122DA5}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents>
<ProjectComponent z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<CApiVersion></CApiVersion>
<CBundle></CBundle>
<CClass>Device</CClass>
<CGroup>Startup</CGroup>
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>1.6.0</CVersion>
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Description></Description>
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include\</AbsolutePath>
<Attribute></Attribute>
<Category>include</Category>
<Condition>C</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>include/</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\include\avr\iom2560.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>MkwPezikXVtYA90mpLpFfA==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iom2560.h</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\templates\library.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Lib</Condition>
<FileContentHash>VjSGq44t/3IHSL1ATPOBng==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/library.c</Name>
<SelectString>Main file (.c)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\templates\library.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Lib</Condition>
<FileContentHash>G0XtXwMIamMgYWpjMWDloQ==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/library.cpp</Name>
<SelectString>Main file (.cpp)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega2560</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>gcc/dev/atmega2560</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
</Files>
<PackName>ATmega_DFP</PackName>
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.6.364/Atmel.ATmega_DFP.pdsc</PackPath>
<PackVersion>1.6.364</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATmega2560</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string></d4p1:string>
</RteComponents>
<Status>Resolved</Status>
<VersionMode>Fixed</VersionMode>
<IsComponentInAtProject>true</IsComponentInAtProject>
</ProjectComponent>
</ProjectComponents>
</Store>

@ -0,0 +1,395 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>d2221125-fc2c-43ae-a08a-d2054a122da5</ProjectGuid>
<avrdevice>atmega2560</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>StaticLibrary</OutputType>
<Language>CPP</Language>
<OutputFileName>lib$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.a</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<Name>ArduinoCore</Name>
<ArduinoIdeDir>C:\Program Files (x86)\Arduino</ArduinoIdeDir>
<ArduinoProjectType>Core</ArduinoProjectType>
<ToolchainFlavour>Native</ToolchainFlavour>
<AssemblyName>ArduinoCore</AssemblyName>
<RootNamespace>ArduinoCore</RootNamespace>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<AsfFrameworkConfig>
<framework-data>
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.44.1" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.atmelice</avrtool>
<avrtoolserialnumber>J41800097429</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x1E9801</avrdeviceexpectedsignature>
<avrtoolinterface>JTAG</avrtoolinterface>
<avrtoolinterfaceclock>1000000</avrtoolinterfaceclock>
<com_atmel_avrdbg_tool_ispmk2>
<ToolOptions>
<InterfaceProperties>
<IspClock>0</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.ispmk2</ToolType>
<ToolNumber>193775278415</ToolNumber>
<ToolName>AVRISP mkII</ToolName>
</com_atmel_avrdbg_tool_ispmk2>
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
<com_atmel_avrdbg_tool_atmelice>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
<JtagDbgClock>1000000</JtagDbgClock>
</InterfaceProperties>
<InterfaceName>JTAG</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
<ToolNumber>J41800097429</ToolNumber>
<ToolName>Atmel-ICE</ToolName>
</com_atmel_avrdbg_tool_atmelice>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega2560 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega2560"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
<Value>IDIBUS_F_CPU=16000000L</Value>
<Value>ARDUINO=108013</Value>
<Value>ARDUINO_AVR_MEGA2560</Value>
<Value>ARDUINO_ARCH_AVR</Value>
<Value>USB_VID=0x2341</Value>
<Value>USB_PID=0x0010</Value>
<Value>USB_MANUFACTURER="\"Arduino LLC\""</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>..\include\core</Value>
<Value>..\include\variants\mega</Value>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.OtherFlags>-fno-threadsafe-statics</avrgcc.compiler.optimization.OtherFlags>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.InhibitAllWarnings>True</avrgcc.compiler.warnings.InhibitAllWarnings>
<avrgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -std=gnu11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
<Value>IDIBUS_F_CPU=16000000L</Value>
<Value>ARDUINO=108013</Value>
<Value>ARDUINO_AVR_MEGA2560</Value>
<Value>ARDUINO_ARCH_AVR</Value>
<Value>USB_VID=0x2341</Value>
<Value>USB_PID=0x0010</Value>
<Value>USB_MANUFACTURER="\"Arduino LLC\""</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>..\include\core</Value>
<Value>..\include\variants\mega</Value>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.OtherFlags>-fno-threadsafe-statics</avrgcccpp.compiler.optimization.OtherFlags>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.InhibitAllWarnings>True</avrgcccpp.compiler.warnings.InhibitAllWarnings>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=gnu++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.linker.miscellaneous.LinkerFlags>-Os</avrgcccpp.linker.miscellaneous.LinkerFlags>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega2560 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\gcc\dev\atmega2560"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
<Value>IDIBUS_F_CPU=16000000L</Value>
<Value>ARDUINO=108013</Value>
<Value>ARDUINO_AVR_MEGA2560</Value>
<Value>ARDUINO_ARCH_AVR</Value>
<Value>USB_VID=0x2341</Value>
<Value>USB_PID=0x0010</Value>
<Value>USB_MANUFACTURER="\"Arduino LLC\""</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>..\include\core</Value>
<Value>..\include\variants\mega</Value>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.OtherFlags>-fno-threadsafe-statics</avrgcc.compiler.optimization.OtherFlags>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.InhibitAllWarnings>True</avrgcc.compiler.warnings.InhibitAllWarnings>
<avrgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -std=gnu11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
<Value>IDIBUS_F_CPU=16000000L</Value>
<Value>ARDUINO=108013</Value>
<Value>ARDUINO_AVR_MEGA2560</Value>
<Value>ARDUINO_ARCH_AVR</Value>
<Value>USB_VID=0x2341</Value>
<Value>USB_PID=0x0010</Value>
<Value>USB_MANUFACTURER="\"Arduino LLC\""</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>..\include\core</Value>
<Value>..\include\variants\mega</Value>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.OtherFlags>-fno-threadsafe-statics</avrgcccpp.compiler.optimization.OtherFlags>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.InhibitAllWarnings>True</avrgcccpp.compiler.warnings.InhibitAllWarnings>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=gnu++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.linker.miscellaneous.LinkerFlags>-Os</avrgcccpp.linker.miscellaneous.LinkerFlags>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.6.364\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="include\core\Arduino.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\binary.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Client.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\HardwareSerial.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\HardwareSerial_private.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\IPAddress.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\new.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\PluggableUSB.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Print.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Printable.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Server.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Stream.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\Udp.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\USBAPI.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\USBCore.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\USBDesc.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\WCharacter.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\wiring_private.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\core\WString.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="include\variants\mega\pins_arduino.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\abi.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\CDC.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\HardwareSerial.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\HardwareSerial0.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\HardwareSerial1.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\HardwareSerial2.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\HardwareSerial3.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\hooks.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\IPAddress.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\main.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\new.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\PluggableUSB.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\PreprocessingAssembly\wiring_pulse.S">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\Print.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\Stream.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\Tone.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\USBCore.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\WInterrupts.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\wiring.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\wiring_analog.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\wiring_digital.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\wiring_pulse.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\wiring_shift.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\WMath.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\core\WString.cpp">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="include\" />
<Folder Include="include\core\" />
<Folder Include="include\variants\" />
<Folder Include="include\variants\mega\" />
<Folder Include="src\" />
<Folder Include="src\core\" />
<Folder Include="src\core\PreprocessingAssembly\" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

@ -0,0 +1,260 @@
/*
Arduino.h - Main include file for the Arduino SDK
Copyright (c) 2005-2013 Arduino Team. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Arduino_h
#define Arduino_h
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "binary.h"
#ifdef __cplusplus
extern "C"{
#endif
void yield(void);
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define EULER 2.718281828459045235360287471352
#define SERIAL 0x0
#define DISPLAY 0x1
#define LSBFIRST 0
#define MSBFIRST 1
#define CHANGE 1
#define FALLING 2
#define RISING 3
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#define DEFAULT 0
#define EXTERNAL 1
#define INTERNAL1V1 2
#define INTERNAL INTERNAL1V1
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define DEFAULT 0
#define EXTERNAL 4
#define INTERNAL1V1 8
#define INTERNAL INTERNAL1V1
#define INTERNAL2V56 9
#define INTERNAL2V56_EXTCAP 13
#else
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define INTERNAL1V1 2
#define INTERNAL2V56 3
#else
#define INTERNAL 3
#endif
#define DEFAULT 1
#define EXTERNAL 0
#endif
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
#define interrupts() sei()
#define noInterrupts() cli()
#define clockCyclesPerMicrosecond() ( IDIBUS_F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
#endif
typedef unsigned int word;
#define bit(b) (1UL << (b))
typedef bool boolean;
typedef uint8_t byte;
void init(void);
void initVariant(void);
int atexit(void (*func)()) __attribute__((weak));
void pinMode(uint8_t pin, uint8_t mode);
void digitalWrite(uint8_t pin, uint8_t val);
int digitalRead(uint8_t pin);
int analogRead(uint8_t pin);
void analogReference(uint8_t mode);
void analogWrite(uint8_t pin, int val);
unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long ms);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
void detachInterrupt(uint8_t interruptNum);
void setup(void);
void loop(void);
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
#define analogInPinToBit(P) (P)
// On the ATmega1280, the addresses of some of the port registers are
// greater than 255, so we can't store them in uint8_t's.
extern const uint16_t PROGMEM port_to_mode_PGM[];
extern const uint16_t PROGMEM port_to_input_PGM[];
extern const uint16_t PROGMEM port_to_output_PGM[];
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
//
// These perform slightly better as macros compared to inline functions
//
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
#define analogInPinToBit(P) (P)
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
#define NOT_A_PIN 0
#define NOT_A_PORT 0
#define NOT_AN_INTERRUPT -1
#ifdef ARDUINO_MAIN
#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 10
#define PK 11
#define PL 12
#endif
#define NOT_ON_TIMER 0
#define TIMER0A 1
#define TIMER0B 2
#define TIMER1A 3
#define TIMER1B 4
#define TIMER1C 5
#define TIMER2 6
#define TIMER2A 7
#define TIMER2B 8
#define TIMER3A 9
#define TIMER3B 10
#define TIMER3C 11
#define TIMER4A 12
#define TIMER4B 13
#define TIMER4C 14
#define TIMER4D 15
#define TIMER5A 16
#define TIMER5B 17
#define TIMER5C 18
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
#include "WCharacter.h"
#include "WString.h"
#include "HardwareSerial.h"
#include "USBAPI.h"
#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL)
#error "Targets with both UART0 and CDC serial not supported"
#endif
uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h, byte l);
#define word(...) makeWord(__VA_ARGS__)
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
void noTone(uint8_t _pin);
// WMath prototypes
long random(long);
long random(long, long);
void randomSeed(unsigned long);
long map(long, long, long, long, long);
#endif
#include "pins_arduino.h"
#endif

@ -0,0 +1,45 @@
/*
Client.h - Base class that provides Client
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef client_h
#define client_h
#include "Print.h"
#include "Stream.h"
#include "IPAddress.h"
class Client : public Stream {
public:
virtual int connect(IPAddress ip, uint16_t port) =0;
virtual int connect(const char *host, uint16_t port) =0;
virtual size_t write(uint8_t) =0;
virtual size_t write(const uint8_t *buf, size_t size) =0;
virtual int available() = 0;
virtual int read() = 0;
virtual int read(uint8_t *buf, size_t size) = 0;
virtual int peek() = 0;
virtual void flush() = 0;
virtual void stop() = 0;
virtual uint8_t connected() = 0;
virtual operator bool() = 0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
#endif

@ -0,0 +1,161 @@
/*
HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#ifndef HardwareSerial_h
#define HardwareSerial_h
#include <inttypes.h>
#include "Stream.h"
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which head is the index of the location
// to which to write the next incoming character and tail is the index of the
// location from which to read.
// NOTE: a "power of 2" buffer size is reccomended to dramatically
// optimize all the modulo operations for ring buffers.
// WARNING: When buffer sizes are increased to > 256, the buffer index
// variables are automatically increased in size, but the extra
// atomicity guards needed for that are not implemented. This will
// often work, but occasionally a race condition can occur that makes
// Serial behave erratically. See https://github.com/arduino/Arduino/issues/2405
#if !defined(SERIAL_TX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_TX_BUFFER_SIZE 16
#else
#define SERIAL_TX_BUFFER_SIZE 64
#endif
#endif
#if !defined(SERIAL_RX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_RX_BUFFER_SIZE 16
#else
#define SERIAL_RX_BUFFER_SIZE 64
#endif
#endif
#if (SERIAL_TX_BUFFER_SIZE>256)
typedef uint16_t tx_buffer_index_t;
#else
typedef uint8_t tx_buffer_index_t;
#endif
#if (SERIAL_RX_BUFFER_SIZE>256)
typedef uint16_t rx_buffer_index_t;
#else
typedef uint8_t rx_buffer_index_t;
#endif
// Define config for Serial.begin(baud, config);
#define SERIAL_5N1 0x00
#define SERIAL_6N1 0x02
#define SERIAL_7N1 0x04
#define SERIAL_8N1 0x06
#define SERIAL_5N2 0x08
#define SERIAL_6N2 0x0A
#define SERIAL_7N2 0x0C
#define SERIAL_8N2 0x0E
#define SERIAL_5E1 0x20
#define SERIAL_6E1 0x22
#define SERIAL_7E1 0x24
#define SERIAL_8E1 0x26
#define SERIAL_5E2 0x28
#define SERIAL_6E2 0x2A
#define SERIAL_7E2 0x2C
#define SERIAL_8E2 0x2E
#define SERIAL_5O1 0x30
#define SERIAL_6O1 0x32
#define SERIAL_7O1 0x34
#define SERIAL_8O1 0x36
#define SERIAL_5O2 0x38
#define SERIAL_6O2 0x3A
#define SERIAL_7O2 0x3C
#define SERIAL_8O2 0x3E
class HardwareSerial : public Stream
{
protected:
volatile uint8_t * const _ubrrh;
volatile uint8_t * const _ubrrl;
volatile uint8_t * const _ucsra;
volatile uint8_t * const _ucsrb;
volatile uint8_t * const _ucsrc;
volatile uint8_t * const _udr;
// Has any byte been written to the UART since begin()
bool _written;
volatile rx_buffer_index_t _rx_buffer_head;
volatile rx_buffer_index_t _rx_buffer_tail;
volatile tx_buffer_index_t _tx_buffer_head;
volatile tx_buffer_index_t _tx_buffer_tail;
// Don't put any members after these buffers, since only the first
// 32 bytes of this struct can be accessed quickly using the ldd
// instruction.
unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];
public:
inline HardwareSerial(
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
volatile uint8_t *ucsrc, volatile uint8_t *udr);
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
void begin(unsigned long, uint8_t);
void end();
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual int availableForWrite(void);
virtual void flush(void);
virtual size_t write(uint8_t);
inline size_t write(unsigned long n) { return write((uint8_t)n); }
inline size_t write(long n) { return write((uint8_t)n); }
inline size_t write(unsigned int n) { return write((uint8_t)n); }
inline size_t write(int n) { return write((uint8_t)n); }
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() { return true; }
// Interrupt handlers - Not intended to be called externally
inline void _rx_complete_irq(void);
void _tx_udr_empty_irq(void);
};
#if defined(UBRRH) || defined(UBRR0H)
extern HardwareSerial Serial;
#define HAVE_HWSERIAL0
#endif
#if defined(UBRR1H)
extern HardwareSerial Serial1;
#define HAVE_HWSERIAL1
#endif
#if defined(UBRR2H)
extern HardwareSerial Serial2;
#define HAVE_HWSERIAL2
#endif
#if defined(UBRR3H)
extern HardwareSerial Serial3;
#define HAVE_HWSERIAL3
#endif
extern void serialEventRun(void) __attribute__((weak));
#endif

@ -0,0 +1,123 @@
/*
HardwareSerial_private.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
*/
#include "wiring_private.h"
// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3)
// Ensure that the various bit positions we use are available with a 0
// postfix, so we can always use the values for UART0 for all UARTs. The
// alternative, passing the various values for each UART to the
// HardwareSerial constructor also works, but makes the code bigger and
// slower.
#if !defined(TXC0)
#if defined(TXC)
// Some chips like ATmega8 don't have UPE, only PE. The other bits are
// named as expected.
#if !defined(UPE) && defined(PE)
#define UPE PE
#endif
// On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc.
#define TXC0 TXC
#define RXEN0 RXEN
#define TXEN0 TXEN
#define RXCIE0 RXCIE
#define UDRIE0 UDRIE
#define U2X0 U2X
#define UPE0 UPE
#define UDRE0 UDRE
#elif defined(TXC1)
// Some devices have uart1 but no uart0
#define TXC0 TXC1
#define RXEN0 RXEN1
#define TXEN0 TXEN1
#define RXCIE0 RXCIE1
#define UDRIE0 UDRIE1
#define U2X0 U2X1
#define UPE0 UPE1
#define UDRE0 UDRE1
#else
#error No UART found in HardwareSerial.cpp
#endif
#endif // !defined TXC0
// Check at compiletime that it is really ok to use the bit positions of
// UART0 for the other UARTs as well, in case these values ever get
// changed for future hardware.
#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \
UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \
UDRE1 != UDRE0)
#error "Not all bit positions for UART1 are the same as for UART0"
#endif
#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \
UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \
UDRE2 != UDRE0)
#error "Not all bit positions for UART2 are the same as for UART0"
#endif
#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \
UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \
UDRE3 != UDRE0)
#error "Not all bit positions for UART3 are the same as for UART0"
#endif
// Constructors ////////////////////////////////////////////////////////////////
HardwareSerial::HardwareSerial(
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
volatile uint8_t *ucsrc, volatile uint8_t *udr) :
_ubrrh(ubrrh), _ubrrl(ubrrl),
_ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc),
_udr(udr),
_rx_buffer_head(0), _rx_buffer_tail(0),
_tx_buffer_head(0), _tx_buffer_tail(0)
{
}
// Actual interrupt handlers //////////////////////////////////////////////////////////////
void HardwareSerial::_rx_complete_irq(void)
{
if (bit_is_clear(*_ucsra, UPE0)) {
// No Parity error, read byte and store it in the buffer if there is
// room
unsigned char c = *_udr;
rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != _rx_buffer_tail) {
_rx_buffer[_rx_buffer_head] = c;
_rx_buffer_head = i;
}
} else {
// Parity error, read byte but discard it
*_udr;
};
}
#endif // whole file

@ -0,0 +1,78 @@
/*
IPAddress.h - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IPAddress_h
#define IPAddress_h
#include <stdint.h>
#include "Printable.h"
#include "WString.h"
// A class to make it easier to handle and pass around IP addresses
class IPAddress : public Printable {
private:
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _address;
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _address.bytes; };
public:
// Constructors
IPAddress();
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
bool fromString(const char *address);
bool fromString(const String &address) { return fromString(address.c_str()); }
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() const { return _address.dword; };
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
bool operator==(const uint8_t* addr) const;
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const { return _address.bytes[index]; };
uint8_t& operator[](int index) { return _address.bytes[index]; };
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);
IPAddress& operator=(uint32_t address);
virtual size_t printTo(Print& p) const;
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
};
const IPAddress INADDR_NONE(0,0,0,0);
#endif

@ -0,0 +1,74 @@
/*
PluggableUSB.h
Copyright (c) 2015 Arduino LLC
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PUSB_h
#define PUSB_h
#include "USBAPI.h"
#include <stdint.h>
#if defined(USBCON)
class PluggableUSBModule {
public:
PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint8_t *epType) :
numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType)
{ }
protected:
virtual bool setup(USBSetup& setup) = 0;
virtual int getInterface(uint8_t* interfaceCount) = 0;
virtual int getDescriptor(USBSetup& setup) = 0;
virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
uint8_t pluggedInterface;
uint8_t pluggedEndpoint;
const uint8_t numEndpoints;
const uint8_t numInterfaces;
const uint8_t *endpointType;
PluggableUSBModule *next = NULL;
friend class PluggableUSB_;
};
class PluggableUSB_ {
public:
PluggableUSB_();
bool plug(PluggableUSBModule *node);
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
void getShortName(char *iSerialNum);
private:
uint8_t lastIf;
uint8_t lastEp;
PluggableUSBModule* rootNode;
};
// Replacement for global singleton.
// This function prevents static-initialization-order-fiasco
// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
PluggableUSB_& PluggableUSB();
#endif
#endif

@ -0,0 +1,93 @@
/*
Print.h - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Print_h
#define Print_h
#include <inttypes.h>
#include <stdio.h> // for size_t
#include "WString.h"
#include "Printable.h"
#define DEC 10
#define HEX 16
#define OCT 8
#ifdef BIN // Prevent warnings if BIN is previously defined in "iotnx4.h" or similar
#undef BIN
#endif
#define BIN 2
class Print
{
private:
int write_error;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
protected:
void setWriteError(int err = 1) { write_error = err; }
public:
Print() : write_error(0) {}
int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
virtual size_t write(const uint8_t *buffer, size_t size);
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
// default to zero, meaning "a single write may block"
// should be overriden by subclasses with buffering
virtual int availableForWrite() { return 0; }
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
size_t println(const __FlashStringHelper *);
size_t println(const String &s);
size_t println(const char[]);
size_t println(char);
size_t println(unsigned char, int = DEC);
size_t println(int, int = DEC);
size_t println(unsigned int, int = DEC);
size_t println(long, int = DEC);
size_t println(unsigned long, int = DEC);
size_t println(double, int = 2);
size_t println(const Printable&);
size_t println(void);
virtual void flush() { /* Empty implementation for backward compatibility */ }
};
#endif

@ -0,0 +1,40 @@
/*
Printable.h - Interface class that allows printing of complex types
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Printable_h
#define Printable_h
#include <stdlib.h>
class Print;
/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual size_t printTo(Print& p) const = 0;
};
#endif

@ -0,0 +1,30 @@
/*
Server.h - Base class that provides Server
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef server_h
#define server_h
#include "Print.h"
class Server : public Print {
public:
virtual void begin() =0;
};
#endif

@ -0,0 +1,129 @@
/*
Stream.h - base class for character-based streams.
Copyright (c) 2010 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
parsing functions based on TextFinder library by Michael Margolis
*/
#ifndef Stream_h
#define Stream_h
#include <inttypes.h>
#include "Print.h"
// compatability macros for testing
/*
#define getInt() parseInt()
#define getInt(ignore) parseInt(ignore)
#define getFloat() parseFloat()
#define getFloat(ignore) parseFloat(ignore)
#define getString( pre_string, post_string, buffer, length)
readBytesBetween( pre_string, terminator, buffer, length)
*/
// This enumeration provides the lookahead options for parseInt(), parseFloat()
// The rules set out here are used until either the first valid character is found
// or a time out occurs due to lack of input.
enum LookaheadMode{
SKIP_ALL, // All invalid characters are ignored.
SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped.
};
#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field
class Stream : public Print
{
protected:
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
unsigned long _startMillis; // used for timeout measurement
int timedRead(); // read stream with timeout
int timedPeek(); // peek stream with timeout
int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout
public:
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
Stream() {_timeout=1000;}
// parsing methods
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
unsigned long getTimeout(void) { return _timeout; }
bool find(char *target); // reads data from the stream until the target string is found
bool find(uint8_t *target) { return find ((char *)target); }
// returns true if target string is found, false if timed out (see setTimeout)
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
// returns true if target string is found, false if timed out
bool find(char target) { return find (&target, 1); }
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
// returns the first valid (long) integer value from the current position.
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
// float version of parseInt
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
// terminates if length characters have been read or timeout (see setTimeout)
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
// Arduino String functions to be added here
String readString();
String readStringUntil(char terminator);
protected:
long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); }
float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); }
// These overload exists for compatibility with any class that has derived
// Stream and used parseFloat/Int with a custom ignore character. To keep
// the public API simple, these overload remains protected.
struct MultiTarget {
const char *str; // string you're searching for
size_t len; // length of string you're searching for
size_t index; // index used by the search routine.
};
// This allows you to search for an arbitrary number of strings.
// Returns index of the target that is found first or -1 if timeout occurs.
int findMulti(struct MultiTarget *targets, int tCount);
};
#undef NO_IGNORE_CHAR
#endif

@ -0,0 +1,209 @@
/*
USBAPI.h
Copyright (c) 2005-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __USBAPI__
#define __USBAPI__
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
#include "Arduino.h"
// This definitions is usefull if you want to reduce the EP_SIZE to 16
// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint
#ifndef USB_EP_SIZE
#define USB_EP_SIZE 64
#endif
#if defined(USBCON)
#include "USBDesc.h"
#include "USBCore.h"
//================================================================================
//================================================================================
// USB
#define EP_TYPE_CONTROL (0x00)
#define EP_TYPE_BULK_IN ((1<<EPTYPE1) | (1<<EPDIR))
#define EP_TYPE_BULK_OUT (1<<EPTYPE1)
#define EP_TYPE_INTERRUPT_IN ((1<<EPTYPE1) | (1<<EPTYPE0) | (1<<EPDIR))
#define EP_TYPE_INTERRUPT_OUT ((1<<EPTYPE1) | (1<<EPTYPE0))
#define EP_TYPE_ISOCHRONOUS_IN ((1<<EPTYPE0) | (1<<EPDIR))
#define EP_TYPE_ISOCHRONOUS_OUT (1<<EPTYPE0)
class USBDevice_
{
public:
USBDevice_();
bool configured();
void attach();
void detach(); // Serial port goes down too...
void poll();
bool wakeupHost(); // returns false, when wakeup cannot be processed
bool isSuspended();
};
extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
// Serial over CDC (Serial1 is the physical port)
struct ring_buffer;
#ifndef SERIAL_BUFFER_SIZE
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 64
#endif
#endif
#if (SERIAL_BUFFER_SIZE>256)
#error Please lower the CDC Buffer size
#endif
class Serial_ : public Stream
{
private:
int peek_buffer;
public:
Serial_() { peek_buffer = -1; };
void begin(unsigned long);
void begin(unsigned long, uint8_t);
void end(void);
virtual int available(void);
virtual int peek(void);
virtual int read(void);
virtual int availableForWrite(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t*, size_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
volatile uint8_t _rx_buffer_head;
volatile uint8_t _rx_buffer_tail;
unsigned char _rx_buffer[SERIAL_BUFFER_SIZE];
// This method allows processing "SEND_BREAK" requests sent by
// the USB host. Those requests indicate that the host wants to
// send a BREAK signal and are accompanied by a single uint16_t
// value, specifying the duration of the break. The value 0
// means to end any current break, while the value 0xffff means
// to start an indefinite break.
// readBreak() will return the value of the most recent break
// request, but will return it at most once, returning -1 when
// readBreak() is called again (until another break request is
// received, which is again returned once).
// This also mean that if two break requests are received
// without readBreak() being called in between, the value of the
// first request is lost.
// Note that the value returned is a long, so it can return
// 0-0xffff as well as -1.
int32_t readBreak();
// These return the settings specified by the USB host for the
// serial port. These aren't really used, but are offered here
// in case a sketch wants to act on these settings.
uint32_t baud();
uint8_t stopbits();
uint8_t paritytype();
uint8_t numbits();
bool dtr();
bool rts();
enum {
ONE_STOP_BIT = 0,
ONE_AND_HALF_STOP_BIT = 1,
TWO_STOP_BITS = 2,
};
enum {
NO_PARITY = 0,
ODD_PARITY = 1,
EVEN_PARITY = 2,
MARK_PARITY = 3,
SPACE_PARITY = 4,
};
};
extern Serial_ Serial;
#define HAVE_CDCSERIAL
//================================================================================
//================================================================================
// Low level API
typedef struct
{
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
uint16_t wIndex;
uint16_t wLength;
} USBSetup;
//================================================================================
//================================================================================
// MSC 'Driver'
int MSC_GetInterface(uint8_t* interfaceNum);
int MSC_GetDescriptor(int i);
bool MSC_Setup(USBSetup& setup);
bool MSC_Data(uint8_t rx,uint8_t tx);
//================================================================================
//================================================================================
// CSC 'Driver'
int CDC_GetInterface(uint8_t* interfaceNum);
int CDC_GetDescriptor(int i);
bool CDC_Setup(USBSetup& setup);
//================================================================================
//================================================================================
#define TRANSFER_PGM 0x80
#define TRANSFER_RELEASE 0x40
#define TRANSFER_ZERO 0x20
int USB_SendControl(uint8_t flags, const void* d, int len);
int USB_RecvControl(void* d, int len);
int USB_RecvControlLong(void* d, int len);
uint8_t USB_Available(uint8_t ep);
uint8_t USB_SendSpace(uint8_t ep);
int USB_Send(uint8_t ep, const void* data, int len); // blocking
int USB_Recv(uint8_t ep, void* data, int len); // non-blocking
int USB_Recv(uint8_t ep); // non-blocking
void USB_Flush(uint8_t ep);
#endif
#endif /* if defined(USBCON) */

@ -0,0 +1,304 @@
// Copyright (c) 2010, Peter Barrett
/*
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#ifndef __USBCORE_H__
#define __USBCORE_H__
#include "USBAPI.h"
// Standard requests
#define GET_STATUS 0
#define CLEAR_FEATURE 1
#define SET_FEATURE 3
#define SET_ADDRESS 5
#define GET_DESCRIPTOR 6
#define SET_DESCRIPTOR 7
#define GET_CONFIGURATION 8
#define SET_CONFIGURATION 9
#define GET_INTERFACE 10
#define SET_INTERFACE 11
// bmRequestType
#define REQUEST_HOSTTODEVICE 0x00
#define REQUEST_DEVICETOHOST 0x80
#define REQUEST_DIRECTION 0x80
#define REQUEST_STANDARD 0x00
#define REQUEST_CLASS 0x20
#define REQUEST_VENDOR 0x40
#define REQUEST_TYPE 0x60
#define REQUEST_DEVICE 0x00
#define REQUEST_INTERFACE 0x01
#define REQUEST_ENDPOINT 0x02
#define REQUEST_OTHER 0x03
#define REQUEST_RECIPIENT 0x03
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE)
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE)
#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE)
// Class requests
#define CDC_SET_LINE_CODING 0x20
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22
#define CDC_SEND_BREAK 0x23
#define MSC_RESET 0xFF
#define MSC_GET_MAX_LUN 0xFE
// Descriptors
#define USB_DEVICE_DESC_SIZE 18
#define USB_CONFIGUARTION_DESC_SIZE 9
#define USB_INTERFACE_DESC_SIZE 9
#define USB_ENDPOINT_DESC_SIZE 7
#define USB_DEVICE_DESCRIPTOR_TYPE 1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
#define USB_STRING_DESCRIPTOR_TYPE 3
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
// usb_20.pdf Table 9.6 Standard Feature Selectors
#define DEVICE_REMOTE_WAKEUP 1
#define ENDPOINT_HALT 2
#define TEST_MODE 3
// usb_20.pdf Figure 9-4. Information Returned by a GetStatus() Request to a Device
#define FEATURE_SELFPOWERED_ENABLED (1 << 0)
#define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1)
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
#define USB_DEVICE_CLASS_STORAGE 0x08
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
#define USB_CONFIG_POWERED_MASK 0x40
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0xC0
#define USB_CONFIG_REMOTE_WAKEUP 0x20
// bMaxPower in Configuration Descriptor
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
#ifndef USB_CONFIG_POWER
#define USB_CONFIG_POWER (500)
#endif
// bEndpointAddress in Endpoint Descriptor
#define USB_ENDPOINT_DIRECTION_MASK 0x80
#define USB_ENDPOINT_OUT(addr) (lowByte((addr) | 0x00))
#define USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80))
#define USB_ENDPOINT_TYPE_MASK 0x03
#define USB_ENDPOINT_TYPE_CONTROL 0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
#define USB_ENDPOINT_TYPE_BULK 0x02
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
#define MSC_SUBCLASS_SCSI 0x06
#define MSC_PROTOCOL_BULK_ONLY 0x50
#ifndef USB_VERSION
#define USB_VERSION 0x200
#endif
// Device
typedef struct {
u8 len; // 18
u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
u16 usbVersion; // 0x200 or 0x210
u8 deviceClass;
u8 deviceSubClass;
u8 deviceProtocol;
u8 packetSize0; // Packet 0
u16 idVendor;
u16 idProduct;
u16 deviceVersion; // 0x100
u8 iManufacturer;
u8 iProduct;
u8 iSerialNumber;
u8 bNumConfigurations;
} DeviceDescriptor;
// Config
typedef struct {
u8 len; // 9
u8 dtype; // 2
u16 clen; // total length
u8 numInterfaces;
u8 config;
u8 iconfig;
u8 attributes;
u8 maxPower;
} ConfigDescriptor;
// String
// Interface
typedef struct
{
u8 len; // 9
u8 dtype; // 4
u8 number;
u8 alternate;
u8 numEndpoints;
u8 interfaceClass;
u8 interfaceSubClass;
u8 protocol;
u8 iInterface;
} InterfaceDescriptor;
// Endpoint
typedef struct
{
u8 len; // 7
u8 dtype; // 5
u8 addr;
u8 attr;
u16 packetSize;
u8 interval;
} EndpointDescriptor;
// Interface Association Descriptor
// Used to bind 2 interfaces together in CDC compostite device
typedef struct
{
u8 len; // 8
u8 dtype; // 11
u8 firstInterface;
u8 interfaceCount;
u8 functionClass;
u8 funtionSubClass;
u8 functionProtocol;
u8 iInterface;
} IADDescriptor;
// CDC CS interface descriptor
typedef struct
{
u8 len; // 5
u8 dtype; // 0x24
u8 subtype;
u8 d0;
u8 d1;
} CDCCSInterfaceDescriptor;
typedef struct
{
u8 len; // 4
u8 dtype; // 0x24
u8 subtype;
u8 d0;
} CDCCSInterfaceDescriptor4;
typedef struct
{
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
u8 bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
u8 len;
u8 dtype; // 0x24
u8 subtype; // 1
u8 bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif; //
CDCCSInterfaceDescriptor header;
CMFunctionalDescriptor callManagement; // Call Management
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
typedef struct
{
InterfaceDescriptor msc;
EndpointDescriptor in;
EndpointDescriptor out;
} MSCDescriptor;
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
{ 18, 1, USB_VERSION, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
#define D_CONFIG(_totalLength,_interfaces) \
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(USB_CONFIG_POWER) }
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
{ 7, 5, _addr,_attr,_packetSize, _interval }
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
// Bootloader related fields
// Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten
// by the running sketch before to actual reboot).
// Newer bootloaders, recognizable by the LUFA "signature" at the end of the flash, can handle both
// the usafe and the safe location.
#ifndef MAGIC_KEY
#define MAGIC_KEY 0x7777
#endif
#ifndef MAGIC_KEY_POS
#define MAGIC_KEY_POS 0x0800
#endif
#ifndef NEW_LUFA_SIGNATURE
#define NEW_LUFA_SIGNATURE 0xDCFB
#endif
#endif

@ -0,0 +1,46 @@
/*
Copyright (c) 2011, Peter Barrett
Copyright (c) 2015, Arduino LLC
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
*/
#define PLUGGABLE_USB_ENABLED
#if defined(EPRST6)
#define USB_ENDPOINTS 7 // AtMegaxxU4
#else
#define USB_ENDPOINTS 5 // AtMegaxxU2
#endif
#define ISERIAL_MAX_LEN 20
#define CDC_INTERFACE_COUNT 2
#define CDC_ENPOINT_COUNT 3
#define CDC_ACM_INTERFACE 0 // CDC ACM
#define CDC_DATA_INTERFACE 1 // CDC Data
#define CDC_FIRST_ENDPOINT 1
#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
#define IMANUFACTURER 1
#define IPRODUCT 2
#define ISERIAL 3

@ -0,0 +1,89 @@
/*
* Udp.cpp: Library to send/receive UDP packets.
*
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
* might not happen often in practice, but in larger network topologies, a UDP
* packet can be received out of sequence.
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
* aware of it. Again, this may not be a concern in practice on small local networks.
* For more information, see http://www.cafeaulait.org/course/week12/35.html
*
* MIT License:
* Copyright (c) 2008 Bjoern Hartmann
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* bjoern@cs.stanford.edu 12/30/2008
*/
#ifndef udp_h
#define udp_h
#include <Stream.h>
#include <IPAddress.h>
class UDP : public Stream {
public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; } // initialize, start listening on specified multicast IP address and port. Returns 1 if successful, 0 on failure
virtual void stop() =0; // Finish with the UDP socket
// Sending UDP packets
// Start building up a packet to send to the remote host specific in ip and port
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
// Start building up a packet to send to the remote host specific in host and port
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
virtual int beginPacket(const char *host, uint16_t port) =0;
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
virtual int endPacket() =0;
// Write a single byte into the packet
virtual size_t write(uint8_t) =0;
// Write size bytes from buffer into the packet
virtual size_t write(const uint8_t *buffer, size_t size) =0;
// Start processing the next available incoming packet
// Returns the size of the packet in bytes, or 0 if no packets are available
virtual int parsePacket() =0;
// Number of bytes remaining in the current packet
virtual int available() =0;
// Read a single byte from the current packet
virtual int read() =0;
// Read up to len bytes from the current packet and place them into buffer
// Returns the number of bytes read, or 0 if none are available
virtual int read(unsigned char* buffer, size_t len) =0;
// Read up to len characters from the current packet and place them into buffer
// Returns the number of characters read, or 0 if none are available
virtual int read(char* buffer, size_t len) =0;
// Return the next byte from the current packet without moving on to the next byte
virtual int peek() =0;
virtual void flush() =0; // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() =0;
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() =0;
protected:
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
};
#endif

@ -0,0 +1,168 @@
/*
WCharacter.h - Character utility functions for Wiring & Arduino
Copyright (c) 2010 Hernando Barragan. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Character_h
#define Character_h
#include <ctype.h>
// WCharacter.h prototypes
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
inline boolean isAlpha(int c) __attribute__((always_inline));
inline boolean isAscii(int c) __attribute__((always_inline));
inline boolean isWhitespace(int c) __attribute__((always_inline));
inline boolean isControl(int c) __attribute__((always_inline));
inline boolean isDigit(int c) __attribute__((always_inline));
inline boolean isGraph(int c) __attribute__((always_inline));
inline boolean isLowerCase(int c) __attribute__((always_inline));
inline boolean isPrintable(int c) __attribute__((always_inline));
inline boolean isPunct(int c) __attribute__((always_inline));
inline boolean isSpace(int c) __attribute__((always_inline));
inline boolean isUpperCase(int c) __attribute__((always_inline));
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
inline int toAscii(int c) __attribute__((always_inline));
inline int toLowerCase(int c) __attribute__((always_inline));
inline int toUpperCase(int c)__attribute__((always_inline));
// Checks for an alphanumeric character.
// It is equivalent to (isalpha(c) || isdigit(c)).
inline boolean isAlphaNumeric(int c)
{
return ( isalnum(c) == 0 ? false : true);
}
// Checks for an alphabetic character.
// It is equivalent to (isupper(c) || islower(c)).
inline boolean isAlpha(int c)
{
return ( isalpha(c) == 0 ? false : true);
}
// Checks whether c is a 7-bit unsigned char value
// that fits into the ASCII character set.
inline boolean isAscii(int c)
{
return ( isascii (c) == 0 ? false : true);
}
// Checks for a blank character, that is, a space or a tab.
inline boolean isWhitespace(int c)
{
return ( isblank (c) == 0 ? false : true);
}
// Checks for a control character.
inline boolean isControl(int c)
{
return ( iscntrl (c) == 0 ? false : true);
}
// Checks for a digit (0 through 9).
inline boolean isDigit(int c)
{
return ( isdigit (c) == 0 ? false : true);
}
// Checks for any printable character except space.
inline boolean isGraph(int c)
{
return ( isgraph (c) == 0 ? false : true);
}
// Checks for a lower-case character.
inline boolean isLowerCase(int c)
{
return (islower (c) == 0 ? false : true);
}
// Checks for any printable character including space.
inline boolean isPrintable(int c)
{
return ( isprint (c) == 0 ? false : true);
}
// Checks for any printable character which is not a space
// or an alphanumeric character.
inline boolean isPunct(int c)
{
return ( ispunct (c) == 0 ? false : true);
}
// Checks for white-space characters. For the avr-libc library,
// these are: space, formfeed ('\f'), newline ('\n'), carriage
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
inline boolean isSpace(int c)
{
return ( isspace (c) == 0 ? false : true);
}
// Checks for an uppercase letter.
inline boolean isUpperCase(int c)
{
return ( isupper (c) == 0 ? false : true);
}
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
// 8 9 a b c d e f A B C D E F.
inline boolean isHexadecimalDigit(int c)
{
return ( isxdigit (c) == 0 ? false : true);
}
// Converts c to a 7-bit unsigned char value that fits into the
// ASCII character set, by clearing the high-order bits.
inline int toAscii(int c)
{
return toascii (c);
}
// Warning:
// Many people will be unhappy if you use this function.
// This function will convert accented letters into random
// characters.
// Converts the letter c to lower case, if possible.
inline int toLowerCase(int c)
{
return tolower (c);
}
// Converts the letter c to upper case, if possible.
inline int toUpperCase(int c)
{
return toupper (c);
}
#endif

@ -0,0 +1,229 @@
/*
WString.h - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef String_class_h
#define String_class_h
#ifdef __cplusplus
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <avr/pgmspace.h>
// When compiling programs with this class, the following gcc parameters
// dramatically increase performance and memory (RAM) efficiency, typically
// with little or no increase in code size.
// -felide-constructors
// -std=c++0x
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
// An inherited class for holding the result of a concatenation. These
// result objects are assumed to be writable by subsequent concatenations.
class StringSumHelper;
// The string class
class String
{
// use a function pointer to allow for "if (s)" without the
// complications of an operator bool(). for more information, see:
// http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
public:
// constructors
// creates a copy of the initial value.
// if the initial value is null or invalid, or if memory allocation
// fails, the string will be marked as invalid (i.e. "if (s)" will
// be false).
String(const char *cstr = "");
String(const String &str);
String(const __FlashStringHelper *str);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String(String &&rval);
String(StringSumHelper &&rval);
#endif
explicit String(char c);
explicit String(unsigned char, unsigned char base=10);
explicit String(int, unsigned char base=10);
explicit String(unsigned int, unsigned char base=10);
explicit String(long, unsigned char base=10);
explicit String(unsigned long, unsigned char base=10);
explicit String(float, unsigned char decimalPlaces=2);
explicit String(double, unsigned char decimalPlaces=2);
~String(void);
// memory management
// return true on success, false on failure (in which case, the string
// is left unchanged). reserve(0), if successful, will validate an
// invalid string (i.e., "if (s)" will be true afterwards)
unsigned char reserve(unsigned int size);
inline unsigned int length(void) const {return len;}
// creates a copy of the assigned value. if the value is null or
// invalid, or if the memory allocation fails, the string will be
// marked as invalid ("if (s)" will be false).
String & operator = (const String &rhs);
String & operator = (const char *cstr);
String & operator = (const __FlashStringHelper *str);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & operator = (String &&rval);
String & operator = (StringSumHelper &&rval);
#endif
// concatenate (works w/ built-in types)
// returns true on success, false on failure (in which case, the string
// is left unchanged). if the argument is null or invalid, the
// concatenation is considered unsucessful.
unsigned char concat(const String &str);
unsigned char concat(const char *cstr);
unsigned char concat(char c);
unsigned char concat(unsigned char c);
unsigned char concat(int num);
unsigned char concat(unsigned int num);
unsigned char concat(long num);
unsigned char concat(unsigned long num);
unsigned char concat(float num);
unsigned char concat(double num);
unsigned char concat(const __FlashStringHelper * str);
// if there's not enough memory for the concatenated value, the string
// will be left unchanged (but this isn't signalled in any way)
String & operator += (const String &rhs) {concat(rhs); return (*this);}
String & operator += (const char *cstr) {concat(cstr); return (*this);}
String & operator += (char c) {concat(c); return (*this);}
String & operator += (unsigned char num) {concat(num); return (*this);}
String & operator += (int num) {concat(num); return (*this);}
String & operator += (unsigned int num) {concat(num); return (*this);}
String & operator += (long num) {concat(num); return (*this);}
String & operator += (unsigned long num) {concat(num); return (*this);}
String & operator += (float num) {concat(num); return (*this);}
String & operator += (double num) {concat(num); return (*this);}
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
// comparison (only works w/ Strings and "strings")
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
int compareTo(const String &s) const;
unsigned char equals(const String &s) const;
unsigned char equals(const char *cstr) const;
unsigned char operator == (const String &rhs) const {return equals(rhs);}
unsigned char operator == (const char *cstr) const {return equals(cstr);}
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
unsigned char operator < (const String &rhs) const;
unsigned char operator > (const String &rhs) const;
unsigned char operator <= (const String &rhs) const;
unsigned char operator >= (const String &rhs) const;
unsigned char equalsIgnoreCase(const String &s) const;
unsigned char startsWith( const String &prefix) const;
unsigned char startsWith(const String &prefix, unsigned int offset) const;
unsigned char endsWith(const String &suffix) const;
// character acccess
char charAt(unsigned int index) const;
void setCharAt(unsigned int index, char c);
char operator [] (unsigned int index) const;
char& operator [] (unsigned int index);
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
{ getBytes((unsigned char *)buf, bufsize, index); }
const char* c_str() const { return buffer; }
char* begin() { return buffer; }
char* end() { return buffer + length(); }
const char* begin() const { return c_str(); }
const char* end() const { return c_str() + length(); }
// search
int indexOf( char ch ) const;
int indexOf( char ch, unsigned int fromIndex ) const;
int indexOf( const String &str ) const;
int indexOf( const String &str, unsigned int fromIndex ) const;
int lastIndexOf( char ch ) const;
int lastIndexOf( char ch, unsigned int fromIndex ) const;
int lastIndexOf( const String &str ) const;
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
// modification
void replace(char find, char replace);
void replace(const String& find, const String& replace);
void remove(unsigned int index);
void remove(unsigned int index, unsigned int count);
void toLowerCase(void);
void toUpperCase(void);
void trim(void);
// parsing/conversion
long toInt(void) const;
float toFloat(void) const;
double toDouble(void) const;
protected:
char *buffer; // the actual char array
unsigned int capacity; // the array length minus one (for the '\0')
unsigned int len; // the String length (not counting the '\0')
protected:
void init(void);
void invalidate(void);
unsigned char changeBuffer(unsigned int maxStrLen);
unsigned char concat(const char *cstr, unsigned int length);
// copy and move
String & copy(const char *cstr, unsigned int length);
String & copy(const __FlashStringHelper *pstr, unsigned int length);
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void move(String &rhs);
#endif
};
class StringSumHelper : public String
{
public:
StringSumHelper(const String &s) : String(s) {}
StringSumHelper(const char *p) : String(p) {}
StringSumHelper(char c) : String(c) {}
StringSumHelper(unsigned char num) : String(num) {}
StringSumHelper(int num) : String(num) {}
StringSumHelper(unsigned int num) : String(num) {}
StringSumHelper(long num) : String(num) {}
StringSumHelper(unsigned long num) : String(num) {}
StringSumHelper(float num) : String(num) {}
StringSumHelper(double num) : String(num) {}
};
#endif // __cplusplus
#endif // String_class_h

@ -0,0 +1,534 @@
/*
binary.h - Definitions for binary constants
Copyright (c) 2006 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Binary_h
#define Binary_h
#define B0 0
#define B00 0
#define B000 0
#define B0000 0
#define B00000 0
#define B000000 0
#define B0000000 0
#define B00000000 0
#define B1 1
#define B01 1
#define B001 1
#define B0001 1
#define B00001 1
#define B000001 1
#define B0000001 1
#define B00000001 1
#define B10 2
#define B010 2
#define B0010 2
#define B00010 2
#define B000010 2
#define B0000010 2
#define B00000010 2
#define B11 3
#define B011 3
#define B0011 3
#define B00011 3
#define B000011 3
#define B0000011 3
#define B00000011 3
#define B100 4
#define B0100 4
#define B00100 4
#define B000100 4
#define B0000100 4
#define B00000100 4
#define B101 5
#define B0101 5
#define B00101 5
#define B000101 5
#define B0000101 5
#define B00000101 5
#define B110 6
#define B0110 6
#define B00110 6
#define B000110 6
#define B0000110 6
#define B00000110 6
#define B111 7
#define B0111 7
#define B00111 7
#define B000111 7
#define B0000111 7
#define B00000111 7
#define B1000 8
#define B01000 8
#define B001000 8
#define B0001000 8
#define B00001000 8
#define B1001 9
#define B01001 9
#define B001001 9
#define B0001001 9
#define B00001001 9
#define B1010 10
#define B01010 10
#define B001010 10
#define B0001010 10
#define B00001010 10
#define B1011 11
#define B01011 11
#define B001011 11
#define B0001011 11
#define B00001011 11
#define B1100 12
#define B01100 12
#define B001100 12
#define B0001100 12
#define B00001100 12
#define B1101 13
#define B01101 13
#define B001101 13
#define B0001101 13
#define B00001101 13
#define B1110 14
#define B01110 14
#define B001110 14
#define B0001110 14
#define B00001110 14
#define B1111 15
#define B01111 15
#define B001111 15
#define B0001111 15
#define B00001111 15
#define B10000 16
#define B010000 16
#define B0010000 16
#define B00010000 16
#define B10001 17
#define B010001 17
#define B0010001 17
#define B00010001 17
#define B10010 18
#define B010010 18
#define B0010010 18
#define B00010010 18
#define B10011 19
#define B010011 19
#define B0010011 19
#define B00010011 19
#define B10100 20
#define B010100 20
#define B0010100 20
#define B00010100 20
#define B10101 21
#define B010101 21
#define B0010101 21
#define B00010101 21
#define B10110 22
#define B010110 22
#define B0010110 22
#define B00010110 22
#define B10111 23
#define B010111 23
#define B0010111 23
#define B00010111 23
#define B11000 24
#define B011000 24
#define B0011000 24
#define B00011000 24
#define B11001 25
#define B011001 25
#define B0011001 25
#define B00011001 25
#define B11010 26
#define B011010 26
#define B0011010 26
#define B00011010 26
#define B11011 27
#define B011011 27
#define B0011011 27
#define B00011011 27
#define B11100 28
#define B011100 28
#define B0011100 28
#define B00011100 28
#define B11101 29
#define B011101 29
#define B0011101 29
#define B00011101 29
#define B11110 30
#define B011110 30
#define B0011110 30
#define B00011110 30
#define B11111 31
#define B011111 31
#define B0011111 31
#define B00011111 31
#define B100000 32
#define B0100000 32
#define B00100000 32
#define B100001 33
#define B0100001 33
#define B00100001 33
#define B100010 34
#define B0100010 34
#define B00100010 34
#define B100011 35
#define B0100011 35
#define B00100011 35
#define B100100 36
#define B0100100 36
#define B00100100 36
#define B100101 37
#define B0100101 37
#define B00100101 37
#define B100110 38
#define B0100110 38
#define B00100110 38
#define B100111 39
#define B0100111 39
#define B00100111 39
#define B101000 40
#define B0101000 40
#define B00101000 40
#define B101001 41
#define B0101001 41
#define B00101001 41
#define B101010 42
#define B0101010 42
#define B00101010 42
#define B101011 43
#define B0101011 43
#define B00101011 43
#define B101100 44
#define B0101100 44
#define B00101100 44
#define B101101 45
#define B0101101 45
#define B00101101 45
#define B101110 46
#define B0101110 46
#define B00101110 46
#define B101111 47
#define B0101111 47
#define B00101111 47
#define B110000 48
#define B0110000 48
#define B00110000 48
#define B110001 49
#define B0110001 49
#define B00110001 49
#define B110010 50
#define B0110010 50
#define B00110010 50
#define B110011 51
#define B0110011 51
#define B00110011 51
#define B110100 52
#define B0110100 52
#define B00110100 52
#define B110101 53
#define B0110101 53
#define B00110101 53
#define B110110 54
#define B0110110 54
#define B00110110 54
#define B110111 55
#define B0110111 55
#define B00110111 55
#define B111000 56
#define B0111000 56
#define B00111000 56
#define B111001 57
#define B0111001 57
#define B00111001 57
#define B111010 58
#define B0111010 58
#define B00111010 58
#define B111011 59
#define B0111011 59
#define B00111011 59
#define B111100 60
#define B0111100 60
#define B00111100 60
#define B111101 61
#define B0111101 61
#define B00111101 61
#define B111110 62
#define B0111110 62
#define B00111110 62
#define B111111 63
#define B0111111 63
#define B00111111 63
#define B1000000 64
#define B01000000 64
#define B1000001 65
#define B01000001 65
#define B1000010 66
#define B01000010 66
#define B1000011 67
#define B01000011 67
#define B1000100 68
#define B01000100 68
#define B1000101 69
#define B01000101 69
#define B1000110 70
#define B01000110 70
#define B1000111 71
#define B01000111 71
#define B1001000 72
#define B01001000 72
#define B1001001 73
#define B01001001 73
#define B1001010 74
#define B01001010 74
#define B1001011 75
#define B01001011 75
#define B1001100 76
#define B01001100 76
#define B1001101 77
#define B01001101 77
#define B1001110 78
#define B01001110 78
#define B1001111 79
#define B01001111 79
#define B1010000 80
#define B01010000 80
#define B1010001 81
#define B01010001 81
#define B1010010 82
#define B01010010 82
#define B1010011 83
#define B01010011 83
#define B1010100 84
#define B01010100 84
#define B1010101 85
#define B01010101 85
#define B1010110 86
#define B01010110 86
#define B1010111 87
#define B01010111 87
#define B1011000 88
#define B01011000 88
#define B1011001 89
#define B01011001 89
#define B1011010 90
#define B01011010 90
#define B1011011 91
#define B01011011 91
#define B1011100 92
#define B01011100 92
#define B1011101 93
#define B01011101 93
#define B1011110 94
#define B01011110 94
#define B1011111 95
#define B01011111 95
#define B1100000 96
#define B01100000 96
#define B1100001 97
#define B01100001 97
#define B1100010 98
#define B01100010 98
#define B1100011 99
#define B01100011 99
#define B1100100 100
#define B01100100 100
#define B1100101 101
#define B01100101 101
#define B1100110 102
#define B01100110 102
#define B1100111 103
#define B01100111 103
#define B1101000 104
#define B01101000 104
#define B1101001 105
#define B01101001 105
#define B1101010 106
#define B01101010 106
#define B1101011 107
#define B01101011 107
#define B1101100 108
#define B01101100 108
#define B1101101 109
#define B01101101 109
#define B1101110 110
#define B01101110 110
#define B1101111 111
#define B01101111 111
#define B1110000 112
#define B01110000 112
#define B1110001 113
#define B01110001 113
#define B1110010 114
#define B01110010 114
#define B1110011 115
#define B01110011 115
#define B1110100 116
#define B01110100 116
#define B1110101 117
#define B01110101 117
#define B1110110 118
#define B01110110 118
#define B1110111 119
#define B01110111 119
#define B1111000 120
#define B01111000 120
#define B1111001 121
#define B01111001 121
#define B1111010 122
#define B01111010 122
#define B1111011 123
#define B01111011 123
#define B1111100 124
#define B01111100 124
#define B1111101 125
#define B01111101 125
#define B1111110 126
#define B01111110 126
#define B1111111 127
#define B01111111 127
#define B10000000 128
#define B10000001 129
#define B10000010 130
#define B10000011 131
#define B10000100 132
#define B10000101 133
#define B10000110 134
#define B10000111 135
#define B10001000 136
#define B10001001 137
#define B10001010 138
#define B10001011 139
#define B10001100 140
#define B10001101 141
#define B10001110 142
#define B10001111 143
#define B10010000 144
#define B10010001 145
#define B10010010 146
#define B10010011 147
#define B10010100 148
#define B10010101 149
#define B10010110 150
#define B10010111 151
#define B10011000 152
#define B10011001 153
#define B10011010 154
#define B10011011 155
#define B10011100 156
#define B10011101 157
#define B10011110 158
#define B10011111 159
#define B10100000 160
#define B10100001 161
#define B10100010 162
#define B10100011 163
#define B10100100 164
#define B10100101 165
#define B10100110 166
#define B10100111 167
#define B10101000 168
#define B10101001 169
#define B10101010 170
#define B10101011 171
#define B10101100 172
#define B10101101 173
#define B10101110 174
#define B10101111 175
#define B10110000 176
#define B10110001 177
#define B10110010 178
#define B10110011 179
#define B10110100 180
#define B10110101 181
#define B10110110 182
#define B10110111 183
#define B10111000 184
#define B10111001 185
#define B10111010 186
#define B10111011 187
#define B10111100 188
#define B10111101 189
#define B10111110 190
#define B10111111 191
#define B11000000 192
#define B11000001 193
#define B11000010 194
#define B11000011 195
#define B11000100 196
#define B11000101 197
#define B11000110 198
#define B11000111 199
#define B11001000 200
#define B11001001 201
#define B11001010 202
#define B11001011 203
#define B11001100 204
#define B11001101 205
#define B11001110 206
#define B11001111 207
#define B11010000 208
#define B11010001 209
#define B11010010 210
#define B11010011 211
#define B11010100 212
#define B11010101 213
#define B11010110 214
#define B11010111 215
#define B11011000 216
#define B11011001 217
#define B11011010 218
#define B11011011 219
#define B11011100 220
#define B11011101 221
#define B11011110 222
#define B11011111 223
#define B11100000 224
#define B11100001 225
#define B11100010 226
#define B11100011 227
#define B11100100 228
#define B11100101 229
#define B11100110 230
#define B11100111 231
#define B11101000 232
#define B11101001 233
#define B11101010 234
#define B11101011 235
#define B11101100 236
#define B11101101 237
#define B11101110 238
#define B11101111 239
#define B11110000 240
#define B11110001 241
#define B11110010 242
#define B11110011 243
#define B11110100 244
#define B11110101 245
#define B11110110 246
#define B11110111 247
#define B11111000 248
#define B11111001 249
#define B11111010 250
#define B11111011 251
#define B11111100 252
#define B11111101 253
#define B11111110 254
#define B11111111 255
#endif

@ -0,0 +1,31 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef NEW_H
#define NEW_H
#include <stdlib.h>
void * operator new(size_t size);
void * operator new[](size_t size);
void * operator new(size_t size, void * ptr) noexcept;
void operator delete(void * ptr);
void operator delete[](void * ptr);
#endif

@ -0,0 +1,72 @@
/*
wiring_private.h - Internal header file.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#ifndef WiringPrivate_h
#define WiringPrivate_h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdarg.h>
#include "Arduino.h"
#ifdef __cplusplus
extern "C"{
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops);
#define EXTERNAL_INT_0 0
#define EXTERNAL_INT_1 1
#define EXTERNAL_INT_2 2
#define EXTERNAL_INT_3 3
#define EXTERNAL_INT_4 4
#define EXTERNAL_INT_5 5
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) || \
defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define EXTERNAL_NUM_INTERRUPTS 3
#elif defined(__AVR_ATmega32U4__)
#define EXTERNAL_NUM_INTERRUPTS 5
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif
typedef void (*voidFuncPtr)(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

@ -0,0 +1,413 @@
/*
pins_arduino.h - Pin definition functions for Arduino
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2007 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <avr/pgmspace.h>
#define NUM_DIGITAL_PINS 70
#define NUM_ANALOG_INPUTS 16
#define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1)
#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46))
#define PIN_SPI_SS (53)
#define PIN_SPI_MOSI (51)
#define PIN_SPI_MISO (50)
#define PIN_SPI_SCK (52)
static const uint8_t SS = PIN_SPI_SS;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_WIRE_SDA (20)
#define PIN_WIRE_SCL (21)
static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;
#define LED_BUILTIN 13
#define PIN_A0 (54)
#define PIN_A1 (55)
#define PIN_A2 (56)
#define PIN_A3 (57)
#define PIN_A4 (58)
#define PIN_A5 (59)
#define PIN_A6 (60)
#define PIN_A7 (61)
#define PIN_A8 (62)
#define PIN_A9 (63)
#define PIN_A10 (64)
#define PIN_A11 (65)
#define PIN_A12 (66)
#define PIN_A13 (67)
#define PIN_A14 (68)
#define PIN_A15 (69)
static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
static const uint8_t A8 = PIN_A8;
static const uint8_t A9 = PIN_A9;
static const uint8_t A10 = PIN_A10;
static const uint8_t A11 = PIN_A11;
static const uint8_t A12 = PIN_A12;
static const uint8_t A13 = PIN_A13;
static const uint8_t A14 = PIN_A14;
static const uint8_t A15 = PIN_A15;
// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins)
// Only pins available for RECEIVE (TRANSMIT can be on any pin):
// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me)
// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69
#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \
(((p) >= 50) && ((p) <= 53)) || \
(((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) )
#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \
( (((p) >= 62) && ((p) <= 69)) ? 2 : \
0 ) )
#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \
( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \
((uint8_t *)0) ) )
#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \
( ((p) == 50) ? 3 : \
( ((p) == 51) ? 2 : \
( ((p) == 52) ? 1 : \
( ((p) == 53) ? 0 : \
( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \
0 ) ) ) ) ) )
#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : ((p) >= 18 && (p) <= 21 ? 23 - (p) : NOT_AN_INTERRUPT)))
#ifdef ARDUINO_MAIN
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
(uint16_t) &DDRA,
(uint16_t) &DDRB,
(uint16_t) &DDRC,
(uint16_t) &DDRD,
(uint16_t) &DDRE,
(uint16_t) &DDRF,
(uint16_t) &DDRG,
(uint16_t) &DDRH,
NOT_A_PORT,
(uint16_t) &DDRJ,
(uint16_t) &DDRK,
(uint16_t) &DDRL,
};
const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
(uint16_t) &PORTA,
(uint16_t) &PORTB,
(uint16_t) &PORTC,
(uint16_t) &PORTD,
(uint16_t) &PORTE,
(uint16_t) &PORTF,
(uint16_t) &PORTG,
(uint16_t) &PORTH,
NOT_A_PORT,
(uint16_t) &PORTJ,
(uint16_t) &PORTK,
(uint16_t) &PORTL,
};
const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PIN,
(uint16_t) &PINA,
(uint16_t) &PINB,
(uint16_t) &PINC,
(uint16_t) &PIND,
(uint16_t) &PINE,
(uint16_t) &PINF,
(uint16_t) &PING,
(uint16_t) &PINH,
NOT_A_PIN,
(uint16_t) &PINJ,
(uint16_t) &PINK,
(uint16_t) &PINL,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
// PORTLIST
// -------------------------------------------
PE , // PE 0 ** 0 ** USART0_RX
PE , // PE 1 ** 1 ** USART0_TX
PE , // PE 4 ** 2 ** PWM2
PE , // PE 5 ** 3 ** PWM3
PG , // PG 5 ** 4 ** PWM4
PE , // PE 3 ** 5 ** PWM5
PH , // PH 3 ** 6 ** PWM6
PH , // PH 4 ** 7 ** PWM7
PH , // PH 5 ** 8 ** PWM8
PH , // PH 6 ** 9 ** PWM9
PB , // PB 4 ** 10 ** PWM10
PB , // PB 5 ** 11 ** PWM11
PB , // PB 6 ** 12 ** PWM12
PB , // PB 7 ** 13 ** PWM13
PJ , // PJ 1 ** 14 ** USART3_TX
PJ , // PJ 0 ** 15 ** USART3_RX
PH , // PH 1 ** 16 ** USART2_TX
PH , // PH 0 ** 17 ** USART2_RX
PD , // PD 3 ** 18 ** USART1_TX
PD , // PD 2 ** 19 ** USART1_RX
PD , // PD 1 ** 20 ** I2C_SDA
PD , // PD 0 ** 21 ** I2C_SCL
PA , // PA 0 ** 22 ** D22
PA , // PA 1 ** 23 ** D23
PA , // PA 2 ** 24 ** D24
PA , // PA 3 ** 25 ** D25
PA , // PA 4 ** 26 ** D26
PA , // PA 5 ** 27 ** D27
PA , // PA 6 ** 28 ** D28
PA , // PA 7 ** 29 ** D29
PC , // PC 7 ** 30 ** D30
PC , // PC 6 ** 31 ** D31
PC , // PC 5 ** 32 ** D32
PC , // PC 4 ** 33 ** D33
PC , // PC 3 ** 34 ** D34
PC , // PC 2 ** 35 ** D35
PC , // PC 1 ** 36 ** D36
PC , // PC 0 ** 37 ** D37
PD , // PD 7 ** 38 ** D38
PG , // PG 2 ** 39 ** D39
PG , // PG 1 ** 40 ** D40
PG , // PG 0 ** 41 ** D41
PL , // PL 7 ** 42 ** D42
PL , // PL 6 ** 43 ** D43
PL , // PL 5 ** 44 ** D44
PL , // PL 4 ** 45 ** D45
PL , // PL 3 ** 46 ** D46
PL , // PL 2 ** 47 ** D47
PL , // PL 1 ** 48 ** D48
PL , // PL 0 ** 49 ** D49
PB , // PB 3 ** 50 ** SPI_MISO
PB , // PB 2 ** 51 ** SPI_MOSI
PB , // PB 1 ** 52 ** SPI_SCK
PB , // PB 0 ** 53 ** SPI_SS
PF , // PF 0 ** 54 ** A0
PF , // PF 1 ** 55 ** A1
PF , // PF 2 ** 56 ** A2
PF , // PF 3 ** 57 ** A3
PF , // PF 4 ** 58 ** A4
PF , // PF 5 ** 59 ** A5
PF , // PF 6 ** 60 ** A6
PF , // PF 7 ** 61 ** A7
PK , // PK 0 ** 62 ** A8
PK , // PK 1 ** 63 ** A9
PK , // PK 2 ** 64 ** A10
PK , // PK 3 ** 65 ** A11
PK , // PK 4 ** 66 ** A12
PK , // PK 5 ** 67 ** A13
PK , // PK 6 ** 68 ** A14
PK , // PK 7 ** 69 ** A15
};
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
// PIN IN PORT
// -------------------------------------------
_BV( 0 ) , // PE 0 ** 0 ** USART0_RX
_BV( 1 ) , // PE 1 ** 1 ** USART0_TX
_BV( 4 ) , // PE 4 ** 2 ** PWM2
_BV( 5 ) , // PE 5 ** 3 ** PWM3
_BV( 5 ) , // PG 5 ** 4 ** PWM4
_BV( 3 ) , // PE 3 ** 5 ** PWM5
_BV( 3 ) , // PH 3 ** 6 ** PWM6
_BV( 4 ) , // PH 4 ** 7 ** PWM7
_BV( 5 ) , // PH 5 ** 8 ** PWM8
_BV( 6 ) , // PH 6 ** 9 ** PWM9
_BV( 4 ) , // PB 4 ** 10 ** PWM10
_BV( 5 ) , // PB 5 ** 11 ** PWM11
_BV( 6 ) , // PB 6 ** 12 ** PWM12
_BV( 7 ) , // PB 7 ** 13 ** PWM13
_BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
_BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
_BV( 1 ) , // PH 1 ** 16 ** USART2_TX
_BV( 0 ) , // PH 0 ** 17 ** USART2_RX
_BV( 3 ) , // PD 3 ** 18 ** USART1_TX
_BV( 2 ) , // PD 2 ** 19 ** USART1_RX
_BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
_BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
_BV( 0 ) , // PA 0 ** 22 ** D22
_BV( 1 ) , // PA 1 ** 23 ** D23
_BV( 2 ) , // PA 2 ** 24 ** D24
_BV( 3 ) , // PA 3 ** 25 ** D25
_BV( 4 ) , // PA 4 ** 26 ** D26
_BV( 5 ) , // PA 5 ** 27 ** D27
_BV( 6 ) , // PA 6 ** 28 ** D28
_BV( 7 ) , // PA 7 ** 29 ** D29
_BV( 7 ) , // PC 7 ** 30 ** D30
_BV( 6 ) , // PC 6 ** 31 ** D31
_BV( 5 ) , // PC 5 ** 32 ** D32
_BV( 4 ) , // PC 4 ** 33 ** D33
_BV( 3 ) , // PC 3 ** 34 ** D34
_BV( 2 ) , // PC 2 ** 35 ** D35
_BV( 1 ) , // PC 1 ** 36 ** D36
_BV( 0 ) , // PC 0 ** 37 ** D37
_BV( 7 ) , // PD 7 ** 38 ** D38
_BV( 2 ) , // PG 2 ** 39 ** D39
_BV( 1 ) , // PG 1 ** 40 ** D40
_BV( 0 ) , // PG 0 ** 41 ** D41
_BV( 7 ) , // PL 7 ** 42 ** D42
_BV( 6 ) , // PL 6 ** 43 ** D43
_BV( 5 ) , // PL 5 ** 44 ** D44
_BV( 4 ) , // PL 4 ** 45 ** D45
_BV( 3 ) , // PL 3 ** 46 ** D46
_BV( 2 ) , // PL 2 ** 47 ** D47
_BV( 1 ) , // PL 1 ** 48 ** D48
_BV( 0 ) , // PL 0 ** 49 ** D49
_BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
_BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
_BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
_BV( 0 ) , // PB 0 ** 53 ** SPI_SS
_BV( 0 ) , // PF 0 ** 54 ** A0
_BV( 1 ) , // PF 1 ** 55 ** A1
_BV( 2 ) , // PF 2 ** 56 ** A2
_BV( 3 ) , // PF 3 ** 57 ** A3
_BV( 4 ) , // PF 4 ** 58 ** A4
_BV( 5 ) , // PF 5 ** 59 ** A5
_BV( 6 ) , // PF 6 ** 60 ** A6
_BV( 7 ) , // PF 7 ** 61 ** A7
_BV( 0 ) , // PK 0 ** 62 ** A8
_BV( 1 ) , // PK 1 ** 63 ** A9
_BV( 2 ) , // PK 2 ** 64 ** A10
_BV( 3 ) , // PK 3 ** 65 ** A11
_BV( 4 ) , // PK 4 ** 66 ** A12
_BV( 5 ) , // PK 5 ** 67 ** A13
_BV( 6 ) , // PK 6 ** 68 ** A14
_BV( 7 ) , // PK 7 ** 69 ** A15
};
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
// TIMERS
// -------------------------------------------
NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
TIMER3B , // PE 4 ** 2 ** PWM2
TIMER3C , // PE 5 ** 3 ** PWM3
TIMER0B , // PG 5 ** 4 ** PWM4
TIMER3A , // PE 3 ** 5 ** PWM5
TIMER4A , // PH 3 ** 6 ** PWM6
TIMER4B , // PH 4 ** 7 ** PWM7
TIMER4C , // PH 5 ** 8 ** PWM8
TIMER2B , // PH 6 ** 9 ** PWM9
TIMER2A , // PB 4 ** 10 ** PWM10
TIMER1A , // PB 5 ** 11 ** PWM11
TIMER1B , // PB 6 ** 12 ** PWM12
TIMER0A , // PB 7 ** 13 ** PWM13
NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
NOT_ON_TIMER , // PA 0 ** 22 ** D22
NOT_ON_TIMER , // PA 1 ** 23 ** D23
NOT_ON_TIMER , // PA 2 ** 24 ** D24
NOT_ON_TIMER , // PA 3 ** 25 ** D25
NOT_ON_TIMER , // PA 4 ** 26 ** D26
NOT_ON_TIMER , // PA 5 ** 27 ** D27
NOT_ON_TIMER , // PA 6 ** 28 ** D28
NOT_ON_TIMER , // PA 7 ** 29 ** D29
NOT_ON_TIMER , // PC 7 ** 30 ** D30
NOT_ON_TIMER , // PC 6 ** 31 ** D31
NOT_ON_TIMER , // PC 5 ** 32 ** D32
NOT_ON_TIMER , // PC 4 ** 33 ** D33
NOT_ON_TIMER , // PC 3 ** 34 ** D34
NOT_ON_TIMER , // PC 2 ** 35 ** D35
NOT_ON_TIMER , // PC 1 ** 36 ** D36
NOT_ON_TIMER , // PC 0 ** 37 ** D37
NOT_ON_TIMER , // PD 7 ** 38 ** D38
NOT_ON_TIMER , // PG 2 ** 39 ** D39
NOT_ON_TIMER , // PG 1 ** 40 ** D40
NOT_ON_TIMER , // PG 0 ** 41 ** D41
NOT_ON_TIMER , // PL 7 ** 42 ** D42
NOT_ON_TIMER , // PL 6 ** 43 ** D43
TIMER5C , // PL 5 ** 44 ** D44
TIMER5B , // PL 4 ** 45 ** D45
TIMER5A , // PL 3 ** 46 ** D46
NOT_ON_TIMER , // PL 2 ** 47 ** D47
NOT_ON_TIMER , // PL 1 ** 48 ** D48
NOT_ON_TIMER , // PL 0 ** 49 ** D49
NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
NOT_ON_TIMER , // PF 0 ** 54 ** A0
NOT_ON_TIMER , // PF 1 ** 55 ** A1
NOT_ON_TIMER , // PF 2 ** 56 ** A2
NOT_ON_TIMER , // PF 3 ** 57 ** A3
NOT_ON_TIMER , // PF 4 ** 58 ** A4
NOT_ON_TIMER , // PF 5 ** 59 ** A5
NOT_ON_TIMER , // PF 6 ** 60 ** A6
NOT_ON_TIMER , // PF 7 ** 61 ** A7
NOT_ON_TIMER , // PK 0 ** 62 ** A8
NOT_ON_TIMER , // PK 1 ** 63 ** A9
NOT_ON_TIMER , // PK 2 ** 64 ** A10
NOT_ON_TIMER , // PK 3 ** 65 ** A11
NOT_ON_TIMER , // PK 4 ** 66 ** A12
NOT_ON_TIMER , // PK 5 ** 67 ** A13
NOT_ON_TIMER , // PK 6 ** 68 ** A14
NOT_ON_TIMER , // PK 7 ** 69 ** A15
};
#endif
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR Serial
#define SERIAL_PORT_HARDWARE Serial
#define SERIAL_PORT_HARDWARE1 Serial1
#define SERIAL_PORT_HARDWARE2 Serial2
#define SERIAL_PORT_HARDWARE3 Serial3
#define SERIAL_PORT_HARDWARE_OPEN Serial1
#define SERIAL_PORT_HARDWARE_OPEN1 Serial2
#define SERIAL_PORT_HARDWARE_OPEN2 Serial3
#endif

@ -0,0 +1,16 @@
/*
* ArduinoCore.cpp
*
* Created: 11.02.2021 15:39:41
* Author : EG
*/
#include <avr/io.h>
/* Replace with your library code */
int myfunc(void)
{
return 0;
}

@ -0,0 +1,302 @@
/* Copyright (c) 2011, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#include "USBAPI.h"
#include <avr/wdt.h>
#include <util/atomic.h>
#if defined(USBCON)
typedef struct
{
u32 dwDTERate;
u8 bCharFormat;
u8 bParityType;
u8 bDataBits;
u8 lineState;
} LineInfo;
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
static volatile int32_t breakValue = -1;
static u8 wdtcsr_save;
#define WEAK __attribute__ ((weak))
extern const CDCDescriptor _cdcInterface PROGMEM;
const CDCDescriptor _cdcInterface =
{
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
// CDC communication interface
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0)
};
bool isLUFAbootloader()
{
return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE;
}
int CDC_GetInterface(u8* interfaceNum)
{
interfaceNum[0] += 2; // uses 2
return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
}
bool CDC_Setup(USBSetup& setup)
{
u8 r = setup.bRequest;
u8 requestType = setup.bmRequestType;
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
{
if (CDC_GET_LINE_CODING == r)
{
USB_SendControl(0,(void*)&_usbLineInfo,7);
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (CDC_SEND_BREAK == r)
{
breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
}
if (CDC_SET_LINE_CODING == r)
{
USB_RecvControl((void*)&_usbLineInfo,7);
}
if (CDC_SET_CONTROL_LINE_STATE == r)
{
_usbLineInfo.lineState = setup.wValueL;
// auto-reset into the bootloader is triggered when the port, already
// open at 1200 bps, is closed. this is the signal to start the watchdog
// with a relatively long period so it can finish housekeeping tasks
// like servicing endpoints before the sketch ends
uint16_t magic_key_pos = MAGIC_KEY_POS;
// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
// This is used to keep compatible with the old leonardo bootloaders.
// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
#if MAGIC_KEY_POS != (RAMEND-1)
// For future boards save the key in the inproblematic RAMEND
// Which is reserved for the main() return value (which will never return)
if (isLUFAbootloader()) {
// horray, we got a new bootloader!
magic_key_pos = (RAMEND-1);
}
#endif
// We check DTR state to determine if host port is open (bit 0 of lineState).
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
{
#if MAGIC_KEY_POS != (RAMEND-1)
// Backup ram value if its not a newer bootloader and it hasn't already been saved.
// This should avoid memory corruption at least a bit, not fully
if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
}
#endif
// Store boot key
*(uint16_t *)magic_key_pos = MAGIC_KEY;
// Save the watchdog state in case the reset is aborted.
wdtcsr_save = WDTCSR;
wdt_enable(WDTO_120MS);
}
else if (*(uint16_t *)magic_key_pos == MAGIC_KEY)
{
// Most OSs do some intermediate steps when configuring ports and DTR can
// twiggle more than once before stabilizing.
// To avoid spurious resets we set the watchdog to 120ms and eventually
// cancel if DTR goes back high.
// Cancellation is only done if an auto-reset was started, which is
// indicated by the magic key having been set.
wdt_reset();
// Restore the watchdog state in case the sketch was using it.
WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = wdtcsr_save;
#if MAGIC_KEY_POS != (RAMEND-1)
// Restore backed up (old bootloader) magic key data
if (magic_key_pos != (RAMEND-1)) {
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
} else
#endif
{
// Clean up RAMEND key
*(uint16_t *)magic_key_pos = 0x0000;
}
}
}
return true;
}
return false;
}
void Serial_::begin(unsigned long /* baud_count */)
{
peek_buffer = -1;
}
void Serial_::begin(unsigned long /* baud_count */, byte /* config */)
{
peek_buffer = -1;
}
void Serial_::end(void)
{
}
int Serial_::available(void)
{
if (peek_buffer >= 0) {
return 1 + USB_Available(CDC_RX);
}
return USB_Available(CDC_RX);
}
int Serial_::peek(void)
{
if (peek_buffer < 0)
peek_buffer = USB_Recv(CDC_RX);
return peek_buffer;
}
int Serial_::read(void)
{
if (peek_buffer >= 0) {
int c = peek_buffer;
peek_buffer = -1;
return c;
}
return USB_Recv(CDC_RX);
}
int Serial_::availableForWrite(void)
{
return USB_SendSpace(CDC_TX);
}
void Serial_::flush(void)
{
USB_Flush(CDC_TX);
}
size_t Serial_::write(uint8_t c)
{
return write(&c, 1);
}
size_t Serial_::write(const uint8_t *buffer, size_t size)
{
/* only try to send bytes if the high-level CDC connection itself
is open (not just the pipe) - the OS should set lineState when the port
is opened and clear lineState when the port is closed.
bytes sent before the user opens the connection or after
the connection is closed are lost - just like with a UART. */
// TODO - ZE - check behavior on different OSes and test what happens if an
// open connection isn't broken cleanly (cable is yanked out, host dies
// or locks up, or host virtual serial port hangs)
if (_usbLineInfo.lineState > 0) {
int r = USB_Send(CDC_TX,buffer,size);
if (r > 0) {
return r;
} else {
setWriteError();
return 0;
}
}
setWriteError();
return 0;
}
// This operator is a convenient way for a sketch to check whether the
// port has actually been configured and opened by the host (as opposed
// to just being connected to the host). It can be used, for example, in
// setup() before printing to ensure that an application on the host is
// actually ready to receive and display the data.
// We add a short delay before returning to fix a bug observed by Federico
// where the port is configured (lineState != 0) but not quite opened.
Serial_::operator bool() {
bool result = false;
if (_usbLineInfo.lineState > 0)
result = true;
delay(10);
return result;
}
unsigned long Serial_::baud() {
// Disable interrupts while reading a multi-byte value
uint32_t baudrate;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
baudrate = _usbLineInfo.dwDTERate;
}
return baudrate;
}
uint8_t Serial_::stopbits() {
return _usbLineInfo.bCharFormat;
}
uint8_t Serial_::paritytype() {
return _usbLineInfo.bParityType;
}
uint8_t Serial_::numbits() {
return _usbLineInfo.bDataBits;
}
bool Serial_::dtr() {
return _usbLineInfo.lineState & 0x1;
}
bool Serial_::rts() {
return _usbLineInfo.lineState & 0x2;
}
int32_t Serial_::readBreak() {
int32_t ret;
// Disable IRQs while reading and clearing breakValue to make
// sure we don't overwrite a value just set by the ISR.
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
ret = breakValue;
breakValue = -1;
}
return ret;
}
Serial_ Serial;
#endif /* if defined(USBCON) */

@ -0,0 +1,281 @@
/*
HardwareSerial.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <util/atomic.h>
#include "Arduino.h"
#include "HardwareSerial.h"
#include "HardwareSerial_private.h"
// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3)
// SerialEvent functions are weak, so when the user doesn't define them,
// the linker just sets their address to 0 (which is checked below).
// The Serialx_available is just a wrapper around Serialx.available(),
// but we can refer to it weakly so we don't pull in the entire
// HardwareSerial instance if the user doesn't also refer to it.
#if defined(HAVE_HWSERIAL0)
void serialEvent() __attribute__((weak));
bool Serial0_available() __attribute__((weak));
#endif
#if defined(HAVE_HWSERIAL1)
void serialEvent1() __attribute__((weak));
bool Serial1_available() __attribute__((weak));
#endif
#if defined(HAVE_HWSERIAL2)
void serialEvent2() __attribute__((weak));
bool Serial2_available() __attribute__((weak));
#endif
#if defined(HAVE_HWSERIAL3)
void serialEvent3() __attribute__((weak));
bool Serial3_available() __attribute__((weak));
#endif
void serialEventRun(void)
{
#if defined(HAVE_HWSERIAL0)
if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
#endif
#if defined(HAVE_HWSERIAL1)
if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1();
#endif
#if defined(HAVE_HWSERIAL2)
if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2();
#endif
#if defined(HAVE_HWSERIAL3)
if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3();
#endif
}
// macro to guard critical sections when needed for large TX buffer sizes
#if (SERIAL_TX_BUFFER_SIZE>256)
#define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#else
#define TX_BUFFER_ATOMIC
#endif
// Actual interrupt handlers //////////////////////////////////////////////////////////////
void HardwareSerial::_tx_udr_empty_irq(void)
{
// If interrupts are enabled, there must be more data in the output
// buffer. Send the next byte
unsigned char c = _tx_buffer[_tx_buffer_tail];
_tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;
*_udr = c;
// clear the TXC bit -- "can be cleared by writing a one to its bit
// location". This makes sure flush() won't return until the bytes
// actually got written. Other r/w bits are preserved, and zeroes
// written to the rest.
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
if (_tx_buffer_head == _tx_buffer_tail) {
// Buffer empty, so disable interrupts
cbi(*_ucsrb, UDRIE0);
}
}
// Public Methods //////////////////////////////////////////////////////////////
void HardwareSerial::begin(unsigned long baud, byte config)
{
// Try u2x mode first
uint16_t baud_setting = (IDIBUS_F_CPU / 4 / baud - 1) / 2;
*_ucsra = 1 << U2X0;
// hardcoded exception for 57600 for compatibility with the bootloader
// shipped with the Duemilanove and previous boards and the firmware
// on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot
// be > 4095, so switch back to non-u2x mode if the baud rate is too
// low.
if (((IDIBUS_F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095))
{
*_ucsra = 0;
baud_setting = (IDIBUS_F_CPU / 8 / baud - 1) / 2;
}
// assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register)
*_ubrrh = baud_setting >> 8;
*_ubrrl = baud_setting;
_written = false;
//set the data bits, parity, and stop bits
#if defined(__AVR_ATmega8__)
config |= 0x80; // select UCSRC register (shared with UBRRH)
#endif
*_ucsrc = config;
sbi(*_ucsrb, RXEN0);
sbi(*_ucsrb, TXEN0);
sbi(*_ucsrb, RXCIE0);
cbi(*_ucsrb, UDRIE0);
}
void HardwareSerial::end()
{
// wait for transmission of outgoing data
flush();
cbi(*_ucsrb, RXEN0);
cbi(*_ucsrb, TXEN0);
cbi(*_ucsrb, RXCIE0);
cbi(*_ucsrb, UDRIE0);
// clear any received data
_rx_buffer_head = _rx_buffer_tail;
}
int HardwareSerial::available(void)
{
return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE;
}
int HardwareSerial::peek(void)
{
if (_rx_buffer_head == _rx_buffer_tail) {
return -1;
} else {
return _rx_buffer[_rx_buffer_tail];
}
}
int HardwareSerial::read(void)
{
// if the head isn't ahead of the tail, we don't have any characters
if (_rx_buffer_head == _rx_buffer_tail) {
return -1;
} else {
unsigned char c = _rx_buffer[_rx_buffer_tail];
_rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE;
return c;
}
}
int HardwareSerial::availableForWrite(void)
{
tx_buffer_index_t head;
tx_buffer_index_t tail;
TX_BUFFER_ATOMIC {
head = _tx_buffer_head;
tail = _tx_buffer_tail;
}
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}
void HardwareSerial::flush()
{
// If we have never written a byte, no need to flush. This special
// case is needed since there is no way to force the TXC (transmit
// complete) bit to 1 during initialization
if (!_written)
return;
while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) {
if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0))
// Interrupts are globally disabled, but the DR empty
// interrupt should be enabled, so poll the DR empty flag to
// prevent deadlock
if (bit_is_set(*_ucsra, UDRE0))
_tx_udr_empty_irq();
}
// If we get here, nothing is queued anymore (DRIE is disabled) and
// the hardware finished tranmission (TXC is set).
}
size_t HardwareSerial::write(uint8_t c)
{
_written = true;
// If the buffer and the data register is empty, just write the byte
// to the data register and be done. This shortcut helps
// significantly improve the effective datarate at high (>
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
// If TXC is cleared before writing UDR and the previous byte
// completes before writing to UDR, TXC will be set but a byte
// is still being transmitted causing flush() to return too soon.
// So writing UDR must happen first.
// Writing UDR and clearing TC must be done atomically, otherwise
// interrupts might delay the TXC clear so the byte written to UDR
// is transmitted (setting TXC) before clearing TXC. Then TXC will
// be cleared when no bytes are left, causing flush() to hang
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
*_udr = c;
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
}
return 1;
}
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
// If the output buffer is full, there's nothing for it other than to
// wait for the interrupt handler to empty it a bit
while (i == _tx_buffer_tail) {
if (bit_is_clear(SREG, SREG_I)) {
// Interrupts are disabled, so we'll have to poll the data
// register empty flag ourselves. If it is set, pretend an
// interrupt has happened and call the handler to free up
// space for us.
if(bit_is_set(*_ucsra, UDRE0))
_tx_udr_empty_irq();
} else {
// nop, the interrupt handler will free up space for us
}
}
_tx_buffer[_tx_buffer_head] = c;
// make atomic to prevent execution of ISR between setting the
// head pointer and setting the interrupt flag resulting in buffer
// retransmission
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
_tx_buffer_head = i;
sbi(*_ucsrb, UDRIE0);
}
return 1;
}
#endif // whole file

@ -0,0 +1,79 @@
/*
HardwareSerial0.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#include "Arduino.h"
#include "HardwareSerial.h"
#include "HardwareSerial_private.h"
// Each HardwareSerial is defined in its own file, since the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.
#if defined(HAVE_HWSERIAL0)
#if defined(USART_RX_vect)
ISR(USART_RX_vect)
#elif defined(USART0_RX_vect)
ISR(USART0_RX_vect)
#elif defined(USART_RXC_vect)
ISR(USART_RXC_vect) // ATmega8
#else
#error "Don't know what the Data Received vector is called for Serial"
#endif
{
Serial._rx_complete_irq();
}
#if defined(UART0_UDRE_vect)
ISR(UART0_UDRE_vect)
#elif defined(UART_UDRE_vect)
ISR(UART_UDRE_vect)
#elif defined(USART0_UDRE_vect)
ISR(USART0_UDRE_vect)
#elif defined(USART_UDRE_vect)
ISR(USART_UDRE_vect)
#else
#error "Don't know what the Data Register Empty vector is called for Serial"
#endif
{
Serial._tx_udr_empty_irq();
}
#if defined(UBRRH) && defined(UBRRL)
HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR);
#else
HardwareSerial Serial(&UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0);
#endif
// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial0_available() {
return Serial.available();
}
#endif // HAVE_HWSERIAL0

@ -0,0 +1,69 @@
/*
HardwareSerial1.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#include "Arduino.h"
#include "HardwareSerial.h"
#include "HardwareSerial_private.h"
// Each HardwareSerial is defined in its own file, since the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.
#if defined(HAVE_HWSERIAL1)
#if defined(UART1_RX_vect)
ISR(UART1_RX_vect)
#elif defined(USART1_RX_vect)
ISR(USART1_RX_vect)
#else
#error "Don't know what the Data Register Empty vector is called for Serial1"
#endif
{
Serial1._rx_complete_irq();
}
#if defined(UART1_UDRE_vect)
ISR(UART1_UDRE_vect)
#elif defined(USART1_UDRE_vect)
ISR(USART1_UDRE_vect)
#else
#error "Don't know what the Data Register Empty vector is called for Serial1"
#endif
{
Serial1._tx_udr_empty_irq();
}
HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1);
// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial1_available() {
return Serial1.available();
}
#endif // HAVE_HWSERIAL1

@ -0,0 +1,57 @@
/*
HardwareSerial2.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#include "Arduino.h"
#include "HardwareSerial.h"
#include "HardwareSerial_private.h"
// Each HardwareSerial is defined in its own file, since the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.
#if defined(HAVE_HWSERIAL2)
ISR(USART2_RX_vect)
{
Serial2._rx_complete_irq();
}
ISR(USART2_UDRE_vect)
{
Serial2._tx_udr_empty_irq();
}
HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2);
// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial2_available() {
return Serial2.available();
}
#endif // HAVE_HWSERIAL2

@ -0,0 +1,57 @@
/*
HardwareSerial3.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
*/
#include "Arduino.h"
#include "HardwareSerial.h"
#include "HardwareSerial_private.h"
// Each HardwareSerial is defined in its own file, since the linker pulls
// in the entire file when any element inside is used. --gc-sections can
// additionally cause unused symbols to be dropped, but ISRs have the
// "used" attribute so are never dropped and they keep the
// HardwareSerial instance in as well. Putting each instance in its own
// file prevents the linker from pulling in any unused instances in the
// first place.
#if defined(HAVE_HWSERIAL3)
ISR(USART3_RX_vect)
{
Serial3._rx_complete_irq();
}
ISR(USART3_UDRE_vect)
{
Serial3._tx_udr_empty_irq();
}
HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3);
// Function that can be weakly referenced by serialEventRun to prevent
// pulling in this file if it's not otherwise used.
bool Serial3_available() {
return Serial3.available();
}
#endif // HAVE_HWSERIAL3

@ -0,0 +1,114 @@
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <IPAddress.h>
IPAddress::IPAddress()
{
_address.dword = 0;
}
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address.bytes[0] = first_octet;
_address.bytes[1] = second_octet;
_address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet;
}
IPAddress::IPAddress(uint32_t address)
{
_address.dword = address;
}
IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
}
bool IPAddress::fromString(const char *address)
{
uint16_t acc = 0; // Accumulator
uint8_t dots = 0;
while (*address)
{
char c = *address++;
if (c >= '0' && c <= '9')
{
acc = acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
}
else if (c == '.')
{
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
_address.bytes[dots++] = acc;
acc = 0;
}
else
{
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
_address.bytes[3] = acc;
return true;
}
IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}
IPAddress& IPAddress::operator=(uint32_t address)
{
_address.dword = address;
return *this;
}
bool IPAddress::operator==(const uint8_t* addr) const
{
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}
size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for (int i =0; i < 3; i++)
{
n += p.print(_address.bytes[i], DEC);
n += p.print('.');
}
n += p.print(_address.bytes[3], DEC);
return n;
}

@ -0,0 +1,115 @@
/*
PluggableUSB.cpp
Copyright (c) 2015 Arduino LLC
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "USBAPI.h"
#include "PluggableUSB.h"
#if defined(USBCON)
#ifdef PLUGGABLE_USB_ENABLED
extern uint8_t _initEndpoints[];
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
{
int sent = 0;
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
int res = node->getInterface(interfaceCount);
if (res < 0)
return -1;
sent += res;
}
return sent;
}
int PluggableUSB_::getDescriptor(USBSetup& setup)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
int ret = node->getDescriptor(setup);
// ret!=0 -> request has been processed
if (ret)
return ret;
}
return 0;
}
void PluggableUSB_::getShortName(char *iSerialNum)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
iSerialNum += node->getShortName(iSerialNum);
}
*iSerialNum = 0;
}
bool PluggableUSB_::setup(USBSetup& setup)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
if (node->setup(setup)) {
return true;
}
}
return false;
}
bool PluggableUSB_::plug(PluggableUSBModule *node)
{
if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) {
return false;
}
if (!rootNode) {
rootNode = node;
} else {
PluggableUSBModule *current = rootNode;
while (current->next) {
current = current->next;
}
current->next = node;
}
node->pluggedInterface = lastIf;
node->pluggedEndpoint = lastEp;
lastIf += node->numInterfaces;
for (uint8_t i = 0; i < node->numEndpoints; i++) {
_initEndpoints[lastEp] = node->endpointType[i];
lastEp++;
}
return true;
// restart USB layer???
}
PluggableUSB_& PluggableUSB()
{
static PluggableUSB_ obj;
return obj;
}
PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT),
lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT),
rootNode(NULL)
{
// Empty
}
#endif
#endif /* if defined(USBCON) */

@ -0,0 +1,178 @@
/*
wiring_pulse.s - pulseInASM() function in different flavours
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2014 Martino Facchin
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
/*
* The following routine was generated by avr-gcc 4.8.3 with the following parameters
* -gstabs -Wa,-ahlmsd=output.lst -dp -fverbose-asm -O2
* on the original C function
*
* unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops)
* {
* unsigned long width = 0;
* // wait for any previous pulse to end
* while ((*port & bit) == stateMask)
* if (--maxloops == 0)
* return 0;
*
* // wait for the pulse to start
* while ((*port & bit) != stateMask)
* if (--maxloops == 0)
* return 0;
*
* // wait for the pulse to stop
* while ((*port & bit) == stateMask) {
* if (++width == maxloops)
* return 0;
* }
* return width;
* }
*
* some compiler outputs were removed but the rest of the code is untouched
*/
#include <avr/io.h>
.section .text
.global countPulseASM
countPulseASM:
.LM0:
.LFBB1:
push r12 ; ; 130 pushqi1/1 [length = 1]
push r13 ; ; 131 pushqi1/1 [length = 1]
push r14 ; ; 132 pushqi1/1 [length = 1]
push r15 ; ; 133 pushqi1/1 [length = 1]
push r16 ; ; 134 pushqi1/1 [length = 1]
push r17 ; ; 135 pushqi1/1 [length = 1]
/* prologue: function */
/* frame size = 0 */
/* stack size = 6 */
.L__stack_usage = 6
mov r30,r24 ; port, port ; 2 *movhi/1 [length = 2]
mov r31,r25 ; port, port
/* unsigned long width = 0;
*** // wait for any previous pulse to end
*** while ((*port & bit) == stateMask)
*/
.LM1:
rjmp .L2 ; ; 181 jump [length = 1]
.L4:
/* if (--maxloops == 0) */
.LM2:
subi r16,1 ; maxloops, ; 17 addsi3/2 [length = 4]
sbc r17, r1 ; maxloops
sbc r18, r1 ; maxloops
sbc r19, r1 ; maxloops
breq .L13 ; , ; 19 branch [length = 1]
.L2:
/* if (--maxloops == 0) */
.LM3:
ld r25,Z ; D.1554, *port_7(D) ; 22 movqi_insn/4 [length = 1]
and r25,r22 ; D.1554, bit ; 24 andqi3/1 [length = 1]
cp r25,r20 ; D.1554, stateMask ; 25 *cmpqi/2 [length = 1]
breq .L4 ; , ; 26 branch [length = 1]
rjmp .L6 ; ; 184 jump [length = 1]
.L7:
/* return 0;
***
*** // wait for the pulse to start
*** while ((*port & bit) != stateMask)
*** if (--maxloops == 0)
*/
.LM4:
subi r16,1 ; maxloops, ; 31 addsi3/2 [length = 4]
sbc r17, r1 ; maxloops
sbc r18, r1 ; maxloops
sbc r19, r1 ; maxloops
breq .L13 ; , ; 33 branch [length = 1]
.L6:
/* if (--maxloops == 0) */
.LM5:
ld r25,Z ; D.1554, *port_7(D) ; 41 movqi_insn/4 [length = 1]
and r25,r22 ; D.1554, bit ; 43 andqi3/1 [length = 1]
cpse r25,r20 ; D.1554, stateMask ; 44 enable_interrupt-3 [length = 1]
rjmp .L7 ;
mov r12, r1 ; width ; 7 *movsi/2 [length = 4]
mov r13, r1 ; width
mov r14, r1 ; width
mov r15, r1 ; width
rjmp .L9 ; ; 186 jump [length = 1]
.L10:
/* return 0;
***
*** // wait for the pulse to stop
*** while ((*port & bit) == stateMask) {
*** if (++width == maxloops)
*/
.LM6:
ldi r24,-1 ; , ; 50 addsi3/3 [length = 5]
sub r12,r24 ; width,
sbc r13,r24 ; width,
sbc r14,r24 ; width,
sbc r15,r24 ; width,
cp r16,r12 ; maxloops, width ; 51 *cmpsi/2 [length = 4]
cpc r17,r13 ; maxloops, width
cpc r18,r14 ; maxloops, width
cpc r19,r15 ; maxloops, width
breq .L13 ; , ; 52 branch [length = 1]
.L9:
/* if (++width == maxloops) */
.LM7:
ld r24,Z ; D.1554, *port_7(D) ; 60 movqi_insn/4 [length = 1]
and r24,r22 ; D.1554, bit ; 62 andqi3/1 [length = 1]
cp r24,r20 ; D.1554, stateMask ; 63 *cmpqi/2 [length = 1]
breq .L10 ; , ; 64 branch [length = 1]
/* return 0;
*** }
*** return width;
*/
.LM8:
mov r22,r12 ; D.1553, width ; 108 movqi_insn/1 [length = 1]
mov r23,r13 ; D.1553, width ; 109 movqi_insn/1 [length = 1]
mov r24,r14 ; D.1553, width ; 110 movqi_insn/1 [length = 1]
mov r25,r15 ; D.1553, width ; 111 movqi_insn/1 [length = 1]
/* epilogue start */
.LM9:
pop r17 ; ; 171 popqi [length = 1]
pop r16 ; ; 172 popqi [length = 1]
pop r15 ; ; 173 popqi [length = 1]
pop r14 ; ; 174 popqi [length = 1]
pop r13 ; ; 175 popqi [length = 1]
pop r12 ; ; 176 popqi [length = 1]
ret ; 177 return_from_epilogue [length = 1]
.L13:
.LM10:
ldi r22,0 ; D.1553 ; 120 movqi_insn/1 [length = 1]
ldi r23,0 ; D.1553 ; 121 movqi_insn/1 [length = 1]
ldi r24,0 ; D.1553 ; 122 movqi_insn/1 [length = 1]
ldi r25,0 ; D.1553 ; 123 movqi_insn/1 [length = 1]
/* epilogue start */
.LM11:
pop r17 ; ; 138 popqi [length = 1]
pop r16 ; ; 139 popqi [length = 1]
pop r15 ; ; 140 popqi [length = 1]
pop r14 ; ; 141 popqi [length = 1]
pop r13 ; ; 142 popqi [length = 1]
pop r12 ; ; 143 popqi [length = 1]
ret ; 144 return_from_epilogue [length = 1]

@ -0,0 +1,266 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
Modified 03 August 2015 by Chuck Todd
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Arduino.h"
#include "Print.h"
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t n = 0;
while (size--) {
if (write(*buffer++)) n++;
else break;
}
return n;
}
size_t Print::print(const __FlashStringHelper *ifsh)
{
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
size_t n = 0;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) break;
if (write(c)) n++;
else break;
}
return n;
}
size_t Print::print(const String &s)
{
return write(s.c_str(), s.length());
}
size_t Print::print(const char str[])
{
return write(str);
}
size_t Print::print(char c)
{
return write(c);
}
size_t Print::print(unsigned char b, int base)
{
return print((unsigned long) b, base);
}
size_t Print::print(int n, int base)
{
return print((long) n, base);
}
size_t Print::print(unsigned int n, int base)
{
return print((unsigned long) n, base);
}
size_t Print::print(long n, int base)
{
if (base == 0) {
return write(n);
} else if (base == 10) {
if (n < 0) {
int t = print('-');
n = -n;
return printNumber(n, 10) + t;
}
return printNumber(n, 10);
} else {
return printNumber(n, base);
}
}
size_t Print::print(unsigned long n, int base)
{
if (base == 0) return write(n);
else return printNumber(n, base);
}
size_t Print::print(double n, int digits)
{
return printFloat(n, digits);
}
size_t Print::println(const __FlashStringHelper *ifsh)
{
size_t n = print(ifsh);
n += println();
return n;
}
size_t Print::print(const Printable& x)
{
return x.printTo(*this);
}
size_t Print::println(void)
{
return write("\r\n");
}
size_t Print::println(const String &s)
{
size_t n = print(s);
n += println();
return n;
}
size_t Print::println(const char c[])
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(char c)
{
size_t n = print(c);
n += println();
return n;
}
size_t Print::println(unsigned char b, int base)
{
size_t n = print(b, base);
n += println();
return n;
}
size_t Print::println(int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned int num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(unsigned long num, int base)
{
size_t n = print(num, base);
n += println();
return n;
}
size_t Print::println(double num, int digits)
{
size_t n = print(num, digits);
n += println();
return n;
}
size_t Print::println(const Printable& x)
{
size_t n = print(x);
n += println();
return n;
}
// Private Methods /////////////////////////////////////////////////////////////
size_t Print::printNumber(unsigned long n, uint8_t base)
{
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
char *str = &buf[sizeof(buf) - 1];
*str = '\0';
// prevent crash if called with base == 1
if (base < 2) base = 10;
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while(n);
return write(str);
}
size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0)
{
n += print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
n += print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
n += print('.');
}
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
unsigned int toPrint = (unsigned int)(remainder);
n += print(toPrint);
remainder -= toPrint;
}
return n;
}

@ -0,0 +1,318 @@
/*
Stream.cpp - adds parsing methods to Stream class
Copyright (c) 2008 David A. Mellis. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Created July 2011
parsing functions based on TextFinder library by Michael Margolis
findMulti/findUntil routines written by Jim Leonard/Xuth
*/
#include "Arduino.h"
#include "Stream.h"
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
// protected method to read stream with timeout
int Stream::timedRead()
{
int c;
_startMillis = millis();
do {
c = read();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// protected method to peek stream with timeout
int Stream::timedPeek()
{
int c;
_startMillis = millis();
do {
c = peek();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}
// returns peek of the next digit in the stream or -1 if timeout
// discards non-numeric characters
int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)
{
int c;
while (1) {
c = timedPeek();
if( c < 0 ||
c == '-' ||
(c >= '0' && c <= '9') ||
(detectDecimal && c == '.')) return c;
switch( lookahead ){
case SKIP_NONE: return -1; // Fail code.
case SKIP_WHITESPACE:
switch( c ){
case ' ':
case '\t':
case '\r':
case '\n': break;
default: return -1; // Fail code.
}
case SKIP_ALL:
break;
}
read(); // discard non-numeric
}
}
// Public Methods
//////////////////////////////////////////////////////////////
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
{
_timeout = timeout;
}
// find returns true if the target string is found
bool Stream::find(char *target)
{
return findUntil(target, strlen(target), NULL, 0);
}
// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
}
// as find but search ends if the terminator string is found
bool Stream::findUntil(char *target, char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
// reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
{
if (terminator == NULL) {
MultiTarget t[1] = {{target, targetLen, 0}};
return findMulti(t, 1) == 0 ? true : false;
} else {
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
return findMulti(t, 2) == 0 ? true : false;
}
}
// returns the first valid (long) integer value from the current position.
// lookahead determines how parseInt looks ahead in the stream.
// See LookaheadMode enumeration at the top of the file.
// Lookahead is terminated by the first character that is not a valid part of an integer.
// Once parsing commences, 'ignore' will be skipped in the stream.
long Stream::parseInt(LookaheadMode lookahead, char ignore)
{
bool isNegative = false;
long value = 0;
int c;
c = peekNextDigit(lookahead, false);
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if(c == ignore)
; // ignore this character
else if(c == '-')
isNegative = true;
else if(c >= '0' && c <= '9') // is c a digit?
value = value * 10 + c - '0';
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || c == ignore );
if(isNegative)
value = -value;
return value;
}
// as parseInt but returns a floating point value
float Stream::parseFloat(LookaheadMode lookahead, char ignore)
{
bool isNegative = false;
bool isFraction = false;
long value = 0;
int c;
float fraction = 1.0;
c = peekNextDigit(lookahead, true);
// ignore non numeric leading characters
if(c < 0)
return 0; // zero returned if timeout
do{
if(c == ignore)
; // ignore
else if(c == '-')
isNegative = true;
else if (c == '.')
isFraction = true;
else if(c >= '0' && c <= '9') { // is c a digit?
value = value * 10 + c - '0';
if(isFraction)
fraction *= 0.1;
}
read(); // consume the character we got with peek
c = timedPeek();
}
while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore );
if(isNegative)
value = -value;
if(isFraction)
return value * fraction;
else
return value;
}
// read characters from stream into buffer
// terminates if length characters have been read, or timeout (see setTimeout)
// returns the number of characters placed in the buffer
// the buffer is NOT null terminated.
//
size_t Stream::readBytes(char *buffer, size_t length)
{
size_t count = 0;
while (count < length) {
int c = timedRead();
if (c < 0) break;
*buffer++ = (char)c;
count++;
}
return count;
}
// as readBytes with terminator character
// terminates if length characters have been read, timeout, or if the terminator character detected
// returns the number of characters placed in the buffer (0 means no valid data found)
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
size_t index = 0;
while (index < length) {
int c = timedRead();
if (c < 0 || c == terminator) break;
*buffer++ = (char)c;
index++;
}
return index; // return number of characters, not including null terminator
}
String Stream::readString()
{
String ret;
int c = timedRead();
while (c >= 0)
{
ret += (char)c;
c = timedRead();
}
return ret;
}
String Stream::readStringUntil(char terminator)
{
String ret;
int c = timedRead();
while (c >= 0 && c != terminator)
{
ret += (char)c;
c = timedRead();
}
return ret;
}
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
// any zero length target string automatically matches and would make
// a mess of the rest of the algorithm.
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
if (t->len <= 0)
return t - targets;
}
while (1) {
int c = timedRead();
if (c < 0)
return -1;
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
// the simple case is if we match, deal with that first.
if (c == t->str[t->index]) {
if (++t->index == t->len)
return t - targets;
else
continue;
}
// if not we need to walk back and see if we could have matched further
// down the stream (ie '1112' doesn't match the first position in '11112'
// but it will match the second position so we can't just reset the current
// index to 0 when we find a mismatch.
if (t->index == 0)
continue;
int origIndex = t->index;
do {
--t->index;
// first check if current char works against the new current index
if (c != t->str[t->index])
continue;
// if it's the only char then we're good, nothing more to check
if (t->index == 0) {
t->index++;
break;
}
// otherwise we need to check the rest of the found string
int diff = origIndex - t->index;
size_t i;
for (i = 0; i < t->index; ++i) {
if (t->str[i] != t->str[i + diff])
break;
}
// if we successfully got through the previous loop then our current
// index is good.
if (i == t->index) {
t->index++;
break;
}
// otherwise we just try the next index
} while (t->index);
}
}
// unreachable
return -1;
}

@ -0,0 +1,619 @@
/* Tone.cpp
A Tone Generator Library
Written by Brett Hagman
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Version Modified By Date Comments
------- ----------- -------- --------
0001 B Hagman 09/08/02 Initial coding
0002 B Hagman 09/08/18 Multiple pins
0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
0004 B Hagman 09/09/26 Fixed problems with ATmega8
0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
09/11/25 Changed pin toggle method to XOR
09/11/25 Fixed timer0 from being excluded
0006 D Mellis 09/12/29 Replaced objects with functions
0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
0009 J Reucker 15/04/10 Issue #292 Fixed problems with ATmega8 (thanks to Pete62)
0010 jipp 15/04/13 added additional define check #2923
*************************************************/
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "Arduino.h"
#include "pins_arduino.h"
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
#define TCCR2A TCCR2
#define TCCR2B TCCR2
#define COM2A1 COM21
#define COM2A0 COM20
#define OCR2A OCR2
#define TIMSK2 TIMSK
#define OCIE2A OCIE2
#define TIMER2_COMPA_vect TIMER2_COMP_vect
#define TIMSK1 TIMSK
#endif
// timerx_toggle_count:
// > 0 - duration specified
// = 0 - stopped
// < 0 - infinitely (until stop() method called, or new play() called)
#if !defined(__AVR_ATmega8__)
volatile long timer0_toggle_count;
volatile uint8_t *timer0_pin_port;
volatile uint8_t timer0_pin_mask;
#endif
volatile long timer1_toggle_count;
volatile uint8_t *timer1_pin_port;
volatile uint8_t timer1_pin_mask;
volatile long timer2_toggle_count;
volatile uint8_t *timer2_pin_port;
volatile uint8_t timer2_pin_mask;
#if defined(TIMSK3)
volatile long timer3_toggle_count;
volatile uint8_t *timer3_pin_port;
volatile uint8_t timer3_pin_mask;
#endif
#if defined(TIMSK4)
volatile long timer4_toggle_count;
volatile uint8_t *timer4_pin_port;
volatile uint8_t timer4_pin_mask;
#endif
#if defined(TIMSK5)
volatile long timer5_toggle_count;
volatile uint8_t *timer5_pin_port;
volatile uint8_t timer5_pin_mask;
#endif
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
#elif defined(__AVR_ATmega8__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#elif defined(__AVR_ATmega32U4__)
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER3
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
#else
#define AVAILABLE_TONE_PINS 1
#define USE_TIMER2
// Leave timer 0 to last.
const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
#endif
static int8_t toneBegin(uint8_t _pin)
{
int8_t _timer = -1;
// if we're already using the pin, the timer should be configured.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
return pgm_read_byte(tone_pin_to_timer_PGM + i);
}
}
// search for an unused timer.
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == 255) {
tone_pins[i] = _pin;
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
break;
}
}
if (_timer != -1)
{
// Set timer specific stuff
// All timers in CTC mode
// 8 bit timers will require changing prescalar values,
// whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
switch (_timer)
{
#if defined(TCCR0A) && defined(TCCR0B) && defined(WGM01)
case 0:
// 8 bit timer
TCCR0A = 0;
TCCR0B = 0;
bitWrite(TCCR0A, WGM01, 1);
bitWrite(TCCR0B, CS00, 1);
timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer0_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
case 1:
// 16 bit timer
TCCR1A = 0;
TCCR1B = 0;
bitWrite(TCCR1B, WGM12, 1);
bitWrite(TCCR1B, CS10, 1);
timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer1_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR2A) && defined(TCCR2B)
case 2:
// 8 bit timer
TCCR2A = 0;
TCCR2B = 0;
bitWrite(TCCR2A, WGM21, 1);
bitWrite(TCCR2B, CS20, 1);
timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer2_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
case 3:
// 16 bit timer
TCCR3A = 0;
TCCR3B = 0;
bitWrite(TCCR3B, WGM32, 1);
bitWrite(TCCR3B, CS30, 1);
timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer3_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
case 4:
// 16 bit timer
TCCR4A = 0;
TCCR4B = 0;
#if defined(WGM42)
bitWrite(TCCR4B, WGM42, 1);
#elif defined(CS43)
// TODO this may not be correct
// atmega32u4
bitWrite(TCCR4B, CS43, 1);
#endif
bitWrite(TCCR4B, CS40, 1);
timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer4_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
#if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
case 5:
// 16 bit timer
TCCR5A = 0;
TCCR5B = 0;
bitWrite(TCCR5B, WGM52, 1);
bitWrite(TCCR5B, CS50, 1);
timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
timer5_pin_mask = digitalPinToBitMask(_pin);
break;
#endif
}
}
return _timer;
}
// frequency (in hertz) and duration (in milliseconds).
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
{
uint8_t prescalarbits = 0b001;
long toggle_count = 0;
uint32_t ocr = 0;
int8_t _timer;
_timer = toneBegin(_pin);
if (_timer >= 0)
{
// Set the pinMode as OUTPUT
pinMode(_pin, OUTPUT);
// if we are using an 8 bit timer, scan through prescalars to find the best fit
if (_timer == 0 || _timer == 2)
{
ocr = IDIBUS_F_CPU / frequency / 2 - 1;
prescalarbits = 0b001; // ck/1: same for both timers
if (ocr > 255)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 8 - 1;
prescalarbits = 0b010; // ck/8: same for both timers
if (_timer == 2 && ocr > 255)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 32 - 1;
prescalarbits = 0b011;
}
if (ocr > 255)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 64 - 1;
prescalarbits = _timer == 0 ? 0b011 : 0b100;
if (_timer == 2 && ocr > 255)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 128 - 1;
prescalarbits = 0b101;
}
if (ocr > 255)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 256 - 1;
prescalarbits = _timer == 0 ? 0b100 : 0b110;
if (ocr > 255)
{
// can't do any better than /1024
ocr = IDIBUS_F_CPU / frequency / 2 / 1024 - 1;
prescalarbits = _timer == 0 ? 0b101 : 0b111;
}
}
}
}
#if defined(TCCR0B)
if (_timer == 0)
{
TCCR0B = (TCCR0B & 0b11111000) | prescalarbits;
}
else
#endif
#if defined(TCCR2B)
{
TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;
}
#else
{
// dummy place holder to make the above ifdefs work
}
#endif
}
else
{
// two choices for the 16 bit timers: ck/1 or ck/64
ocr = IDIBUS_F_CPU / frequency / 2 - 1;
prescalarbits = 0b001;
if (ocr > 0xffff)
{
ocr = IDIBUS_F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011;
}
if (_timer == 1)
{
#if defined(TCCR1B)
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
#endif
}
#if defined(TCCR3B)
else if (_timer == 3)
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR4B)
else if (_timer == 4)
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#endif
#if defined(TCCR5B)
else if (_timer == 5)
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
#endif
}
// Calculate the toggle count
if (duration > 0)
{
toggle_count = 2 * frequency * duration / 1000;
}
else
{
toggle_count = -1;
}
// Set the OCR for the given timer,
// set the toggle count,
// then turn on the interrupts
switch (_timer)
{
#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
case 0:
OCR0A = ocr;
timer0_toggle_count = toggle_count;
bitWrite(TIMSK0, OCIE0A, 1);
break;
#endif
case 1:
#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK1, OCIE1A, 1);
#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
// this combination is for at least the ATmega32
OCR1A = ocr;
timer1_toggle_count = toggle_count;
bitWrite(TIMSK, OCIE1A, 1);
#endif
break;
#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
case 2:
OCR2A = ocr;
timer2_toggle_count = toggle_count;
bitWrite(TIMSK2, OCIE2A, 1);
break;
#endif
#if defined(OCR3A) && defined(TIMSK3) && defined(OCIE3A)
case 3:
OCR3A = ocr;
timer3_toggle_count = toggle_count;
bitWrite(TIMSK3, OCIE3A, 1);
break;
#endif
#if defined(OCR4A) && defined(TIMSK4) && defined(OCIE4A)
case 4:
OCR4A = ocr;
timer4_toggle_count = toggle_count;
bitWrite(TIMSK4, OCIE4A, 1);
break;
#endif
#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
case 5:
OCR5A = ocr;
timer5_toggle_count = toggle_count;
bitWrite(TIMSK5, OCIE5A, 1);
break;
#endif
}
}
}
// XXX: this function only works properly for timer 2 (the only one we use
// currently). for the others, it should end the tone, but won't restore
// proper PWM functionality for the timer.
void disableTimer(uint8_t _timer)
{
switch (_timer)
{
case 0:
#if defined(TIMSK0)
TIMSK0 = 0;
#elif defined(TIMSK)
TIMSK = 0; // atmega32
#endif
break;
#if defined(TIMSK1) && defined(OCIE1A)
case 1:
bitWrite(TIMSK1, OCIE1A, 0);
break;
#endif
case 2:
#if defined(TIMSK2) && defined(OCIE2A)
bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt
#endif
#if defined(TCCR2A) && defined(WGM20)
TCCR2A = (1 << WGM20);
#endif
#if defined(TCCR2B) && defined(CS22)
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
#endif
#if defined(OCR2A)
OCR2A = 0;
#endif
break;
#if defined(TIMSK3) && defined(OCIE3A)
case 3:
bitWrite(TIMSK3, OCIE3A, 0);
break;
#endif
#if defined(TIMSK4) && defined(OCIE4A)
case 4:
bitWrite(TIMSK4, OCIE4A, 0);
break;
#endif
#if defined(TIMSK5) && defined(OCIE5A)
case 5:
bitWrite(TIMSK5, OCIE5A, 0);
break;
#endif
}
}
void noTone(uint8_t _pin)
{
int8_t _timer = -1;
for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
if (tone_pins[i] == _pin) {
_timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
tone_pins[i] = 255;
break;
}
}
disableTimer(_timer);
digitalWrite(_pin, 0);
}
#ifdef USE_TIMER0
ISR(TIMER0_COMPA_vect)
{
if (timer0_toggle_count != 0)
{
// toggle the pin
*timer0_pin_port ^= timer0_pin_mask;
if (timer0_toggle_count > 0)
timer0_toggle_count--;
}
else
{
disableTimer(0);
*timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER1
ISR(TIMER1_COMPA_vect)
{
if (timer1_toggle_count != 0)
{
// toggle the pin
*timer1_pin_port ^= timer1_pin_mask;
if (timer1_toggle_count > 0)
timer1_toggle_count--;
}
else
{
disableTimer(1);
*timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER2
ISR(TIMER2_COMPA_vect)
{
if (timer2_toggle_count != 0)
{
// toggle the pin
*timer2_pin_port ^= timer2_pin_mask;
if (timer2_toggle_count > 0)
timer2_toggle_count--;
}
else
{
// need to call noTone() so that the tone_pins[] entry is reset, so the
// timer gets initialized next time we call tone().
// XXX: this assumes timer 2 is always the first one used.
noTone(tone_pins[0]);
// disableTimer(2);
// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER3
ISR(TIMER3_COMPA_vect)
{
if (timer3_toggle_count != 0)
{
// toggle the pin
*timer3_pin_port ^= timer3_pin_mask;
if (timer3_toggle_count > 0)
timer3_toggle_count--;
}
else
{
disableTimer(3);
*timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER4
ISR(TIMER4_COMPA_vect)
{
if (timer4_toggle_count != 0)
{
// toggle the pin
*timer4_pin_port ^= timer4_pin_mask;
if (timer4_toggle_count > 0)
timer4_toggle_count--;
}
else
{
disableTimer(4);
*timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
}
}
#endif
#ifdef USE_TIMER5
ISR(TIMER5_COMPA_vect)
{
if (timer5_toggle_count != 0)
{
// toggle the pin
*timer5_pin_port ^= timer5_pin_mask;
if (timer5_toggle_count > 0)
timer5_toggle_count--;
}
else
{
disableTimer(5);
*timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
}
}
#endif

@ -0,0 +1,863 @@
/* Copyright (c) 2010, Peter Barrett
** Sleep/Wakeup support added by Michael Dreher
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
#include "USBAPI.h"
#include "PluggableUSB.h"
#include <stdlib.h>
#if defined(USBCON)
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
#define TX_RX_LED_PULSE_MS 100
volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
//==================================================================
//==================================================================
extern const u16 STRING_LANGUAGE[] PROGMEM;
extern const u8 STRING_PRODUCT[] PROGMEM;
extern const u8 STRING_MANUFACTURER[] PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptorIAD PROGMEM;
const u16 STRING_LANGUAGE[2] = {
(3<<8) | (2+2),
0x0409 // English
};
#ifndef USB_PRODUCT
// If no product is provided, use USB IO Board
#define USB_PRODUCT "USB IO Board"
#endif
const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT;
#if USB_VID == 0x2341
# if defined(USB_MANUFACTURER)
# undef USB_MANUFACTURER
# endif
# define USB_MANUFACTURER "Arduino LLC"
#elif USB_VID == 0x1b4f
# if defined(USB_MANUFACTURER)
# undef USB_MANUFACTURER
# endif
# define USB_MANUFACTURER "SparkFun"
#elif !defined(USB_MANUFACTURER)
// Fall through to unknown if no manufacturer name was provided in a macro
# define USB_MANUFACTURER "Unknown"
#endif
const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;
#define DEVICE_CLASS 0x02
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptorIAD =
D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
//==================================================================
//==================================================================
volatile u8 _usbConfiguration = 0;
volatile u8 _usbCurrentStatus = 0; // meaning of bits see usb_20.pdf, Figure 9-4. Information Returned by a GetStatus() Request to a Device
volatile u8 _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits
static inline void WaitIN(void)
{
while (!(UEINTX & (1<<TXINI)))
;
}
static inline void ClearIN(void)
{
UEINTX = ~(1<<TXINI);
}
static inline void WaitOUT(void)
{
while (!(UEINTX & (1<<RXOUTI)))
;
}
static inline u8 WaitForINOrOUT()
{
while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
;
return (UEINTX & (1<<RXOUTI)) == 0;
}
static inline void ClearOUT(void)
{
UEINTX = ~(1<<RXOUTI);
}
static inline void Recv(volatile u8* data, u8 count)
{
while (count--)
*data++ = UEDATX;
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
}
static inline u8 Recv8()
{
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
return UEDATX;
}
static inline void Send8(u8 d)
{
UEDATX = d;
}
static inline void SetEP(u8 ep)
{
UENUM = ep;
}
static inline u8 FifoByteCount()
{
return UEBCLX;
}
static inline u8 ReceivedSetupInt()
{
return UEINTX & (1<<RXSTPI);
}
static inline void ClearSetupInt()
{
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
}
static inline void Stall()
{
UECONX = (1<<STALLRQ) | (1<<EPEN);
}
static inline u8 ReadWriteAllowed()
{
return UEINTX & (1<<RWAL);
}
static inline u8 Stalled()
{
return UEINTX & (1<<STALLEDI);
}
static inline u8 FifoFree()
{
return UEINTX & (1<<FIFOCON);
}
static inline void ReleaseRX()
{
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
}
static inline void ReleaseTX()
{
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
}
static inline u8 FrameNumber()
{
return UDFNUML;
}
//==================================================================
//==================================================================
u8 USBGetConfiguration(void)
{
return _usbConfiguration;
}
#define USB_RECV_TIMEOUT
class LockEP
{
u8 _sreg;
public:
LockEP(u8 ep) : _sreg(SREG)
{
cli();
SetEP(ep & 7);
}
~LockEP()
{
SREG = _sreg;
}
};
// Number of bytes, assumes a rx endpoint
u8 USB_Available(u8 ep)
{
LockEP lock(ep);
return FifoByteCount();
}
// Non Blocking receive
// Return number of bytes read
int USB_Recv(u8 ep, void* d, int len)
{
if (!_usbConfiguration || len < 0)
return -1;
LockEP lock(ep);
u8 n = FifoByteCount();
len = min(n,len);
n = len;
u8* dst = (u8*)d;
while (n--)
*dst++ = Recv8();
if (len && !FifoByteCount()) // release empty buffer
ReleaseRX();
return len;
}
// Recv 1 byte if ready
int USB_Recv(u8 ep)
{
u8 c;
if (USB_Recv(ep,&c,1) != 1)
return -1;
return c;
}
// Space in send EP
u8 USB_SendSpace(u8 ep)
{
LockEP lock(ep);
if (!ReadWriteAllowed())
return 0;
return USB_EP_SIZE - FifoByteCount();
}
// Blocking Send of data to an endpoint
int USB_Send(u8 ep, const void* d, int len)
{
if (!_usbConfiguration)
return -1;
if (_usbSuspendState & (1<<SUSPI)) {
//send a remote wakeup
UDCON |= (1 << RMWKUP);
}
int r = len;
const u8* data = (const u8*)d;
u8 timeout = 250; // 250ms timeout on send? TODO
bool sendZlp = false;
while (len || sendZlp)
{
u8 n = USB_SendSpace(ep);
if (n == 0)
{
if (!(--timeout))
return -1;
delay(1);
continue;
}
if (n > len) {
n = len;
}
{
LockEP lock(ep);
// Frame may have been released by the SOF interrupt handler
if (!ReadWriteAllowed())
continue;
len -= n;
if (ep & TRANSFER_ZERO)
{
while (n--)
Send8(0);
}
else if (ep & TRANSFER_PGM)
{
while (n--)
Send8(pgm_read_byte(data++));
}
else
{
while (n--)
Send8(*data++);
}
if (sendZlp) {
ReleaseTX();
sendZlp = false;
} else if (!ReadWriteAllowed()) { // ...release if buffer is full...
ReleaseTX();
if (len == 0) sendZlp = true;
} else if ((len == 0) && (ep & TRANSFER_RELEASE)) { // ...or if forced with TRANSFER_RELEASE
// XXX: TRANSFER_RELEASE is never used can be removed?
ReleaseTX();
}
}
}
TXLED1; // light the TX LED
TxLEDPulse = TX_RX_LED_PULSE_MS;
return r;
}
u8 _initEndpoints[USB_ENDPOINTS] =
{
0, // Control Endpoint
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
// Following endpoints are automatically initialized to 0
};
#define EP_SINGLE_64 0x32 // EP0
#define EP_DOUBLE_64 0x36 // Other endpoints
#define EP_SINGLE_16 0x12
static
void InitEP(u8 index, u8 type, u8 size)
{
UENUM = index;
UECONX = (1<<EPEN);
UECFG0X = type;
UECFG1X = size;
}
static
void InitEndpoints()
{
for (u8 i = 1; i < sizeof(_initEndpoints) && _initEndpoints[i] != 0; i++)
{
UENUM = i;
UECONX = (1<<EPEN);
UECFG0X = _initEndpoints[i];
#if USB_EP_SIZE == 16
UECFG1X = EP_SINGLE_16;
#elif USB_EP_SIZE == 64
UECFG1X = EP_DOUBLE_64;
#else
#error Unsupported value for USB_EP_SIZE
#endif
}
UERST = 0x7E; // And reset them
UERST = 0;
}
// Handle CLASS_INTERFACE requests
static
bool ClassInterfaceRequest(USBSetup& setup)
{
u8 i = setup.wIndex;
if (CDC_ACM_INTERFACE == i)
return CDC_Setup(setup);
#ifdef PLUGGABLE_USB_ENABLED
return PluggableUSB().setup(setup);
#endif
return false;
}
static int _cmark;
static int _cend;
void InitControl(int end)
{
SetEP(0);
_cmark = 0;
_cend = end;
}
static
bool SendControl(u8 d)
{
if (_cmark < _cend)
{
if (!WaitForINOrOUT())
return false;
Send8(d);
if (!((_cmark + 1) & 0x3F))
ClearIN(); // Fifo is full, release this packet
}
_cmark++;
return true;
}
// Clipped by _cmark/_cend
int USB_SendControl(u8 flags, const void* d, int len)
{
int sent = len;
const u8* data = (const u8*)d;
bool pgm = flags & TRANSFER_PGM;
while (len--)
{
u8 c = pgm ? pgm_read_byte(data++) : *data++;
if (!SendControl(c))
return -1;
}
return sent;
}
// Send a USB descriptor string. The string is stored in PROGMEM as a
// plain ASCII string but is sent out as UTF-16 with the correct 2-byte
// prefix
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) {
SendControl(2 + string_len * 2);
SendControl(3);
bool pgm = flags & TRANSFER_PGM;
for(u8 i = 0; i < string_len; i++) {
bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);
r &= SendControl(0); // high byte
if(!r) {
return false;
}
}
return true;
}
// Does not timeout or cross fifo boundaries
int USB_RecvControl(void* d, int len)
{
auto length = len;
while(length)
{
// Dont receive more than the USB Control EP has to offer
// Use fixed 64 because control EP always have 64 bytes even on 16u2.
auto recvLength = length;
if(recvLength > 64){
recvLength = 64;
}
// Write data to fit to the end (not the beginning) of the array
WaitOUT();
Recv((u8*)d + len - length, recvLength);
ClearOUT();
length -= recvLength;
}
return len;
}
static u8 SendInterfaces()
{
u8 interfaces = 0;
CDC_GetInterface(&interfaces);
#ifdef PLUGGABLE_USB_ENABLED
PluggableUSB().getInterface(&interfaces);
#endif
return interfaces;
}
// Construct a dynamic configuration descriptor
// This really needs dynamic endpoint allocation etc
// TODO
static
bool SendConfiguration(int maxlen)
{
// Count and measure interfaces
InitControl(0);
u8 interfaces = SendInterfaces();
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
// Now send them
InitControl(maxlen);
USB_SendControl(0,&config,sizeof(ConfigDescriptor));
SendInterfaces();
return true;
}
static
bool SendDescriptor(USBSetup& setup)
{
u8 t = setup.wValueH;
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
return SendConfiguration(setup.wLength);
InitControl(setup.wLength);
#ifdef PLUGGABLE_USB_ENABLED
int ret = PluggableUSB().getDescriptor(setup);
if (ret != 0) {
return (ret > 0 ? true : false);
}
#endif
const u8* desc_addr = 0;
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
{
desc_addr = (const u8*)&USB_DeviceDescriptorIAD;
}
else if (USB_STRING_DESCRIPTOR_TYPE == t)
{
if (setup.wValueL == 0) {
desc_addr = (const u8*)&STRING_LANGUAGE;
}
else if (setup.wValueL == IPRODUCT) {
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);
}
else if (setup.wValueL == IMANUFACTURER) {
return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM);
}
else if (setup.wValueL == ISERIAL) {
#ifdef PLUGGABLE_USB_ENABLED
char name[ISERIAL_MAX_LEN];
PluggableUSB().getShortName(name);
return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
#endif
}
else
return false;
}
if (desc_addr == 0)
return false;
u8 desc_length = pgm_read_byte(desc_addr);
USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);
return true;
}
// Endpoint 0 interrupt
ISR(USB_COM_vect)
{
SetEP(0);
if (!ReceivedSetupInt())
return;
USBSetup setup;
Recv((u8*)&setup,8);
ClearSetupInt();
u8 requestType = setup.bmRequestType;
if (requestType & REQUEST_DEVICETOHOST)
WaitIN();
else
ClearIN();
bool ok = true;
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
{
// Standard Requests
u8 r = setup.bRequest;
u16 wValue = setup.wValueL | (setup.wValueH << 8);
if (GET_STATUS == r)
{
if (requestType == (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_DEVICE))
{
Send8(_usbCurrentStatus);
Send8(0);
}
else
{
// TODO: handle the HALT state of an endpoint here
// see "Figure 9-6. Information Returned by a GetStatus() Request to an Endpoint" in usb_20.pdf for more information
Send8(0);
Send8(0);
}
}
else if (CLEAR_FEATURE == r)
{
if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE))
&& (wValue == DEVICE_REMOTE_WAKEUP))
{
_usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED;
}
}
else if (SET_FEATURE == r)
{
if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE))
&& (wValue == DEVICE_REMOTE_WAKEUP))
{
_usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
}
}
else if (SET_ADDRESS == r)
{
WaitIN();
UDADDR = setup.wValueL | (1<<ADDEN);
}
else if (GET_DESCRIPTOR == r)
{
ok = SendDescriptor(setup);
}
else if (SET_DESCRIPTOR == r)
{
ok = false;
}
else if (GET_CONFIGURATION == r)
{
Send8(1);
}
else if (SET_CONFIGURATION == r)
{
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
{
InitEndpoints();
_usbConfiguration = setup.wValueL;
} else
ok = false;
}
else if (GET_INTERFACE == r)
{
}
else if (SET_INTERFACE == r)
{
}
}
else
{
InitControl(setup.wLength); // Max length of transfer
ok = ClassInterfaceRequest(setup);
}
if (ok)
ClearIN();
else
{
Stall();
}
}
void USB_Flush(u8 ep)
{
SetEP(ep);
if (FifoByteCount())
ReleaseTX();
}
static inline void USB_ClockDisable()
{
#if defined(OTGPADE)
USBCON = (USBCON & ~(1<<OTGPADE)) | (1<<FRZCLK); // freeze clock and disable VBUS Pad
#else // u2 Series
USBCON = (1 << FRZCLK); // freeze clock
#endif
PLLCSR &= ~(1<<PLLE); // stop PLL
}
static inline void USB_ClockEnable()
{
#if defined(UHWCON)
UHWCON |= (1<<UVREGE); // power internal reg
#endif
USBCON = (1<<USBE) | (1<<FRZCLK); // clock frozen, usb enabled
// ATmega32U4
#if defined(PINDIV)
#if IDIBUS_F_CPU == 16000000UL
PLLCSR |= (1<<PINDIV); // Need 16 MHz xtal
#elif IDIBUS_F_CPU == 8000000UL
PLLCSR &= ~(1<<PINDIV); // Need 8 MHz xtal
#else
#error "Clock rate of IDIBUS_F_CPU not supported"
#endif
#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
// for the u2 Series the datasheet is confusing. On page 40 its called PINDIV and on page 290 its called PLLP0
#if IDIBUS_F_CPU == 16000000UL
// Need 16 MHz xtal
PLLCSR |= (1 << PLLP0);
#elif IDIBUS_F_CPU == 8000000UL
// Need 8 MHz xtal
PLLCSR &= ~(1 << PLLP0);
#endif
// AT90USB646, AT90USB647, AT90USB1286, AT90USB1287
#elif defined(PLLP2)
#if IDIBUS_F_CPU == 16000000UL
#if defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
// For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x.
PLLCSR = (PLLCSR & ~(1<<PLLP1)) | ((1<<PLLP2) | (1<<PLLP0)); // Need 16 MHz xtal
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
// For AT90USB64x only. Do not use with AT90USB128x.
PLLCSR = (PLLCSR & ~(1<<PLLP0)) | ((1<<PLLP2) | (1<<PLLP1)); // Need 16 MHz xtal
#else
#error "USB Chip not supported, please defined method of USB PLL initialization"
#endif
#elif IDIBUS_F_CPU == 8000000UL
// for Atmel AT90USB128x and AT90USB64x
PLLCSR = (PLLCSR & ~(1<<PLLP2)) | ((1<<PLLP1) | (1<<PLLP0)); // Need 8 MHz xtal
#else
#error "Clock rate of IDIBUS_F_CPU not supported"
#endif
#else
#error "USB Chip not supported, please defined method of USB PLL initialization"
#endif
PLLCSR |= (1<<PLLE);
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
{
}
// Some tests on specific versions of macosx (10.7.3), reported some
// strange behaviors when the board is reset using the serial
// port touch at 1200 bps. This delay fixes this behavior.
delay(1);
#if defined(OTGPADE)
USBCON = (USBCON & ~(1<<FRZCLK)) | (1<<OTGPADE); // start USB clock, enable VBUS Pad
#else
USBCON &= ~(1 << FRZCLK); // start USB clock
#endif
#if defined(RSTCPU)
#if defined(LSM)
UDCON &= ~((1<<RSTCPU) | (1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode
#else // u2 Series
UDCON &= ~((1 << RSTCPU) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode
#endif
#else
// AT90USB64x and AT90USB128x don't have RSTCPU
UDCON &= ~((1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode
#endif
}
// General interrupt
ISR(USB_GEN_vect)
{
u8 udint = UDINT;
UDINT &= ~((1<<EORSTI) | (1<<SOFI)); // clear the IRQ flags for the IRQs which are handled here, except WAKEUPI and SUSPI (see below)
// End of Reset
if (udint & (1<<EORSTI))
{
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
_usbConfiguration = 0; // not configured yet
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
}
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if (udint & (1<<SOFI))
{
USB_Flush(CDC_TX); // Send a tx frame if found
// check whether the one-shot period has elapsed. if so, turn off the LED
if (TxLEDPulse && !(--TxLEDPulse))
TXLED0;
if (RxLEDPulse && !(--RxLEDPulse))
RXLED0;
}
// the WAKEUPI interrupt is triggered as soon as there are non-idle patterns on the data
// lines. Thus, the WAKEUPI interrupt can occur even if the controller is not in the "suspend" mode.
// Therefore the we enable it only when USB is suspended
if (udint & (1<<WAKEUPI))
{
UDIEN = (UDIEN & ~(1<<WAKEUPE)) | (1<<SUSPE); // Disable interrupts for WAKEUP and enable interrupts for SUSPEND
//TODO
// WAKEUPI shall be cleared by software (USB clock inputs must be enabled before).
//USB_ClockEnable();
UDINT &= ~(1<<WAKEUPI);
_usbSuspendState = (_usbSuspendState & ~(1<<SUSPI)) | (1<<WAKEUPI);
}
else if (udint & (1<<SUSPI)) // only one of the WAKEUPI / SUSPI bits can be active at time
{
UDIEN = (UDIEN & ~(1<<SUSPE)) | (1<<WAKEUPE); // Disable interrupts for SUSPEND and enable interrupts for WAKEUP
//TODO
//USB_ClockDisable();
UDINT &= ~((1<<WAKEUPI) | (1<<SUSPI)); // clear any already pending WAKEUP IRQs and the SUSPI request
_usbSuspendState = (_usbSuspendState & ~(1<<WAKEUPI)) | (1<<SUSPI);
}
}
// VBUS or counting frames
// Any frame counting?
u8 USBConnected()
{
u8 f = UDFNUML;
delay(3);
return f != UDFNUML;
}
//=======================================================================
//=======================================================================
USBDevice_ USBDevice;
USBDevice_::USBDevice_()
{
}
void USBDevice_::attach()
{
_usbConfiguration = 0;
_usbCurrentStatus = 0;
_usbSuspendState = 0;
USB_ClockEnable();
UDINT &= ~((1<<WAKEUPI) | (1<<SUSPI)); // clear already pending WAKEUP / SUSPEND requests
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
TX_RX_LED_INIT;
}
void USBDevice_::detach()
{
}
// Check for interrupts
// TODO: VBUS detection
bool USBDevice_::configured()
{
return _usbConfiguration;
}
void USBDevice_::poll()
{
}
bool USBDevice_::wakeupHost()
{
// clear any previous wakeup request which might have been set but could be processed at that time
// e.g. because the host was not suspended at that time
UDCON &= ~(1 << RMWKUP);
if(!(UDCON & (1 << RMWKUP))
&& (_usbSuspendState & (1<<SUSPI))
&& (_usbCurrentStatus & FEATURE_REMOTE_WAKEUP_ENABLED))
{
// This short version will only work, when the device has not been suspended. Currently the
// Arduino core doesn't handle SUSPEND at all, so this is ok.
USB_ClockEnable();
UDCON |= (1 << RMWKUP); // send the wakeup request
return true;
}
return false;
}
bool USBDevice_::isSuspended()
{
return (_usbSuspendState & (1 << SUSPI));
}
#endif /* if defined(USBCON) */

@ -0,0 +1,379 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.uniandes.edu.co
Copyright (c) 2004-05 Hernando Barragan
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
Modified 24 November 2006 by David A. Mellis
Modified 1 August 2010 by Mark Sproul
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "wiring_private.h"
static void nothing(void) {
}
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
#if EXTERNAL_NUM_INTERRUPTS > 8
#warning There are more than 8 external interrupts. Some callbacks may not be initialized.
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 7
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 6
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 5
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 4
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 3
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 2
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 1
nothing,
#endif
#if EXTERNAL_NUM_INTERRUPTS > 0
nothing,
#endif
};
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc;
// Configure the interrupt mode (trigger on low input, any change, rising
// edge, or falling edge). The mode constants were chosen to correspond
// to the configuration bits in the hardware register, so we simply shift
// the mode into place.
// Enable the interrupt.
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
// I hate doing this, but the register assignment differs between the 1280/2560
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// even present on the 32U4 this is the only way to distinguish between them.
case 0:
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
EIMSK |= (1<<INT0);
break;
case 1:
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
EIMSK |= (1<<INT1);
break;
case 2:
EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
EIMSK |= (1<<INT2);
break;
case 3:
EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
EIMSK |= (1<<INT3);
break;
case 4:
EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
EIMSK |= (1<<INT6);
break;
#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
case 0:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 1:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 2:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
break;
case 4:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
break;
case 5:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 4:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
break;
case 5:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
break;
case 0:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
break;
case 1:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
#else
case 0:
#if defined(EICRA) && defined(ISC00) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GICR |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GIMSK |= (1 << INT0);
#else
#error attachInterrupt not finished for this CPU (case 0)
#endif
break;
case 1:
#if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GICR |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GIMSK |= (1 << INT1);
#else
#warning attachInterrupt may need some more work for this cpu (case 1)
#endif
break;
case 2:
#if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GICR |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GIMSK |= (1 << INT2);
#endif
break;
#endif
}
}
}
void detachInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
// Disable the interrupt. (We can't assume that interruptNum is equal
// to the number of the EIMSK bit to clear, as this isn't true on the
// ATmega8. There, INT0 is 6 and INT1 is 7.)
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
case 0:
EIMSK &= ~(1<<INT0);
break;
case 1:
EIMSK &= ~(1<<INT1);
break;
case 2:
EIMSK &= ~(1<<INT2);
break;
case 3:
EIMSK &= ~(1<<INT3);
break;
case 4:
EIMSK &= ~(1<<INT6);
break;
#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
case 0:
EIMSK &= ~(1 << INT0);
break;
case 1:
EIMSK &= ~(1 << INT1);
break;
case 2:
EIMSK &= ~(1 << INT2);
break;
case 3:
EIMSK &= ~(1 << INT3);
break;
case 4:
EIMSK &= ~(1 << INT4);
break;
case 5:
EIMSK &= ~(1 << INT5);
break;
case 6:
EIMSK &= ~(1 << INT6);
break;
case 7:
EIMSK &= ~(1 << INT7);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK &= ~(1 << INT0);
break;
case 3:
EIMSK &= ~(1 << INT1);
break;
case 4:
EIMSK &= ~(1 << INT2);
break;
case 5:
EIMSK &= ~(1 << INT3);
break;
case 0:
EIMSK &= ~(1 << INT4);
break;
case 1:
EIMSK &= ~(1 << INT5);
break;
case 6:
EIMSK &= ~(1 << INT6);
break;
case 7:
EIMSK &= ~(1 << INT7);
break;
#else
case 0:
#if defined(EIMSK) && defined(INT0)
EIMSK &= ~(1 << INT0);
#elif defined(GICR) && defined(ISC00)
GICR &= ~(1 << INT0); // atmega32
#elif defined(GIMSK) && defined(INT0)
GIMSK &= ~(1 << INT0);
#else
#error detachInterrupt not finished for this cpu
#endif
break;
case 1:
#if defined(EIMSK) && defined(INT1)
EIMSK &= ~(1 << INT1);
#elif defined(GICR) && defined(INT1)
GICR &= ~(1 << INT1); // atmega32
#elif defined(GIMSK) && defined(INT1)
GIMSK &= ~(1 << INT1);
#else
#warning detachInterrupt may need some more work for this cpu (case 1)
#endif
break;
case 2:
#if defined(EIMSK) && defined(INT2)
EIMSK &= ~(1 << INT2);
#elif defined(GICR) && defined(INT2)
GICR &= ~(1 << INT2); // atmega32
#elif defined(GIMSK) && defined(INT2)
GIMSK &= ~(1 << INT2);
#elif defined(INT2)
#warning detachInterrupt may need some more work for this cpu (case 2)
#endif
break;
#endif
}
intFunc[interruptNum] = nothing;
}
}
#define IMPLEMENT_ISR(vect, interrupt) \
ISR(vect) { \
intFunc[interrupt](); \
}
#if defined(__AVR_ATmega32U4__)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_4)
#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_4)
IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_5)
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
#elif defined(EICRA) && defined(EICRB)
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_2)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_3)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_4)
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_5)
IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_1)
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
#else
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
#if defined(EICRA) && defined(ISC20)
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
#endif
#endif

@ -0,0 +1,58 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
extern "C" {
#include "stdlib.h"
}
void randomSeed(unsigned long seed)
{
if (seed != 0) {
srandom(seed);
}
}
long random(long howbig)
{
if (howbig == 0) {
return 0;
}
return random() % howbig;
}
long random(long howsmall, long howbig)
{
if (howsmall >= howbig) {
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
unsigned int makeWord(unsigned int w) { return w; }
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

@ -0,0 +1,750 @@
/*
WString.cpp - String library for Wiring & Arduino
...mostly rewritten by Paul Stoffregen...
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
Copyright 2011, Paul Stoffregen, paul@pjrc.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "WString.h"
/*********************************************/
/* Constructors */
/*********************************************/
String::String(const char *cstr)
{
init();
if (cstr) copy(cstr, strlen(cstr));
}
String::String(const String &value)
{
init();
*this = value;
}
String::String(const __FlashStringHelper *pstr)
{
init();
*this = pstr;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String::String(String &&rval)
{
init();
move(rval);
}
String::String(StringSumHelper &&rval)
{
init();
move(rval);
}
#endif
String::String(char c)
{
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
String::String(unsigned char value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned char)];
utoa(value, buf, base);
*this = buf;
}
String::String(int value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(int)];
itoa(value, buf, base);
*this = buf;
}
String::String(unsigned int value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned int)];
utoa(value, buf, base);
*this = buf;
}
String::String(long value, unsigned char base)
{
init();
char buf[2 + 8 * sizeof(long)];
ltoa(value, buf, base);
*this = buf;
}
String::String(unsigned long value, unsigned char base)
{
init();
char buf[1 + 8 * sizeof(unsigned long)];
ultoa(value, buf, base);
*this = buf;
}
String::String(float value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::String(double value, unsigned char decimalPlaces)
{
init();
char buf[33];
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
}
String::~String()
{
if (buffer) free(buffer);
}
/*********************************************/
/* Memory Management */
/*********************************************/
inline void String::init(void)
{
buffer = NULL;
capacity = 0;
len = 0;
}
void String::invalidate(void)
{
if (buffer) free(buffer);
buffer = NULL;
capacity = len = 0;
}
unsigned char String::reserve(unsigned int size)
{
if (buffer && capacity >= size) return 1;
if (changeBuffer(size)) {
if (len == 0) buffer[0] = 0;
return 1;
}
return 0;
}
unsigned char String::changeBuffer(unsigned int maxStrLen)
{
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
if (newbuffer) {
buffer = newbuffer;
capacity = maxStrLen;
return 1;
}
return 0;
}
/*********************************************/
/* Copy and Move */
/*********************************************/
String & String::copy(const char *cstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy(buffer, cstr);
return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
{
if (!reserve(length)) {
invalidate();
return *this;
}
len = length;
strcpy_P(buffer, (PGM_P)pstr);
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
void String::move(String &rhs)
{
if (buffer) {
if (rhs && capacity >= rhs.len) {
strcpy(buffer, rhs.buffer);
len = rhs.len;
rhs.len = 0;
return;
} else {
free(buffer);
}
}
buffer = rhs.buffer;
capacity = rhs.capacity;
len = rhs.len;
rhs.buffer = NULL;
rhs.capacity = 0;
rhs.len = 0;
}
#endif
String & String::operator = (const String &rhs)
{
if (this == &rhs) return *this;
if (rhs.buffer) copy(rhs.buffer, rhs.len);
else invalidate();
return *this;
}
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & String::operator = (String &&rval)
{
if (this != &rval) move(rval);
return *this;
}
String & String::operator = (StringSumHelper &&rval)
{
if (this != &rval) move(rval);
return *this;
}
#endif
String & String::operator = (const char *cstr)
{
if (cstr) copy(cstr, strlen(cstr));
else invalidate();
return *this;
}
String & String::operator = (const __FlashStringHelper *pstr)
{
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
else invalidate();
return *this;
}
/*********************************************/
/* concat */
/*********************************************/
unsigned char String::concat(const String &s)
{
return concat(s.buffer, s.len);
}
unsigned char String::concat(const char *cstr, unsigned int length)
{
unsigned int newlen = len + length;
if (!cstr) return 0;
if (length == 0) return 1;
if (!reserve(newlen)) return 0;
strcpy(buffer + len, cstr);
len = newlen;
return 1;
}
unsigned char String::concat(const char *cstr)
{
if (!cstr) return 0;
return concat(cstr, strlen(cstr));
}
unsigned char String::concat(char c)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
return concat(buf, 1);
}
unsigned char String::concat(unsigned char num)
{
char buf[1 + 3 * sizeof(unsigned char)];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(int num)
{
char buf[2 + 3 * sizeof(int)];
itoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned int num)
{
char buf[1 + 3 * sizeof(unsigned int)];
utoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(long num)
{
char buf[2 + 3 * sizeof(long)];
ltoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(unsigned long num)
{
char buf[1 + 3 * sizeof(unsigned long)];
ultoa(num, buf, 10);
return concat(buf, strlen(buf));
}
unsigned char String::concat(float num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(double num)
{
char buf[20];
char* string = dtostrf(num, 4, 2, buf);
return concat(string, strlen(string));
}
unsigned char String::concat(const __FlashStringHelper * str)
{
if (!str) return 0;
int length = strlen_P((const char *) str);
if (length == 0) return 1;
unsigned int newlen = len + length;
if (!reserve(newlen)) return 0;
strcpy_P(buffer + len, (const char *) str);
len = newlen;
return 1;
}
/*********************************************/
/* Concatenate */
/*********************************************/
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(c)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(num)) a.invalidate();
return a;
}
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
{
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
if (!a.concat(rhs)) a.invalidate();
return a;
}
/*********************************************/
/* Comparison */
/*********************************************/
int String::compareTo(const String &s) const
{
if (!buffer || !s.buffer) {
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
if (buffer && len > 0) return *(unsigned char *)buffer;
return 0;
}
return strcmp(buffer, s.buffer);
}
unsigned char String::equals(const String &s2) const
{
return (len == s2.len && compareTo(s2) == 0);
}
unsigned char String::equals(const char *cstr) const
{
if (len == 0) return (cstr == NULL || *cstr == 0);
if (cstr == NULL) return buffer[0] == 0;
return strcmp(buffer, cstr) == 0;
}
unsigned char String::operator<(const String &rhs) const
{
return compareTo(rhs) < 0;
}
unsigned char String::operator>(const String &rhs) const
{
return compareTo(rhs) > 0;
}
unsigned char String::operator<=(const String &rhs) const
{
return compareTo(rhs) <= 0;
}
unsigned char String::operator>=(const String &rhs) const
{
return compareTo(rhs) >= 0;
}
unsigned char String::equalsIgnoreCase( const String &s2 ) const
{
if (this == &s2) return 1;
if (len != s2.len) return 0;
if (len == 0) return 1;
const char *p1 = buffer;
const char *p2 = s2.buffer;
while (*p1) {
if (tolower(*p1++) != tolower(*p2++)) return 0;
}
return 1;
}
unsigned char String::startsWith( const String &s2 ) const
{
if (len < s2.len) return 0;
return startsWith(s2, 0);
}
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
{
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
}
unsigned char String::endsWith( const String &s2 ) const
{
if ( len < s2.len || !buffer || !s2.buffer) return 0;
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
}
/*********************************************/
/* Character Access */
/*********************************************/
char String::charAt(unsigned int loc) const
{
return operator[](loc);
}
void String::setCharAt(unsigned int loc, char c)
{
if (loc < len) buffer[loc] = c;
}
char & String::operator[](unsigned int index)
{
static char dummy_writable_char;
if (index >= len || !buffer) {
dummy_writable_char = 0;
return dummy_writable_char;
}
return buffer[index];
}
char String::operator[]( unsigned int index ) const
{
if (index >= len || !buffer) return 0;
return buffer[index];
}
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
{
if (!bufsize || !buf) return;
if (index >= len) {
buf[0] = 0;
return;
}
unsigned int n = bufsize - 1;
if (n > len - index) n = len - index;
strncpy((char *)buf, buffer + index, n);
buf[n] = 0;
}
/*********************************************/
/* Search */
/*********************************************/
int String::indexOf(char c) const
{
return indexOf(c, 0);
}
int String::indexOf( char ch, unsigned int fromIndex ) const
{
if (fromIndex >= len) return -1;
const char* temp = strchr(buffer + fromIndex, ch);
if (temp == NULL) return -1;
return temp - buffer;
}
int String::indexOf(const String &s2) const
{
return indexOf(s2, 0);
}
int String::indexOf(const String &s2, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
const char *found = strstr(buffer + fromIndex, s2.buffer);
if (found == NULL) return -1;
return found - buffer;
}
int String::lastIndexOf( char theChar ) const
{
return lastIndexOf(theChar, len - 1);
}
int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
buffer[fromIndex + 1] = tempchar;
if (temp == NULL) return -1;
return temp - buffer;
}
int String::lastIndexOf(const String &s2) const
{
return lastIndexOf(s2, len - s2.len);
}
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1;
int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) {
p = strstr(p, s2.buffer);
if (!p) break;
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
}
return found;
}
String String::substring(unsigned int left, unsigned int right) const
{
if (left > right) {
unsigned int temp = right;
right = left;
left = temp;
}
String out;
if (left >= len) return out;
if (right > len) right = len;
char temp = buffer[right]; // save the replaced character
buffer[right] = '\0';
out = buffer + left; // pointer arithmetic
buffer[right] = temp; //restore character
return out;
}
/*********************************************/
/* Modification */
/*********************************************/
void String::replace(char find, char replace)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
if (*p == find) *p = replace;
}
}
void String::replace(const String& find, const String& replace)
{
if (len == 0 || find.len == 0) return;
int diff = replace.len - find.len;
char *readFrom = buffer;
char *foundAt;
if (diff == 0) {
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
memcpy(foundAt, replace.buffer, replace.len);
readFrom = foundAt + replace.len;
}
} else if (diff < 0) {
char *writeTo = buffer;
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
unsigned int n = foundAt - readFrom;
memcpy(writeTo, readFrom, n);
writeTo += n;
memcpy(writeTo, replace.buffer, replace.len);
writeTo += replace.len;
readFrom = foundAt + find.len;
len += diff;
}
strcpy(writeTo, readFrom);
} else {
unsigned int size = len; // compute size needed for result
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
readFrom = foundAt + find.len;
size += diff;
}
if (size == len) return;
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
int index = len - 1;
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
readFrom = buffer + index + find.len;
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
len += diff;
buffer[len] = 0;
memcpy(buffer + index, replace.buffer, replace.len);
index--;
}
}
}
void String::remove(unsigned int index){
// Pass the biggest integer as the count. The remove method
// below will take care of truncating it at the end of the
// string.
remove(index, (unsigned int)-1);
}
void String::remove(unsigned int index, unsigned int count){
if (index >= len) { return; }
if (count <= 0) { return; }
if (count > len - index) { count = len - index; }
char *writeTo = buffer + index;
len = len - count;
strncpy(writeTo, buffer + index + count,len - index);
buffer[len] = 0;
}
void String::toLowerCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = tolower(*p);
}
}
void String::toUpperCase(void)
{
if (!buffer) return;
for (char *p = buffer; *p; p++) {
*p = toupper(*p);
}
}
void String::trim(void)
{
if (!buffer || len == 0) return;
char *begin = buffer;
while (isspace(*begin)) begin++;
char *end = buffer + len - 1;
while (isspace(*end) && end >= begin) end--;
len = end + 1 - begin;
if (begin > buffer) memcpy(buffer, begin, len);
buffer[len] = 0;
}
/*********************************************/
/* Parsing / Conversion */
/*********************************************/
long String::toInt(void) const
{
if (buffer) return atol(buffer);
return 0;
}
float String::toFloat(void) const
{
return float(toDouble());
}
double String::toDouble(void) const
{
if (buffer) return atof(buffer);
return 0;
}

@ -0,0 +1,35 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
void __cxa_pure_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
}
void __cxa_deleted_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
}

@ -0,0 +1,31 @@
/*
Copyright (c) 2012 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));

@ -0,0 +1,52 @@
/*
main.cpp - Main loop for Arduino sketches
Copyright (c) 2005-2013 Arduino Team. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
// Declared weak in Arduino.h to allow user redefinitions.
int atexit(void (* /*func*/ )()) { return 0; }
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
void initVariant() { }
void setupUSB() __attribute__((weak));
void setupUSB() { }
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}

@ -0,0 +1,41 @@
/*
Copyright (c) 2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
void *operator new(size_t size) {
return malloc(size);
}
void *operator new[](size_t size) {
return malloc(size);
}
void * operator new(size_t size, void * ptr) noexcept {
(void)size;
return ptr;
}
void operator delete(void * ptr) {
free(ptr);
}
void operator delete[](void * ptr) {
free(ptr);
}

@ -0,0 +1,392 @@
/*
wiring.c - Partial implementation of the Wiring API for the ATmega8.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#include "wiring_private.h"
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
#if defined(TIM0_OVF_vect)
ISR(TIM0_OVF_vect)
#else
ISR(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
unsigned long micros() {
unsigned long m;
uint8_t oldSREG = SREG, t;
cli();
m = timer0_overflow_count;
#if defined(TCNT0)
t = TCNT0;
#elif defined(TCNT0L)
t = TCNT0L;
#else
#error TIMER 0 not defined
#endif
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t < 255))
m++;
#else
if ((TIFR & _BV(TOV0)) && (t < 255))
m++;
#endif
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
uint32_t start = micros();
while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
void delayMicroseconds(unsigned int us)
{
// call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
#if IDIBUS_F_CPU >= 24000000L
// for the 24 MHz clock for the aventurous ones, trying to overclock
// zero delay fix
if (!us) return; // = 3 cycles, (4 when true)
// the following loop takes a 1/6 of a microsecond (4 cycles)
// per iteration, so execute it six times for each microsecond of
// delay requested.
us *= 6; // x6 us, = 7 cycles
// account for the time taken in the preceeding commands.
// we just burned 22 (24) cycles above, remove 5, (5*4=20)
// us is at least 6 so we can substract 5
us -= 5; //=2 cycles
#elif IDIBUS_F_CPU >= 20000000L
// for the 20 MHz clock on rare Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call takes 18 (20) cycles, which is 1us
__asm__ __volatile__ (
"nop" "\n\t"
"nop" "\n\t"
"nop" "\n\t"
"nop"); //just waiting 4 cycles
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes a 1/5 of a microsecond (4 cycles)
// per iteration, so execute it five times for each microsecond of
// delay requested.
us = (us << 2) + us; // x5 us, = 7 cycles
// account for the time taken in the preceeding commands.
// we just burned 26 (28) cycles above, remove 7, (7*4=28)
// us is at least 10 so we can substract 7
us -= 7; // 2 cycles
#elif IDIBUS_F_CPU >= 16000000L
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 1us
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes 1/4 of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2; // x4 us, = 4 cycles
// account for the time taken in the preceeding commands.
// we just burned 19 (21) cycles above, remove 5, (5*4=20)
// us is at least 8 so we can substract 5
us -= 5; // = 2 cycles,
#elif IDIBUS_F_CPU >= 12000000L
// for the 12 MHz clock if somebody is working with USB
// for a 1 microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 1.5us
if (us <= 1) return; // = 3 cycles, (4 when true)
// the following loop takes 1/3 of a microsecond (4 cycles)
// per iteration, so execute it three times for each microsecond of
// delay requested.
us = (us << 1) + us; // x3 us, = 5 cycles
// account for the time taken in the preceeding commands.
// we just burned 20 (22) cycles above, remove 5, (5*4=20)
// us is at least 6 so we can substract 5
us -= 5; //2 cycles
#elif IDIBUS_F_CPU >= 8000000L
// for the 8 MHz internal clock
// for a 1 and 2 microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 2us
if (us <= 2) return; // = 3 cycles, (4 when true)
// the following loop takes 1/2 of a microsecond (4 cycles)
// per iteration, so execute it twice for each microsecond of
// delay requested.
us <<= 1; //x2 us, = 2 cycles
// account for the time taken in the preceeding commands.
// we just burned 17 (19) cycles above, remove 4, (4*4=16)
// us is at least 6 so we can substract 4
us -= 4; // = 2 cycles
#else
// for the 1 MHz internal clock (default settings for common Atmega microcontrollers)
// the overhead of the function calls is 14 (16) cycles
if (us <= 16) return; //= 3 cycles, (4 when true)
if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22)
// compensate for the time taken by the preceeding and next commands (about 22 cycles)
us -= 22; // = 2 cycles
// the following loop takes 4 microseconds (4 cycles)
// per iteration, so execute it us/4 times
// us is at least 4, divided by 4 gives us 1 (no zero delay bug)
us >>= 2; // us div 4, = 4 cycles
#endif
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
// return = 4 cycles
}
void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();
// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if defined(TCCR0A) && defined(WGM01)
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
#endif
// set timer 0 prescale factor to 64
#if defined(__AVR_ATmega128__)
// CPU specific: different values for the ATmega128
sbi(TCCR0, CS02);
#elif defined(TCCR0) && defined(CS01) && defined(CS00)
// this combination is for the standard atmega8
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
// this combination is for the standard 168/328/1280/2560
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
// this combination is for the __AVR_ATmega645__ series
sbi(TCCR0A, CS01);
sbi(TCCR0A, CS00);
#else
#error Timer 0 prescale factor 64 not set correctly
#endif
// enable timer 0 overflow interrupt
#if defined(TIMSK) && defined(TOIE0)
sbi(TIMSK, TOIE0);
#elif defined(TIMSK0) && defined(TOIE0)
sbi(TIMSK0, TOIE0);
#else
#error Timer 0 overflow interrupt not set correctly
#endif
// timers 1 and 2 are used for phase-correct hardware pwm
// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle
#if defined(TCCR1B) && defined(CS11) && defined(CS10)
TCCR1B = 0;
// set timer 1 prescale factor to 64
sbi(TCCR1B, CS11);
#if IDIBUS_F_CPU >= 8000000L
sbi(TCCR1B, CS10);
#endif
#elif defined(TCCR1) && defined(CS11) && defined(CS10)
sbi(TCCR1, CS11);
#if IDIBUS_F_CPU >= 8000000L
sbi(TCCR1, CS10);
#endif
#endif
// put timer 1 in 8-bit phase correct pwm mode
#if defined(TCCR1A) && defined(WGM10)
sbi(TCCR1A, WGM10);
#endif
// set timer 2 prescale factor to 64
#if defined(TCCR2) && defined(CS22)
sbi(TCCR2, CS22);
#elif defined(TCCR2B) && defined(CS22)
sbi(TCCR2B, CS22);
//#else
// Timer 2 not finished (may not be present on this CPU)
#endif
// configure timer 2 for phase correct pwm (8-bit)
#if defined(TCCR2) && defined(WGM20)
sbi(TCCR2, WGM20);
#elif defined(TCCR2A) && defined(WGM20)
sbi(TCCR2A, WGM20);
//#else
// Timer 2 not finished (may not be present on this CPU)
#endif
#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64
sbi(TCCR3B, CS30);
sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
#endif
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
sbi(TCCR4B, CS41);
sbi(TCCR4B, CS40);
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
sbi(TCCR4B, CS40);
sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
#endif
#endif /* end timer4 block for ATMEGA1280/2560 and similar */
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
sbi(TCCR5B, CS50);
sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode
#endif
#if defined(ADCSRA)
// set a2d prescaler so we are inside the desired 50-200 KHz range.
#if IDIBUS_F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#elif IDIBUS_F_CPU >= 8000000 // 8 MHz / 64 = 125 KHz
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
#elif IDIBUS_F_CPU >= 4000000 // 4 MHz / 32 = 125 KHz
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#elif IDIBUS_F_CPU >= 2000000 // 2 MHz / 16 = 125 KHz
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);
#elif IDIBUS_F_CPU >= 1000000 // 1 MHz / 8 = 125 KHz
cbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#else // 128 kHz / 2 = 64 KHz -> This is the closest you can get, the prescaler is 2
cbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
#endif
// enable a2d conversions
sbi(ADCSRA, ADEN);
#endif
// the bootloader connects pins 0 and 1 to the USART; disconnect them
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(UCSRB)
UCSRB = 0;
#elif defined(UCSR0B)
UCSR0B = 0;
#endif
}

@ -0,0 +1,294 @@
/*
wiring_analog.c - analog input and output
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
Modified 28 September 2010 by Mark Sproul
*/
#include "wiring_private.h"
#include "pins_arduino.h"
uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode)
{
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode;
}
int analogRead(uint8_t pin)
{
uint8_t low, high;
#if defined(analogPinToChannel)
#if defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
#if defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = (analog_reference << 4) | (pin & 0x07);
#else
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
#endif
// without a delay, we seem to read from the wrong channel
//delay(1);
#if defined(ADCSRA) && defined(ADCL)
// start the conversion
sbi(ADCSRA, ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
#else
// we dont have an ADC, return 0
low = 0;
high = 0;
#endif
// combine the two bytes
return (high << 8) | low;
}
// Right now, PWM output only works on the pins with
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
// We need to make sure the PWM output is enabled for those pins
// that support it, as we turn it off when digitally reading or
// writing with them. Also, make sure the pin is in output mode
// for consistenty with Wiring, which doesn't require a pinMode
// call for the analog output pins.
pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
else
{
switch(digitalPinToTimer(pin))
{
// XXX fix needed for atmega8
#if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
case TIMER0A:
// connect pwm to pin on timer 0
sbi(TCCR0, COM00);
OCR0 = val; // set pwm duty
break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A:
// connect pwm to pin on timer 0, channel A
sbi(TCCR0A, COM0A1);
OCR0A = val; // set pwm duty
break;
#endif
#if defined(TCCR0A) && defined(COM0B1)
case TIMER0B:
// connect pwm to pin on timer 0, channel B
sbi(TCCR0A, COM0B1);
OCR0B = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A:
// connect pwm to pin on timer 1, channel A
sbi(TCCR1A, COM1A1);
OCR1A = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B:
// connect pwm to pin on timer 1, channel B
sbi(TCCR1A, COM1B1);
OCR1B = val; // set pwm duty
break;
#endif
#if defined(TCCR1A) && defined(COM1C1)
case TIMER1C:
// connect pwm to pin on timer 1, channel C
sbi(TCCR1A, COM1C1);
OCR1C = val; // set pwm duty
break;
#endif
#if defined(TCCR2) && defined(COM21)
case TIMER2:
// connect pwm to pin on timer 2
sbi(TCCR2, COM21);
OCR2 = val; // set pwm duty
break;
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A:
// connect pwm to pin on timer 2, channel A
sbi(TCCR2A, COM2A1);
OCR2A = val; // set pwm duty
break;
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B:
// connect pwm to pin on timer 2, channel B
sbi(TCCR2A, COM2B1);
OCR2B = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3A1)
case TIMER3A:
// connect pwm to pin on timer 3, channel A
sbi(TCCR3A, COM3A1);
OCR3A = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3B1)
case TIMER3B:
// connect pwm to pin on timer 3, channel B
sbi(TCCR3A, COM3B1);
OCR3B = val; // set pwm duty
break;
#endif
#if defined(TCCR3A) && defined(COM3C1)
case TIMER3C:
// connect pwm to pin on timer 3, channel C
sbi(TCCR3A, COM3C1);
OCR3C = val; // set pwm duty
break;
#endif
#if defined(TCCR4A)
case TIMER4A:
//connect pwm to pin on timer 4, channel A
sbi(TCCR4A, COM4A1);
#if defined(COM4A0) // only used on 32U4
cbi(TCCR4A, COM4A0);
#endif
OCR4A = val; // set pwm duty
break;
#endif
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B:
// connect pwm to pin on timer 4, channel B
sbi(TCCR4A, COM4B1);
OCR4B = val; // set pwm duty
break;
#endif
#if defined(TCCR4A) && defined(COM4C1)
case TIMER4C:
// connect pwm to pin on timer 4, channel C
sbi(TCCR4A, COM4C1);
OCR4C = val; // set pwm duty
break;
#endif
#if defined(TCCR4C) && defined(COM4D1)
case TIMER4D:
// connect pwm to pin on timer 4, channel D
sbi(TCCR4C, COM4D1);
#if defined(COM4D0) // only used on 32U4
cbi(TCCR4C, COM4D0);
#endif
OCR4D = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5A1)
case TIMER5A:
// connect pwm to pin on timer 5, channel A
sbi(TCCR5A, COM5A1);
OCR5A = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5B1)
case TIMER5B:
// connect pwm to pin on timer 5, channel B
sbi(TCCR5A, COM5B1);
OCR5B = val; // set pwm duty
break;
#endif
#if defined(TCCR5A) && defined(COM5C1)
case TIMER5C:
// connect pwm to pin on timer 5, channel C
sbi(TCCR5A, COM5C1);
OCR5C = val; // set pwm duty
break;
#endif
case NOT_ON_TIMER:
default:
if (val < 128) {
digitalWrite(pin, LOW);
} else {
digitalWrite(pin, HIGH);
}
}
}
}

@ -0,0 +1,179 @@
/*
wiring_digital.c - digital input and output functions
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
Modified 28 September 2010 by Mark Sproul
*/
#define ARDUINO_MAIN
#include "wiring_private.h"
#include "pins_arduino.h"
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
SREG = oldSREG;
}
}
// Forcing this inline keeps the callers from having to push their own stuff
// on the stack. It is a good performance win and only takes 1 more byte per
// user than calling. (It will take more bytes on the 168.)
//
// But shouldn't this be moved into pinMode? Seems silly to check and do on
// each digitalread or write.
//
// Mark Sproul:
// - Removed inline. Save 170 bytes on atmega1280
// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
// - Added more #ifdefs, now compiles for atmega645
//
//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
//static inline void turnOffPWM(uint8_t timer)
static void turnOffPWM(uint8_t timer)
{
switch (timer)
{
#if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: cbi(TCCR1A, COM1A1); break;
#endif
#if defined(TCCR1A) && defined(COM1B1)
case TIMER1B: cbi(TCCR1A, COM1B1); break;
#endif
#if defined(TCCR1A) && defined(COM1C1)
case TIMER1C: cbi(TCCR1A, COM1C1); break;
#endif
#if defined(TCCR2) && defined(COM21)
case TIMER2: cbi(TCCR2, COM21); break;
#endif
#if defined(TCCR0A) && defined(COM0A1)
case TIMER0A: cbi(TCCR0A, COM0A1); break;
#endif
#if defined(TCCR0A) && defined(COM0B1)
case TIMER0B: cbi(TCCR0A, COM0B1); break;
#endif
#if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: cbi(TCCR2A, COM2A1); break;
#endif
#if defined(TCCR2A) && defined(COM2B1)
case TIMER2B: cbi(TCCR2A, COM2B1); break;
#endif
#if defined(TCCR3A) && defined(COM3A1)
case TIMER3A: cbi(TCCR3A, COM3A1); break;
#endif
#if defined(TCCR3A) && defined(COM3B1)
case TIMER3B: cbi(TCCR3A, COM3B1); break;
#endif
#if defined(TCCR3A) && defined(COM3C1)
case TIMER3C: cbi(TCCR3A, COM3C1); break;
#endif
#if defined(TCCR4A) && defined(COM4A1)
case TIMER4A: cbi(TCCR4A, COM4A1); break;
#endif
#if defined(TCCR4A) && defined(COM4B1)
case TIMER4B: cbi(TCCR4A, COM4B1); break;
#endif
#if defined(TCCR4A) && defined(COM4C1)
case TIMER4C: cbi(TCCR4A, COM4C1); break;
#endif
#if defined(TCCR4C) && defined(COM4D1)
case TIMER4D: cbi(TCCR4C, COM4D1); break;
#endif
#if defined(TCCR5A)
case TIMER5A: cbi(TCCR5A, COM5A1); break;
case TIMER5B: cbi(TCCR5A, COM5B1); break;
case TIMER5C: cbi(TCCR5A, COM5C1); break;
#endif
}
}
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}

@ -0,0 +1,93 @@
/*
wiring_pulse.c - pulseIn() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#include "wiring_private.h"
#include "pins_arduino.h"
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*
* This function performs better with short pulses in noInterrupt() context
*/
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes approximately 16 clock cycles per iteration
unsigned long maxloops = microsecondsToClockCycles(timeout)/16;
unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);
// prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out
if (width)
return clockCyclesToMicroseconds(width * 16 + 16);
else
return 0;
}
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse.
*
* ATTENTION:
* this function relies on micros() so cannot be used in noInterrupt() context
*/
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long startMicros = micros();
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
unsigned long start = micros();
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask) {
if (micros() - startMicros > timeout)
return 0;
}
return micros() - start;
}

@ -0,0 +1,56 @@
/*
wiring_shift.c - shiftOut() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/
#include "wiring_private.h"
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
uint8_t value = 0;
uint8_t i;
for (i = 0; i < 8; ++i) {
digitalWrite(clockPin, HIGH);
if (bitOrder == LSBFIRST)
value |= digitalRead(dataPin) << i;
else
value |= digitalRead(dataPin) << (7 - i);
digitalWrite(clockPin, LOW);
}
return value;
}
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST) {
digitalWrite(dataPin, val & 1);
val >>= 1;
} else {
digitalWrite(dataPin, (val & 128) != 0);
val <<= 1;
}
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}

@ -0,0 +1,29 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_CALLBACK_INTERFACE_H_
#define _IDIBUS_CALLBACK_INTERFACE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusCallbackInterface {
public:
static void USART_Callback_InterruptTX (IdiBusCallbackInterface *inst) { inst->USART_TxInterruptFunc(); }
static void USART_Callback_InterruptRX (IdiBusCallbackInterface *inst) { inst->USART_RxInterruptFunc(); }
static void USART_Callback_InterruptUDRE (IdiBusCallbackInterface *inst) { inst->USART_UdreInterruptFunc(); }
virtual void USART_RxInterruptFunc(void) {}
virtual void USART_TxInterruptFunc(void) {}
virtual void USART_UdreInterruptFunc(void) {}
static void TIM_Callback_InterruptCOMPA (IdiBusCallbackInterface *inst) { inst->TIM_COMPA_InterruptFunc(); }
static void TIM_Callback_InterruptCOMPB (IdiBusCallbackInterface *inst) { inst->TIM_COMPB_InterruptFunc(); }
static void TIM_Callback_InterruptCOMPC (IdiBusCallbackInterface *inst) { inst->TIM_COMPC_InterruptFunc(); }
static void TIM_Callback_InterruptOVF (IdiBusCallbackInterface *inst) { inst->TIM_OVF_InterruptFunc(); }
virtual void TIM_COMPA_InterruptFunc (void) {}
virtual void TIM_COMPB_InterruptFunc (void) {}
virtual void TIM_COMPC_InterruptFunc (void) {}
virtual void TIM_OVF_InterruptFunc (void) {}
};
typedef void (*CallbackTypeFunction)(IdiBusCallbackInterface*);
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_CALLBACK_INTERFACE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,18 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_INTERRUPTS_DISABLE_H_
#define _IDIBUS_INTERRUPTS_DISABLE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_USART0_ISR_DISABLE
//#define IDIBUS_USART1_ISR_DISABLE
//#define IDIBUS_USART2_ISR_DISABLE
#define IDIBUS_USART3_ISR_DISABLE
#define IDIBUS_TIM0_ISR_DISABLE
//#define IDIBUS_TIM1_ISR_DISABLE
//#define IDIBUS_TIM2_ISR_DISABLE
//#define IDIBUS_TIM3_ISR_DISABLE
//#define IDIBUS_TIM4_ISR_DISABLE
//#define IDIBUS_TIM5_ISR_DISABLE
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_INTERRUPTS_DISABLE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,65 @@
//#############################################################################################################################################################################################################
#include "IdiBusInterruptsList.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct IDIBUS_INTERRUPT_LISTENERS_STR InterruptListenersList;
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#ifndef IDIBUS_USART0_ISR_DISABLE
ISR(USART0_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART0_CallbackInstance); }
ISR(USART0_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART0_CallbackInstance); }
ISR(USART0_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART0_CallbackInstance); }
#endif
#ifndef IDIBUS_USART1_ISR_DISABLE
ISR(USART1_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART1_CallbackInstance); }
ISR(USART1_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART1_CallbackInstance); }
ISR(USART1_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART1_CallbackInstance); }
#endif
#ifndef IDIBUS_USART2_ISR_DISABLE
ISR(USART2_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART2_CallbackInstance); }
ISR(USART2_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART2_CallbackInstance); }
ISR(USART2_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART2_CallbackInstance); }
#endif
#ifndef IDIBUS_USART3_ISR_DISABLE
ISR(USART3_RX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptRX(InterruptListenersList.USART3_CallbackInstance); }
ISR(USART3_TX_vect) { IdiBusCallbackInterface::USART_Callback_InterruptTX(InterruptListenersList.USART3_CallbackInstance); }
ISR(USART3_UDRE_vect) { IdiBusCallbackInterface::USART_Callback_InterruptUDRE(InterruptListenersList.USART3_CallbackInstance); }
#endif
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#ifndef IDIBUS_TIM0_ISR_DISABLE
ISR(TIMER0_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM0_CallbackInstance); }
ISR(TIMER0_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM0_CallbackInstance); }
ISR(TIMER0_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM0_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM1_ISR_DISABLE
ISR(TIMER1_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM1_CallbackInstance); }
ISR(TIMER1_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM1_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM2_ISR_DISABLE
ISR(TIMER2_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM2_CallbackInstance); }
ISR(TIMER2_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM2_CallbackInstance); }
ISR(TIMER2_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM2_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM3_ISR_DISABLE
ISR(TIMER3_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM3_CallbackInstance); }
ISR(TIMER3_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM3_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM4_ISR_DISABLE
ISR(TIMER4_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM4_CallbackInstance); }
ISR(TIMER4_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM4_CallbackInstance); }
#endif
#ifndef IDIBUS_TIM5_ISR_DISABLE
ISR(TIMER5_COMPA_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPA(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_COMPB_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPB(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_COMPC_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptCOMPC(InterruptListenersList.TIM5_CallbackInstance); }
ISR(TIMER5_OVF_vect) { IdiBusCallbackInterface::TIM_Callback_InterruptOVF(InterruptListenersList.TIM5_CallbackInstance); }
#endif
//#############################################################################################################################################################################################################

@ -0,0 +1,48 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_INTERRUPTS_LIST_H_
#define _IDIBUS_INTERRUPTS_LIST_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "IdiBusCallbackInterface.h"
#include "IdiBusInterruptsDisable.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct IDIBUS_INTERRUPT_LISTENERS_STR {
#ifndef IDIBUS_USART0_ISR_DISABLE
IdiBusCallbackInterface *USART0_CallbackInstance;
#endif
#ifndef IDIBUS_USART1_ISR_DISABLE
IdiBusCallbackInterface *USART1_CallbackInstance;
#endif
#ifndef IDIBUS_USART2_ISR_DISABLE
IdiBusCallbackInterface *USART2_CallbackInstance;
#endif
#ifndef IDIBUS_USART3_ISR_DISABLE
IdiBusCallbackInterface *USART3_CallbackInstance;
#endif
#ifndef IDIBUS_TIM0_ISR_DISABLE
IdiBusCallbackInterface *TIM0_CallbackInstance;
#endif
#ifndef IDIBUS_TIM1_ISR_DISABLE
IdiBusCallbackInterface *TIM1_CallbackInstance;
#endif
#ifndef IDIBUS_TIM2_ISR_DISABLE
IdiBusCallbackInterface *TIM2_CallbackInstance;
#endif
#ifndef IDIBUS_TIM3_ISR_DISABLE
IdiBusCallbackInterface *TIM3_CallbackInstance;
#endif
#ifndef IDIBUS_TIM4_ISR_DISABLE
IdiBusCallbackInterface *TIM4_CallbackInstance;
#endif
#ifndef IDIBUS_TIM5_ISR_DISABLE
IdiBusCallbackInterface *TIM5_CallbackInstance;
#endif
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern struct IDIBUS_INTERRUPT_LISTENERS_STR InterruptListenersList;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_INTERRUPTS_LIST_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,57 @@
//#############################################################################################################################################################################################################
#include "IdiBusDateTime.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiDateFormat::IdiDateFormat(uint8_t day, uint8_t month, uint8_t century, uint8_t year99)
{
this->Day = day;
this->Month = month;
this->Century = century;
this->Year99 = year99;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiDateFormat::isValid(void)
{
if ( (this->Day == 0) || (this->Day > 31) ||
(this->Month == 0) || (this->Month > 12) ||
(this->Century > 99) || (this->Year99 > 99) ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiDateFormat::getSize(void) { return IDIDATE_FORMAT_LENGTH; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiDateFormat::getBufForMMES(uint8_t *Data)
{
Data[IDIDATE_FORMAT_DAY_Pos] = this->Day;
Data[IDIDATE_FORMAT_MONTH_Pos] = this->Month;
Data[IDIDATE_FORMAT_CENTURY_Pos] = this->Century;
Data[IDIDATE_FORMAT_YEAR99_Pos] = this->Year99;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiTimeFormat::IdiTimeFormat(uint8_t seconds, uint8_t minutes, uint8_t hours, int8_t timezone)
{
this->Seconds = seconds;
this->Minutes = minutes;
this->Hours = hours;
this->TimeZone = timezone;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiTimeFormat::isValid(void)
{
if ( (this->Seconds > 60) || (this->Minutes > 60) || (this->Hours > 23) ||
(this->TimeZone < IDITIME_FORMAT_TIMEZONE_MIN) || (this->TimeZone > IDITIME_FORMAT_TIMEZONE_MAX) ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiTimeFormat::getSize(void) { return IDITIME_FORMAT_LENGTH; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiTimeFormat::getBufForMMES(uint8_t *Data)
{
Data[IDITIME_FORMAT_SECONDS_Pos] = this->Seconds;
Data[IDITIME_FORMAT_MINUTES_Pos] = this->Minutes;
Data[IDITIME_FORMAT_HOURS_Pos] = this->Hours;
Data[IDITIME_FORMAT_TIMEZONE_Pos] = (uint8_t)this->TimeZone;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,32 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_DATE_TIME_H_
#define _IDIBUS_DATE_TIME_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiDateFormat {
public:
IdiDateFormat(uint8_t day, uint8_t month, uint8_t century, uint8_t year99);
uint8_t Day;
uint8_t Month;
uint8_t Century;
uint8_t Year99;
uint8_t isValid(void);
uint8_t getSize(void);
void getBufForMMES(uint8_t *Data);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiTimeFormat {
public:
IdiTimeFormat(uint8_t seconds, uint8_t minutes, uint8_t hours, int8_t timezone);
uint8_t Seconds;
uint8_t Minutes;
uint8_t Hours;
int8_t TimeZone;
uint8_t isValid(void);
uint8_t getSize(void);
void getBufForMMES(uint8_t *Data);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_DATE_TIME_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,128 @@
//#############################################################################################################################################################################################################
#include "IdiBusMes.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsGroupAddr(void) { return ( (this->SlAddr >= IDIBUS_GROUP_0_ADDR)&&(this->SlAddr <= IDIBUS_GROUP_15_ADDR) ) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsCommand(void) { return ( this->ComFunc >= IDIMMES_COM_START_NUM ) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsModuleError(uint8_t ErrCode) { return ((ErrCode >= IDIER_MODULE_NUM_START)&&(ErrCode <= IDIER_MODULE_NUM_END)) ? 1 : 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMessage::IsModuleCommand(void)
{
switch (this->ComFunc)
{
case(IDIMMES_COM_C_Init) :
case(IDIMMES_COM_C_ShtDown) :
case(IDIMMES_COM_C_Freeze) :
case(IDIMMES_COM_C_Resume) :
case(IDIMMES_COM_C_SetAlarmL12) :
case(IDIMMES_COM_C_SetAlarmL) :
case(IDIMMES_COM_C_SyncRead) :
case(IDIMMES_COM_C_SyncDoChnl) :
case(IDIMMES_COM_C_SyncDo) :
case(IDIMMES_COM_C_SyncClear) :
case(IDIMMES_COM_C_SendTimeDate) :
case(IDIMMES_COM_C_MkTimedMaster) :
case(IDIMMES_COM_C_FmwUpd) :
case(IDIMMES_COM_C_EndFmwUpd) :
case(IDIMMES_COM_C_FmwWrite) :
case(IDIMMES_COM_C_ReadDevFullSN_MS) :
case(IDIMMES_COM_C_WriteSnIPv4IPv6) :
case(IDIMMES_COM_C_WriteSnVerifyDates) :
case(IDIMMES_COM_C_WriteSnAES256) :
case(IDIMMES_COM_C_DummyModule) :
case(IDIMMES_COM_C_CheckModuleLongOp) : { return 1; }
default : {}
}
return 0;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBusMMES::IdiBusMMES (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->DEV.NUM = 0;
this->DEV.ALLCH = 0;
this->CHNL.ALLSAME = 0;
this->CHNL.NUM = 0;
this->ComFunc = 1;
this->TxData = TX_DataP;
this->TxDataLength = TX_DataLength;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusMMES::IdiBusMMES (uint8_t SlAddr)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->DEV.NUM = 0;
this->DEV.ALLCH = 0;
this->CHNL.ALLSAME = 0;
this->CHNL.NUM = 0;
this->ComFunc = IDIMMES_COM_C_Dummy;
this->TxData = NULL;
this->TxDataLength = 0;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMMES::IsValid(void)
{
if ( (this->ComFunc == 0) || this->IsModuleCommand() || this->IsGroupAddr() ) { return 0; }
return 1;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
IdiBusMMESG::IdiBusMMESG (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->ComFunc = IDIMMES_COM_C_DummyModule;
this->TxData = TX_DataP;
this->TxDataLength = TX_DataLength;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusMMESG::IdiBusMMESG (uint8_t SlAddr)
{
this->SlAddr = SlAddr;
this->MMPS.LongMes = 0;
this->MMPS.AlarmMes = 0;
this->MMPS.EncryptedAes = 0;
this->ComFunc = IDIMMES_COM_C_Dummy;
this->TxData = NULL;
this->TxDataLength = 0;
this->RxData = NULL;
this->RxDataLength = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusMMESG::IsValid(void)
{
uint8_t isModuleCommand = this->IsModuleCommand();
uint8_t isGroupAddress = this->IsGroupAddr();
if ( this->ComFunc == IDIMMES_NOT_FAST_FUNC ) { return 0; }
if ( isGroupAddress )
{
if ( isModuleCommand != 0 ) { return 0; }
}
else if ( isModuleCommand == 0 ) { return 0; }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,50 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_MES_H_
#define _IDIBUS_MES_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMessage {
public :
uint8_t SlAddr;
struct {
uint8_t LongMes : 1;
uint8_t AlarmMes : 1;
uint8_t EncryptedAes : 1;
} MMPS;
uint8_t ComFunc;
uint8_t *TxData;
uint16_t TxDataLength;
uint8_t *RxData;
uint16_t RxDataLength;
uint8_t IsGroupAddr(void);
uint8_t IsModuleCommand(void);
uint8_t IsCommand(void);
uint8_t IsModuleError(uint8_t ErrCode);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMMES : public IdiBusMessage {
public :
IdiBusMMES (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength);
IdiBusMMES (uint8_t SlAddr);
struct {
uint8_t NUM : 5;
uint8_t ALLCH : 1;
} DEV;
struct {
uint8_t NUM : 7;
uint8_t ALLSAME : 1;
} CHNL;
uint8_t IsValid(void);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusMMESG : public IdiBusMessage {
public :
IdiBusMMESG (uint8_t SlAddr, uint8_t *TX_DataP, uint16_t TX_DataLength);
IdiBusMMESG (uint8_t SlAddr);
uint8_t IsValid(void);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_MES_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,621 @@
//#############################################################################################################################################################################################################
#include "IdiBusSerial.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerial::IdiBusSerial(void)
{
this->RS485_DIR_GPIO.DDR = (uint8_t*)&this->InitProtectionVar;
this->RS485_DIR_GPIO.PIN = (uint8_t*)&this->InitProtectionVar;
this->RS485_DIR_GPIO.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S0_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S1_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.DDR = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.PIN = (uint8_t*)&this->InitProtectionVar;
this->BAUDRATE_DIPSW.S2_Gpio.PORT = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNA = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNB = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UCSRNC = (uint8_t*)&this->InitProtectionVar;
this->USARTN.UBRRN = (uint16_t*)&this->InitProtectionVar;
this->USARTN.UDRN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TCCRNA = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TCCRNB = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TIMSKN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.TIFRN = (uint8_t*)&this->InitProtectionVar;
this->TIMN.OCRNA = (uint16_t*)&this->InitProtectionVar;
this->TIMN.OCRNB = (uint16_t*)&this->InitProtectionVar;
this->TIMN.TCNTN = (uint16_t*)&this->InitProtectionVar;
this->InitState = 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::Init(IDIBUS_SERIAL_INIT_TYPEDEF *InitT)
{
if ( (this->GetGpioParamsArduino(InitT->RS485_DIR_PIN, &this->RS485_DIR_GPIO) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S0_PIN, &this->BAUDRATE_DIPSW.S0_Gpio) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S1_PIN, &this->BAUDRATE_DIPSW.S1_Gpio) == 0) ||
(this->GetGpioParamsArduino(InitT->BAUDRATE_DIPSW_S2_PIN, &this->BAUDRATE_DIPSW.S2_Gpio) == 0) ) { return 0; }
return this->BaseInit(InitT->USART_NUMBER, InitT->TIMER_NUMBER, InitT->CONFIG);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::Init(IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF *InitT)
{
if ( (this->GetGpioParams(&InitT->RS485_DIR_GPIO, &this->RS485_DIR_GPIO) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S0, &this->BAUDRATE_DIPSW.S0_Gpio) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S1, &this->BAUDRATE_DIPSW.S1_Gpio) == 0) ||
(this->GetGpioParams(&InitT->BAUDRATE_DIPSW.S2, &this->BAUDRATE_DIPSW.S2_Gpio) == 0) ) { return 0; }
return this->BaseInit(InitT->USART_NUMBER, InitT->TIMER_NUMBER, InitT->CONFIG);
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::BaseInit( enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUM, enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUM, enum IDIBUS_SERIAL_USARTN_CONFIG CONF)
{
// Pointers Init
switch (USART_NUM)
{
case (IDIBUS_SERIAL_USART0) : {
#if defined IDIBUS_USART0_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR0A);
this->USARTN.UCSRNB = &(UCSR0B);
this->USARTN.UCSRNC = &(UCSR0C);
this->USARTN.UBRRN = &(UBRR0);
this->USARTN.UDRN = &(UDR0);
InterruptListenersList.USART0_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART1) : {
#if defined IDIBUS_USART1_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR1A);
this->USARTN.UCSRNB = &(UCSR1B);
this->USARTN.UCSRNC = &(UCSR1C);
this->USARTN.UBRRN = &(UBRR1);
this->USARTN.UDRN = &(UDR1);
InterruptListenersList.USART1_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART2) : {
#if defined IDIBUS_USART2_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR2A);
this->USARTN.UCSRNB = &(UCSR2B);
this->USARTN.UCSRNC = &(UCSR2C);
this->USARTN.UBRRN = &(UBRR2);
this->USARTN.UDRN = &(UDR2);
InterruptListenersList.USART2_CallbackInstance = this;
#endif
break; }
case (IDIBUS_SERIAL_USART3) : {
#if defined IDIBUS_USART3_ISR_DISABLE
return 0;
#else
this->USARTN.UCSRNA = &(UCSR3A);
this->USARTN.UCSRNB = &(UCSR3B);
this->USARTN.UCSRNC = &(UCSR3C);
this->USARTN.UBRRN = &(UBRR3);
this->USARTN.UDRN = &(UDR3);
InterruptListenersList.USART3_CallbackInstance = this;
#endif
break; }
default : { return 0; }
}
switch (TIMER_NUM)
{
case (IDIBUS_TIMER_1) : {
#if defined IDIBUS_TIM1_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR1A);
this->TIMN.TCCRNB = &(TCCR1B);
this->TIMN.TIMSKN = &(TIMSK1);
this->TIMN.TIFRN = &(TIFR1);
this->TIMN.OCRNA = &(OCR1A);
this->TIMN.OCRNB = &(OCR1B);
this->TIMN.TCNTN = &(TCNT1);
InterruptListenersList.TIM1_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_3) : {
#if defined IDIBUS_TIM3_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR3A);
this->TIMN.TCCRNB = &(TCCR3B);
this->TIMN.TIMSKN = &(TIMSK3);
this->TIMN.TIFRN = &(TIFR3);
this->TIMN.OCRNA = &(OCR3A);
this->TIMN.OCRNB = &(OCR3B);
this->TIMN.TCNTN = &(TCNT3);
InterruptListenersList.TIM3_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_4) : {
#if defined IDIBUS_TIM4_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR4A);
this->TIMN.TCCRNB = &(TCCR4B);
this->TIMN.TIMSKN = &(TIMSK4);
this->TIMN.TIFRN = &(TIFR4);
this->TIMN.OCRNA = &(OCR4A);
this->TIMN.OCRNB = &(OCR4B);
this->TIMN.TCNTN = &(TCNT4);
InterruptListenersList.TIM4_CallbackInstance = this;
#endif
break; }
case (IDIBUS_TIMER_5) : {
#if defined IDIBUS_TIM5_ISR_DISABLE
return 0;
#else
this->TIMN.TCCRNA = &(TCCR5A);
this->TIMN.TCCRNB = &(TCCR5B);
this->TIMN.TIMSKN = &(TIMSK5);
this->TIMN.TIFRN = &(TIFR5);
this->TIMN.OCRNA = &(OCR5A);
this->TIMN.OCRNB = &(OCR5B);
this->TIMN.TCNTN = &(TCNT5);
InterruptListenersList.TIM5_CallbackInstance = this;
#endif
break; }
default : { return 0; }
}
// GPIO Init
uint8_t SREG_Temp = SREG;
cli();
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK;
*this->RS485_DIR_GPIO.DDR |= this->RS485_DIR_GPIO.PIN_MASK;
*this->BAUDRATE_DIPSW.S0_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S0_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S1_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S1_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S2_Gpio.PORT &= ~this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK;
*this->BAUDRATE_DIPSW.S2_Gpio.DDR &= ~this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK;
if ( SREG_Temp & (0x01U << SREG_I) ) { sei(); }
// USART Init
*this->USARTN.UBRRN = 0;
*this->USARTN.UCSRNA = (1U<<USARTN_UCSRNA_U2X_Pos);
*this->USARTN.UCSRNB = 0;
this->BAUDRATE = 0;
switch (CONF)
{
case (IDIBUS_SERIAL_8N1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(0U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8N2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(0U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8E1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8E2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(0U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8O1) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(0U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(1U<<USARTN_UCSRNC_UPM0); break; }
case (IDIBUS_SERIAL_8O2) : { *this->USARTN.UCSRNC = (1U<<USARTN_UCSRNC_UCSZ0)|(1U<<USARTN_UCSRNC_UCSZ1)|(1U<<USARTN_UCSRNC_USBS)|(1U<<USARTN_UCSRNC_UPM1)|(1U<<USARTN_UCSRNC_UPM0); break; }
default : { return 0; }
}
// TIMER Init
*this->TIMN.TCCRNB = 0; // Counter stop
*this->TIMN.TCCRNA = 0; // Normal Mode
*this->TIMN.TIMSKN = 0;
this->InitState = 1;
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::SetBaudrate(enum IDIBUS_SERIAL_BAUDRATE Baudrate)
{
switch ( Baudrate )
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : {
this->SetBaudrateLL(2400);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint32_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : {
this->SetBaudrateLL(9600);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint32_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : {
this->SetBaudrateLL(19200);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : {
this->SetBaudrateLL(115200);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : {
this->SetBaudrateLL(250000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : {
this->SetBaudrateLL(500000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : {
this->SetBaudrateLL(1000000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : {
this->SetBaudrateLL(10000000);
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
default : { return; }
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::UpdateBaudrateFromDipSwitch(void)
{
uint8_t BaudrateCode = 0;
uint32_t BaudrateCodeValue;
if ( (*this->BAUDRATE_DIPSW.S2_Gpio.PIN & this->BAUDRATE_DIPSW.S2_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x04; }
if ( (*this->BAUDRATE_DIPSW.S1_Gpio.PIN & this->BAUDRATE_DIPSW.S1_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x02; }
if ( (*this->BAUDRATE_DIPSW.S0_Gpio.PIN & this->BAUDRATE_DIPSW.S0_Gpio.PIN_MASK) != 0 ) { BaudrateCode |= 0x01; }
switch (BaudrateCode)
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : { BaudrateCodeValue = 2400U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : { BaudrateCodeValue = 9600U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : { BaudrateCodeValue = 19200U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : { BaudrateCodeValue = 115200U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : { BaudrateCodeValue = 250000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : { BaudrateCodeValue = 500000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : { BaudrateCodeValue = 1000000U; break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : { BaudrateCodeValue = 10000000U; break; }
default : { return; }
}
if ( this->BAUDRATE != BaudrateCodeValue )
{
this->SetBaudrateLL(BaudrateCodeValue);
switch ( BaudrateCode )
{
case (IDIBUS_BAUDRATE_DSW_CODE_2400B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_9600B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_19200B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_115200B) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_250K) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_500K) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_1M) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
case (IDIBUS_BAUDRATE_DSW_CODE_10M) : {
this->TimerInterFrameCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_INTERFRAME_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE ) / 1000000ULL );
this->TimerTimeoutCompValue = (uint16_t)( ((uint64_t)IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US * (uint64_t)F_CPU / (uint64_t)IDIBUS_SERIAL_TIMER_PR_VALUE) / 1000000ULL );
break; }
default : { return; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::SetBaudrateLL(uint32_t Baudrate)
{
uint16_t UBRR_2X;
if ( ((F_CPU / 8U) % Baudrate) < (Baudrate / 2) )
{
UBRR_2X = (uint16_t)( ((uint32_t)F_CPU / 8U) / Baudrate );
if ( UBRR_2X != 0 ) { UBRR_2X--; }
}
else { UBRR_2X = (uint16_t)( ((uint32_t)F_CPU / 16U) / Baudrate ); } // WARNING CHANGED DIVIDER FROM 8 TO 16!!! //(F_CPU / 8U) / Baudrate + 1 - 1
*this->USARTN.UBRRN = UBRR_2X;
this->BAUDRATE = Baudrate;
if ( this->InitState == 1 ) { this->InitState = 2; }
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiBusSerial::Start(void)
{
*this->USARTN.UCSRNB = (1U<<USARTN_UCSRNB_TXEN_Pos) | (1U<<USARTN_UCSRNB_TXCIE_Pos); // USART TX Periph enable
cli();
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK; // Dir to Tx
sei();
this->TransferComplete = 1; //
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::Stop(void)
{
*this->TIMN.TCCRNB = 0; // Timer Stop
cli();
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK; // Dir to RX
sei();
*this->USARTN.UCSRNB = 0; // USART TX/RX Periph disable
this->TransferComplete = 1; //
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
if ( _TxBufLength_ == 0 ) { this->ERROR_STATUS.BF.TxZerolength = 1; return 0; }
else if ( _TxBufLength_ > IDIBUS_SERIAL_TX_BUF_SIZE ) { this->ERROR_STATUS.BF.TxOverflow = 1; return 0; }
memcpy(this->TxBuf, _TxBuf_, _TxBufLength_);
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_RX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
if ( this->TimerTimeoutCompValue > (0xFFFFU - this->TimerInterFrameCompValue) )
{
*this->TIMN.OCRNB = 0xFFFFU;
this->TimerTimeoutOverflow = (uint16_t)( this->TimerTimeoutCompValue - (0xFFFFU - this->TimerInterFrameCompValue) );
}
else
{
*this->TIMN.OCRNB = (uint16_t)(this->TimerTimeoutCompValue + this->TimerInterFrameCompValue);
this->TimerTimeoutOverflow = 0;
}
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe and Response timeouts
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos) | (1U << USRTN_TIM_TIMSK_OCIEB_Pos);
this->TxBufCounter = 1;
this->TxBufLength = _TxBufLength_;
this->RxBufCounter = 0;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestSync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) { }
if ( this->SendRequestAsync(_TxBuf_, _TxBufLength_) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) { }
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
if ( _TxBufLength_ == 0 ) { this->ERROR_STATUS.BF.TxZerolength = 1; return 0; }
else if ( _TxBufLength_ > IDIBUS_SERIAL_TX_BUF_SIZE ) { this->ERROR_STATUS.BF.TxOverflow = 1; return 0; }
this->TransferComplete = 0;
memcpy(this->TxBuf, _TxBuf_, _TxBufLength_);
this->RequestType = _IDIBUS_SERIAL_TX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe Timeout
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos);
this->TxBufCounter = 1;
this->TxBufLength = _TxBufLength_;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteSync(uint8_t *_TxBuf_, uint16_t _TxBufLength_)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->WriteAsync(_TxBuf_, _TxBufLength_) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t *IdiBusSerial::getTxBufPointer(void)
{
if ( this->TransferComplete ) { return this->TxBuf; }
else { return NULL; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t *IdiBusSerial::getRxBufPointer (void)
{
return this->RxBuf;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestAsync(uint16_t DataLength)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_RX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
if ( this->TimerTimeoutCompValue > (0xFFFFU - this->TimerInterFrameCompValue) )
{
*this->TIMN.OCRNB = 0xFFFFU;
this->TimerTimeoutOverflow = (uint16_t)( this->TimerTimeoutCompValue - (0xFFFFU - this->TimerInterFrameCompValue) );
}
else
{
*this->TIMN.OCRNB = (uint16_t)(this->TimerTimeoutCompValue + this->TimerInterFrameCompValue);
this->TimerTimeoutOverflow = 0;
}
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe and Response timeouts
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos) | (1U << USRTN_TIM_TIMSK_OCIEB_Pos);
this->TxBufCounter = 1;
this->TxBufLength = DataLength;
this->RxBufCounter = 0;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::SendRequestSync(uint16_t DataLength)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->SendRequestAsync(DataLength) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteAsync(uint16_t DataLength)
{
if ( (this->TransferComplete == 0) || (this->InitState != 2) ) { return 0; }
this->ERROR_STATUS.SumVar = 0;
this->TransferComplete = 0;
this->RequestType = _IDIBUS_SERIAL_TX_;
*this->TIMN.OCRNA = this->TimerInterFrameCompValue;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFA_Pos) | (1U << USARTN_TIM_TIFR_OCFB_Pos); // Interframe Timeout
*this->TIMN.TIMSKN = (1U << USRTN_TIM_TIMSK_OCIEA_Pos);
this->TxBufCounter = 1;
this->TxBufLength = DataLength;
*this->USARTN.UDRN = this->TxBuf[0];
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::WriteSync(uint16_t DataLength)
{
if ( this->InitState != 2 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
if ( this->WriteAsync(DataLength) == 0 ) { return 0; }
while ( this->TransferComplete == 0 ) {}
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::IsTransferComplete(void) { return this->TransferComplete; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t IdiBusSerial::GetRxBufCounter(void) { return this->RxBufCounter; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IDIBUS_SERIAL_ERROR_STATUS_TYPE IdiBusSerial::GetErrorStatus(void) { return this->ERROR_STATUS; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint32_t IdiBusSerial::GetBaudrate(void) { return this->BAUDRATE; }
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiBusSerial::USART_RxInterruptFunc (void)
{
*this->TIMN.TCNTN = 0;
if ( (*this->USARTN.UCSRNA & ( (1U<<USARTN_UCSRNA_FE_Pos)|(1U<<USARTN_UCSRNA_DOR_Pos)|(1U<<USARTN_UCSRNA_UPE_Pos)) ) == 0 )
{
if ( this->RxBufCounter < IDIBUS_SERIAL_RX_BUF_SIZE ) { this->RxBuf[this->RxBufCounter++] = *this->USARTN.UDRN; }
else { this->ERROR_STATUS.BF.RxOverflow = 1; (void)*this->USARTN.UDRN; }
}
else { this->ERROR_STATUS.BF.LLComERR = 1; (void)*this->USARTN.UDRN; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::USART_TxInterruptFunc (void)
{
if ( this->TxBufCounter != this->TxBufLength ) { *this->USARTN.UDRN = this->TxBuf[this->TxBufCounter++]; }
else
{
switch (this->RequestType)
{
case (_IDIBUS_SERIAL_TX_RX_) : {
*this->RS485_DIR_GPIO.PORT &= ~this->RS485_DIR_GPIO.PIN_MASK;
*this->USARTN.UCSRNB |= (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos);
*this->TIMN.TCCRNB = IDIBUS_SERIAL_TIMER_PR_REG; //Timer Start
break; }
case (_IDIBUS_SERIAL_TX_) : {
*this->TIMN.TCCRNB = IDIBUS_SERIAL_TIMER_PR_REG; //Timer Start
break; }
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::TIM_COMPA_InterruptFunc (void)
{
switch (this->RequestType)
{
case ( _IDIBUS_SERIAL_TX_RX_ ) : {
if ( this->RxBufCounter != 0 ) // Interframe Timeout < Response < Request Timeout
{
*this->TIMN.TCCRNB = 0; // Timer Stop
*this->USARTN.UCSRNB &= ~( (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos) ); // Rx Periph Stop
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK; // Dir to TX
this->TransferComplete = 1; // Complete
}
break; }
case (_IDIBUS_SERIAL_TX_) : {
*this->TIMN.TCCRNB = 0; // Timer Stop
this->TransferComplete = 1; // Complete
break; }
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSerial::TIM_COMPB_InterruptFunc (void)
{
if ( this->TimerTimeoutOverflow != 0 )
{
*this->TIMN.OCRNB = this->TimerTimeoutOverflow;
*this->TIMN.TCNTN = 0;
*this->TIMN.TIFRN = (1U << USARTN_TIM_TIFR_OCFB_Pos);
this->TimerTimeoutOverflow = 0;
}
else
{
*this->TIMN.TCCRNB = 0; //Timer Stop
*this->USARTN.UCSRNB &= ~( (1U<<USARTN_UCSRNB_RXEN_Pos) | (1U<<USARTN_UCSRNB_RXCIE_Pos) );
*this->RS485_DIR_GPIO.PORT |= this->RS485_DIR_GPIO.PIN_MASK;
this->ERROR_STATUS.BF.TimeoutERR = 1;
this->TransferComplete = 1;
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSerial::GetGpioParams(IDIBUS_SERIAL_GPIO_INIT *InitSTR, IDIBUS_SERIAL_GPIO *gpio)
{
if ( InitSTR->PIN_NUM > 7 ) { return 0; }
if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTA ) { gpio->PORT = &PORTA; gpio->DDR = &DDRA; gpio->PIN = &PINA; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTB ) { gpio->PORT = &PORTB; gpio->DDR = &DDRB; gpio->PIN = &PINB; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTC ) { gpio->PORT = &PORTC; gpio->DDR = &DDRC; gpio->PIN = &PINC; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTD ) { gpio->PORT = &PORTD; gpio->DDR = &DDRD; gpio->PIN = &PIND; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTE ) { gpio->PORT = &PORTE; gpio->DDR = &DDRE; gpio->PIN = &PINE; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTF ) { gpio->PORT = &PORTF; gpio->DDR = &DDRF; gpio->PIN = &PINF; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTG ) { gpio->PORT = &PORTG; gpio->DDR = &DDRG; gpio->PIN = &PING; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTH ) { gpio->PORT = &PORTH; gpio->DDR = &DDRH; gpio->PIN = &PINH; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTJ ) { gpio->PORT = &PORTJ; gpio->DDR = &DDRJ; gpio->PIN = &PINJ; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTK ) { gpio->PORT = &PORTK; gpio->DDR = &DDRK; gpio->PIN = &PINK; }
else if ( (uint16_t)InitSTR->PORT == (uint16_t)&PORTL ) { gpio->PORT = &PORTL; gpio->DDR = &DDRL; gpio->PIN = &PINL; }
else { return 0; }
gpio->PIN_MASK = (0x01U << InitSTR->PIN_NUM);
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerial::GetGpioParamsArduino(uint8_t PinNum, IDIBUS_SERIAL_GPIO *gpio)
{
uint8_t PortCode;
if ( (PinNum >= NUM_DIGITAL_PINS) || ((PortCode = digitalPinToPort(PinNum)) == NOT_A_PIN) ) { return 0; }
gpio->PIN_MASK = digitalPinToBitMask(PinNum);
gpio->PORT = portOutputRegister(PortCode);
gpio->DDR = portModeRegister(PortCode);
gpio->PIN = portInputRegister(PortCode);
return 1;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,123 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SERIAL_H_
#define _IDIBUS_SERIAL_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusSerialDefs.h"
#include "IdiBusInterruptsList.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_SERIAL_USARTN_NUMBER {
IDIBUS_SERIAL_USART0,
IDIBUS_SERIAL_USART1,
IDIBUS_SERIAL_USART2,
IDIBUS_SERIAL_USART3
};
enum IDIBUS_SERIAL_TIMER_NUMBER {
IDIBUS_TIMER_1 = 1,
IDIBUS_TIMER_3 = 3,
IDIBUS_TIMER_4,
IDIBUS_TIMER_5
};
enum IDIBUS_SERIAL_USARTN_CONFIG {
IDIBUS_SERIAL_8N1,
IDIBUS_SERIAL_8N2,
IDIBUS_SERIAL_8E1,
IDIBUS_SERIAL_8E2,
IDIBUS_SERIAL_8O1,
IDIBUS_SERIAL_8O2
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUMBER;
enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUMBER;
enum IDIBUS_SERIAL_USARTN_CONFIG CONFIG;
uint8_t RS485_DIR_PIN;
uint8_t BAUDRATE_DIPSW_S0_PIN;
uint8_t BAUDRATE_DIPSW_S1_PIN;
uint8_t BAUDRATE_DIPSW_S2_PIN;
} IDIBUS_SERIAL_INIT_TYPEDEF;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUMBER;
enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUMBER;
enum IDIBUS_SERIAL_USARTN_CONFIG CONFIG;
IDIBUS_SERIAL_GPIO_INIT RS485_DIR_GPIO;
struct {
IDIBUS_SERIAL_GPIO_INIT S0;
IDIBUS_SERIAL_GPIO_INIT S1;
IDIBUS_SERIAL_GPIO_INIT S2;
} BAUDRATE_DIPSW;
} IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusSerial : public IdiBusCallbackInterface {
public :
IdiBusSerial(void);
uint8_t Init(IDIBUS_SERIAL_INIT_TYPEDEF *InitT);
uint8_t Init(IDIBUS_SERIAL_ALTERNATIVE_INIT_TYPEDEF *InitT);
void SetBaudrate(enum IDIBUS_SERIAL_BAUDRATE Baudrate);
void UpdateBaudrateFromDipSwitch(void);
void Start (void); // Hold Line
void Stop (void); // TX/RX disable, Release Line
uint8_t SendRequestAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t SendRequestSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t WriteSync (uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t WriteAsync(uint8_t *_TxBuf_, uint16_t _TxBufLength_);
uint8_t IsTransferComplete(void);
uint16_t GetRxBufCounter(void);
IDIBUS_SERIAL_ERROR_STATUS_TYPE GetErrorStatus(void);
uint32_t GetBaudrate(void);
private :
IDIBUS_SERIAL_USART_HW_TYPE USARTN;
IDIBUS_SERIAL_USARTN_16BIT_TIMER TIMN;
IDIBUS_SERIAL_GPIO RS485_DIR_GPIO;
IDIBUS_SERIAL_BAUDRATE_DIPSW_TYPE BAUDRATE_DIPSW;
uint32_t BAUDRATE;
uint8_t TxBuf[IDIBUS_SERIAL_TX_BUF_SIZE];
uint16_t TxBufLength;
uint16_t TxBufCounter;
uint8_t RxBuf[IDIBUS_SERIAL_RX_BUF_SIZE];
uint16_t RxBufCounter;
IDIBUS_SERIAL_ERROR_STATUS_TYPE ERROR_STATUS;
uint16_t TimerInterFrameCompValue;
uint16_t TimerTimeoutCompValue;
uint16_t TimerTimeoutOverflow;
enum IDIBUS_SERIAL_REQUEST_TYPE RequestType;
volatile uint8_t TransferComplete;
uint16_t InitProtectionVar;
uint8_t InitState;
// Interrupt Vectors Pointers
virtual void USART_RxInterruptFunc(void) override;
virtual void USART_TxInterruptFunc(void) override;
virtual void TIM_COMPA_InterruptFunc(void) override;
virtual void TIM_COMPB_InterruptFunc(void) override;
// Routine
uint8_t BaseInit(enum IDIBUS_SERIAL_USARTN_NUMBER USART_NUM, enum IDIBUS_SERIAL_TIMER_NUMBER TIMER_NUM, enum IDIBUS_SERIAL_USARTN_CONFIG CONF);
uint8_t GetGpioParams(IDIBUS_SERIAL_GPIO_INIT *InitSTR, IDIBUS_SERIAL_GPIO *gpio);
uint8_t GetGpioParamsArduino(uint8_t PinNum, IDIBUS_SERIAL_GPIO *gpio);
void SetBaudrateLL(uint32_t Baudrate);
protected :
uint8_t *getTxBufPointer (void);
uint8_t *getRxBufPointer (void);
uint8_t SendRequestAsync(uint16_t DataLength);
uint8_t SendRequestSync(uint16_t DataLength);
uint8_t WriteAsync(uint16_t DataLength);
uint8_t WriteSync(uint16_t DataLength);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_SERIAL_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,138 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SERIAL_COMDEFS_H_
#define _IDIBUS_SERIAL_COMDEFS_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#if defined (__AVR_ATmega2560__)
#define USARTN_UCSRNA_RXC_Pos 7U
#define USARTN_UCSRNA_TXC_Pos 6U
#define USARTN_UCSRNA_UDR_Pos 5U
#define USARTN_UCSRNA_FE_Pos 4U
#define USARTN_UCSRNA_DOR_Pos 3U
#define USARTN_UCSRNA_UPE_Pos 2U
#define USARTN_UCSRNA_U2X_Pos 1U
#define USARTN_UCSRNA_MPCM_Pos 0U
#define USARTN_UCSRNB_RXCIE_Pos 7U
#define USARTN_UCSRNB_TXCIE_Pos 6U
#define USARTN_UCSRNB_UDRIE_Pos 5U
#define USARTN_UCSRNB_RXEN_Pos 4U
#define USARTN_UCSRNB_TXEN_Pos 3U
#define USARTN_UCSRNB_UCSZ2_Pos 2U
#define USARTN_UCSRNB_RXB8_Pos 1U
#define USARTN_UCSRNB_TXB8_Pos 0U
#define USARTN_UCSRNC_UMSEL1 7U
#define USARTN_UCSRNC_UMSEL0 6U
#define USARTN_UCSRNC_UPM1 5U
#define USARTN_UCSRNC_UPM0 4U
#define USARTN_UCSRNC_USBS 3U
#define USARTN_UCSRNC_UCSZ1 2U
#define USARTN_UCSRNC_UCSZ0 1U
#define USARTN_UCSRNC_UCPOL 0U
#define USARTN_TIM_TCCRA_WGMN1_Pos 1U
#define USARTN_TIM_TCCRB_PR1 1U
#define USARTN_TIM_TCCRB_PR8 2U
#define USARTN_TIM_TCCRB_PR64 3U
#define USARTN_TIM_TCCRB_PR256 4U
#define USARTN_TIM_TCCRB_PR1024 5U
#define USRTN_TIM_TIMSK_TOIE_Pos 0U
#define USRTN_TIM_TIMSK_OCIEA_Pos 1U
#define USRTN_TIM_TIMSK_OCIEB_Pos 2U
#define USRTN_TIM_TIMSK_OCIEC_Pos 3U
#define USARTN_TIM_TIFR_TOV_Pos 0U
#define USARTN_TIM_TIFR_OCFA_Pos 1U
#define USARTN_TIM_TIFR_OCFB_Pos 2U
#define USARTN_TIM_TIFR_OCFC_Pos 3U
#endif //#if defined (__AVR_ATmega2560__)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_BAUDRATE_DSW_CODE_19200B 0x00
#define IDIBUS_BAUDRATE_DSW_CODE_500K 0x01
#define IDIBUS_BAUDRATE_DSW_CODE_2400B 0x02
#define IDIBUS_BAUDRATE_DSW_CODE_9600B 0x03
#define IDIBUS_BAUDRATE_DSW_CODE_115200B 0x04
#define IDIBUS_BAUDRATE_DSW_CODE_250K 0x05
#define IDIBUS_BAUDRATE_DSW_CODE_1M 0x06
#define IDIBUS_BAUDRATE_DSW_CODE_10M 0x07
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_SERIAL_TIMER_PR_REG USARTN_TIM_TCCRB_PR64
#if IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR1
#define IDIBUS_SERIAL_TIMER_PR_VALUE 1U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR8
#define IDIBUS_SERIAL_TIMER_PR_VALUE 8U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR64
#define IDIBUS_SERIAL_TIMER_PR_VALUE 64U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR256
#define IDIBUS_SERIAL_TIMER_PR_VALUE 256U
#elif IDIBUS_SERIAL_TIMER_PR_REG == USARTN_TIM_TCCRB_PR1024
#define IDIBUS_SERIAL_TIMER_PR_VALUE 1024U
#else
#error "Idibus Serial: Incorrect Timer Prescaler value !"
#endif //#if IDIBUS_T_CPU==CPU_ATmega2560
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_SERIAL_TX_BUF_SIZE IDIMMES_MAX_MES_SIZE
#define IDIBUS_SERIAL_RX_BUF_SIZE IDISMES_MAX_MES_SIZE
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_SERIAL_REQUEST_TYPE {
_IDIBUS_SERIAL_TX_RX_,
_IDIBUS_SERIAL_TX_,
//Alarm
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
volatile uint8_t *UCSRNA;
volatile uint8_t *UCSRNB;
volatile uint8_t *UCSRNC;
volatile uint16_t *UBRRN;
volatile uint8_t *UDRN;
} IDIBUS_SERIAL_USART_HW_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
volatile uint8_t *TCCRNA;
volatile uint8_t *TCCRNB;
volatile uint8_t *TIMSKN;
volatile uint8_t *TIFRN;
volatile uint16_t *OCRNA;
volatile uint16_t *OCRNB;
volatile uint16_t *TCNTN;
} IDIBUS_SERIAL_USARTN_16BIT_TIMER;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef union {
uint8_t SumVar;
struct {
uint8_t TimeoutERR : 1;
uint8_t TxOverflow : 1;
uint8_t RxOverflow : 1;
uint8_t LLComERR : 1;
uint8_t TxZerolength : 1;
uint8_t Reserved : 3;
} BF;
} IDIBUS_SERIAL_ERROR_STATUS_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
uint8_t PIN_MASK;
volatile uint8_t *PORT;
volatile uint8_t *DDR;
volatile uint8_t *PIN;
} IDIBUS_SERIAL_GPIO;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
uint8_t PIN_NUM;
volatile uint8_t *PORT;
} IDIBUS_SERIAL_GPIO_INIT;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
typedef struct {
IDIBUS_SERIAL_GPIO S0_Gpio;
IDIBUS_SERIAL_GPIO S1_Gpio;
IDIBUS_SERIAL_GPIO S2_Gpio;
} IDIBUS_SERIAL_BAUDRATE_DIPSW_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_IDIBUS_SERIAL_COMDEFS_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,122 @@
//#############################################################################################################################################################################################################
#include "IdiBusSerialLine.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSerialLine::IdiBusSerialLine(void) : IdiBusSerial()
{
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerialLine::sendMMES (IdiBusMMES *MMES)
{
if ( MMES->IsValid() == 0 ) { return IDIERMST_INVALID_TX_REQUEST_FORMAT; }
uint8_t *TxMesBuf = this->getTxBufPointer();
if ( TxMesBuf == NULL ) { return IDIERMST_TX_MES; }
uint8_t *RxMesBuf = this->getRxBufPointer();
uint16_t DataPos;
// Fill Header
TxMesBuf[IDIMMES_ADDR_Pos] = MMES->SlAddr;
TxMesBuf[IDIMMES_MMPS_Pos] = (MMES->MMPS.LongMes << IDIMMES_MMPS_LONG_MES_Pos) |
(IDIMMES_MMPS_MES_TYPE_MMES << IDIMMES_MMPS_MES_TYPE_Pos) |
(0x00U << IDIMMES_MMPS_FAST_FUNC_Pos) |
(MMES->MMPS.AlarmMes << IDIMMES_MMPS_ALARM_FRAME_Pos) |
(MMES->MMPS.EncryptedAes << IDIMMES_MMPS_ENCRYPTED_AES_Pos);
TxMesBuf[IDIMMES_DEV_Pos] = (MMES->DEV.NUM << IDIMMES_DEV_NUM_Pos) | (MMES->DEV.ALLCH << IDIMMES_DEV_ALLCH_Pos);
TxMesBuf[IDIMMES_CHNL_Pos] = (MMES->CHNL.NUM << IDIMMES_CHNL_NUM_Pos) | (MMES->CHNL.ALLSAME << IDIMMES_CHNL_ALLSAME_Pos);
DataPos = IDIMMES_CHNL_Pos + 1;
// If Not Fast Function add command/function
if ( MMES->ComFunc < 16 ) { TxMesBuf[IDIMMES_MMPS_Pos] |= (MMES->ComFunc << IDIMMES_MMPS_FAST_FUNC_Pos); }
else { TxMesBuf[DataPos++] = MMES->ComFunc; }
// Fill Data
if ( MMES->TxDataLength != 0 ) { memcpy(&TxMesBuf[DataPos], &MMES->TxData[0], MMES->TxDataLength); }
// Add CRC
uint16_t CRC = MODBUS_CRC16::CRC16_TF(&TxMesBuf[0], (uint16_t)(DataPos + MMES->TxDataLength));
TxMesBuf[DataPos + MMES->TxDataLength] = (uint8_t)(CRC >> 8);
TxMesBuf[DataPos + MMES->TxDataLength + 1] = (uint8_t) CRC;
if ( this->SendRequestSync(DataPos + MMES->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
IDIBUS_SERIAL_ERROR_STATUS_TYPE SerialError = this->GetErrorStatus();
uint16_t RxMessageLength;
if ( SerialError.BF.TimeoutERR != 0 ) { return IDIERMST_RCV_TIMEOUT; }
else if ( (SerialError.SumVar != 0) || ((RxMessageLength = this->GetRxBufCounter()) < IDISMES_MIN_MES_SIZE) ) { return IDIERMST_MES_RX_INTEGRITY; }
else
{
uint16_t CRC = MODBUS_CRC16::CRC16_TF( &RxMesBuf[0], (uint16_t)(RxMessageLength-MODBUS_CRC16_SIZE) );
uint16_t ReceivedCRC = ((uint16_t)RxMesBuf[RxMessageLength-2] << 8) | RxMesBuf[RxMessageLength-1];
if ( CRC != ReceivedCRC ) { return IDIERMST_CRC; }
else if ( RxMesBuf[IDISMES_ADDR_Pos] != MMES->SlAddr ) { return IDIERMST_INVALID_ADDR_NUM; }
else
{
MMES->RxDataLength = RxMessageLength - (IDISMES_ERROR_Pos + MODBUS_CRC16_SIZE);
MMES->RxData = &RxMesBuf[IDISMES_ERROR_Pos];
return IDIER_NOPE;
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSerialLine::sendMMESG (IdiBusMMESG *MMESG)
{
if ( MMESG->IsValid() == 0 ) { return IDIERMST_INVALID_TX_REQUEST_FORMAT ; }
uint8_t *TxMesBuf = this->getTxBufPointer();
if ( TxMesBuf == NULL ) { return IDIERMST_TX_MES; }
uint8_t *RxMesBuf = this->getRxBufPointer();
uint16_t DataPos;
// Fill Header
TxMesBuf[IDIMMES_ADDR_Pos] = MMESG->SlAddr;
TxMesBuf[IDIMMES_MMPS_Pos] = (MMESG->MMPS.LongMes << IDIMMES_MMPS_LONG_MES_Pos) |
(IDIMMES_MMPS_MES_TYPE_MMESG << IDIMMES_MMPS_MES_TYPE_Pos) |
(0x00 << IDIMMES_MMPS_FAST_FUNC_Pos) |
(MMESG->MMPS.AlarmMes << IDIMMES_MMPS_ALARM_FRAME_Pos) |
(MMESG->MMPS.EncryptedAes << IDIMMES_MMPS_ENCRYPTED_AES_Pos);
DataPos = IDIMMES_MMPS_Pos + 1;
// If Not Fast Function add command/function
if ( MMESG->ComFunc < 16 ) { TxMesBuf[IDIMMES_MMPS_Pos] |= (MMESG->ComFunc << IDIMMES_MMPS_FAST_FUNC_Pos); }
else { TxMesBuf[DataPos++] = MMESG->ComFunc; }
// Fill Data
if ( MMESG->TxDataLength != 0 ) { memcpy(&TxMesBuf[DataPos], &MMESG->TxData[0], MMESG->TxDataLength); }
// Add CRC
uint16_t CRC = MODBUS_CRC16::CRC16_TF(&TxMesBuf[0], (uint16_t)(DataPos + MMESG->TxDataLength));
TxMesBuf[DataPos + MMESG->TxDataLength] = (uint8_t)(CRC >> 8);
TxMesBuf[DataPos + MMESG->TxDataLength + 1] = (uint8_t) CRC;
if ( MMESG->IsGroupAddr() != 0 )
{
if ( this->WriteSync(DataPos + MMESG->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
return IDIER_NOPE;
}
else //Module commands
{
if ( this->SendRequestSync(DataPos + MMESG->TxDataLength + MODBUS_CRC16_SIZE) == 0 ) { return IDIERMST_TX_MES; }
uint16_t RxMessageLength;
IDIBUS_SERIAL_ERROR_STATUS_TYPE SerialError = this->GetErrorStatus();
if ( SerialError.BF.TimeoutERR != 0 ) { return IDIERMST_RCV_TIMEOUT; }
else if ( (SerialError.SumVar != 0) || ((RxMessageLength = this->GetRxBufCounter()) < IDISMES_MIN_MES_SIZE) ) { return IDIERMST_TX_MES; }
else
{
uint16_t CRC = MODBUS_CRC16::CRC16_TF( &RxMesBuf[0], (uint16_t)(RxMessageLength-MODBUS_CRC16_SIZE) );
uint16_t ReceivedCRC = ((uint16_t)RxMesBuf[RxMessageLength-2] << 8) | RxMesBuf[RxMessageLength-1];
if ( CRC != ReceivedCRC ) { return IDIERMST_CRC; }
else if ( RxMesBuf[IDISMES_ADDR_Pos] != MMESG->SlAddr ) { return IDIERMST_INVALID_ADDR_NUM; }
{
MMESG->RxDataLength = RxMessageLength - (IDISMES_ERROR_Pos + MODBUS_CRC16_SIZE);
MMESG->RxData = &RxMesBuf[IDISMES_ERROR_Pos];
return IDIER_NOPE;
}
}
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,17 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_STD_LINE_H_
#define _IDIBUS_STD_LINE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusSerial.h"
#include "IdiBusMes.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusSerialLine : public IdiBusSerial {
public :
IdiBusSerialLine();
uint8_t sendMMES (IdiBusMMES *MMES); // return ErrorCode but not look into [data]
uint8_t sendMMESG (IdiBusMMESG *MMESG);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_STD_LINE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,351 @@
//#############################################################################################################################################################################################################
#include "IdiBusSlave.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSlave::IdiBusSlave( IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress )
{
this->Line = SlaveLine;
this->Address = SlaveAddress;
this->CRC_AVR.CRC_ErrAvrBufCounter = 0;
this->CRC_AVR.CRC_ErrAvrBufPos = 0;
this->CRC_AVR.CRC_ErrAvrBufSum = 0;
this->CRC_MultipleError = 0;
this->ModuleError = IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusSlave::IdiBusSlave(void)
{
this->Line = NULL;
this->Address = 1;
this->CRC_AVR.CRC_ErrAvrBufCounter = 0;
this->CRC_AVR.CRC_ErrAvrBufPos = 0;
this->CRC_AVR.CRC_ErrAvrBufSum = 0;
this->CRC_MultipleError = 0;
this->ModuleError = IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::Init(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress)
{
this->Line = SlaveLine;
this->Address = SlaveAddress;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::SendRequestMMES(IdiBusMMES *MMES)
{
if ( this->Line == NULL ) { return IDIERMST_TX_MES; }
uint8_t RequestError = this->Line->sendMMES(MMES);
this->CrcAvrErrorCalc(RequestError);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMES->IsModuleError(MMES->RxData[0]) )
{
if ( MMES->RxDataLength != 1 ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { this->ModuleError = MMES->RxData[0]; return MMES->RxData[0]; }
}
this->ModuleError = IDIER_NOPE;
return IDIER_NOPE;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::SendRequestMMESG(IdiBusMMESG *MMESG)
{
if ( this->Line == NULL ) { return IDIERMST_TX_MES; }
uint8_t RequestError = this->Line->sendMMESG(MMESG);
this->CrcAvrErrorCalc(RequestError);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG->IsGroupAddr() == 0 )
{
if ( MMESG->IsModuleError(MMESG->RxData[0]) )
{
if ( MMESG->RxDataLength != 1 ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { this->ModuleError = MMESG->RxData[0]; return MMESG->RxData[0]; }
}
}
this->ModuleError = IDIER_NOPE;
return IDIER_NOPE;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::SendModuleSimpleSetCommand(uint8_t Command)
{
IdiBusMMESG MMESG(this->Address);
MMESG.ComFunc = Command;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if (MMESG.RxDataLength != 1) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { return MMESG.RxData[0]; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::SendModuleSimpleSetCommand(uint8_t Command, uint8_t *TxData, uint16_t TxDataLength)
{
IdiBusMMESG MMESG(this->Address, TxData, TxDataLength);
MMESG.ComFunc = Command;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if (MMESG.RxDataLength != 1) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { return MMESG.RxData[0]; }
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::CrcAvrErrorCalc(uint8_t ErrorCode)
{
uint8_t ErrorBufCode;
if ( ErrorCode == IDIERMST_CRC ) { ErrorBufCode = 1; }
else { ErrorBufCode = 0; }
this->CRC_AVR.CRC_ErrAvrBufSum = this->CRC_AVR.CRC_ErrAvrBufSum + ErrorBufCode - this->CRC_AVR.CRC_ErrAvrBuf[this->CRC_AVR.CRC_ErrAvrBufPos];
this->CRC_AVR.CRC_ErrAvrBuf[this->CRC_AVR.CRC_ErrAvrBufPos] = ErrorBufCode;
if ( this->CRC_AVR.CRC_ErrAvrBufPos == (IDIER_MULTIPLE_CRC_AVRBUF_SIZE - 1) ) { this->CRC_AVR.CRC_ErrAvrBufPos = 0; }
else { this->CRC_AVR.CRC_ErrAvrBufPos++; }
if ( this->CRC_AVR.CRC_ErrAvrBufCounter < IDIER_MULTIPLE_CRC_AVRBUF_SIZE ) { this->CRC_AVR.CRC_ErrAvrBufCounter++; }
else
{
if ( this->CRC_AVR.CRC_ErrAvrBufSum >= IDIER_MULTIPLE_CRC_AVRBUF_THR ) { this->CRC_MultipleError = 1; }
else { this->CRC_MultipleError = 0; }
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_Init(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Init); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Init(uint8_t Group) { return (Group > IDIBUS_GROUP_LAST_NUMBER) ? IDIERMST_INVALID_TX_PARAM : this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Init, &Group, 1); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_ShtDown(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_ShtDown); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Freeze(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Freeze); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_Resume(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_Resume); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_DummyModule(void) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_DummyModule); }
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_SendTimeDate(IdiTimeFormat Time, IdiDateFormat Date)
{
if ( (Time.isValid() == 0) || (Date.isValid() == 0) ) { return IDIERMST_INVALID_TX_PARAM; }
uint8_t TxData[IDIMMES_C_DATETIME_LENGTH];
Time.getBufForMMES(&TxData[IDIMMES_C_DATETIME_TIME_Pos]);
Date.getBufForMMES(&TxData[IDIMMES_C_DATETIME_DATE_Pos]);
return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_SendTimeDate, TxData, IDIMMES_C_DATETIME_LENGTH );
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_ReadDevFullSN_MS(void)
{
IdiBusMMESG MMESG (this->Address);
MMESG.ComFunc = IDIMMES_COM_C_ReadDevFullSN_MS;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG.RxDataLength != (IDISN_FULL_LENGTH - IDISN_VARP_AES256_Length + 2 + 1) ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMESG.RxData[0] != IDIER_NOPE ) { return MMESG.RxData[0]; }
else
{
this->ModuleST.parseSmesDataNoAes(&MMESG.RxData[1]);
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnIPv4IPv6(uint32_t IPv4, uint32_t IPv6_B3, uint32_t IPv6_B2, uint32_t IPv6_B1, uint32_t IPv6_B0)
{
uint8_t TxData[IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length];
TxData[0] = (uint8_t)(IPv4 >> 24);
TxData[1] = (uint8_t)(IPv4 >> 16);
TxData[2] = (uint8_t)(IPv4 >> 8);
TxData[3] = (uint8_t)(IPv4);
TxData[4] = (uint8_t)(IPv6_B3 >> 24);
TxData[5] = (uint8_t)(IPv6_B3 >> 16);
TxData[6] = (uint8_t)(IPv6_B3 >> 8);
TxData[7] = (uint8_t)(IPv6_B3);
TxData[8] = (uint8_t)(IPv6_B2 >> 24);
TxData[9] = (uint8_t)(IPv6_B2 >> 16);
TxData[10] = (uint8_t)(IPv6_B2 >> 8);
TxData[11] = (uint8_t)(IPv6_B2);
TxData[12] = (uint8_t)(IPv6_B1 >> 24);
TxData[13] = (uint8_t)(IPv6_B1 >> 16);
TxData[14] = (uint8_t)(IPv6_B1 >> 8);
TxData[15] = (uint8_t)(IPv6_B1);
TxData[16] = (uint8_t)(IPv6_B0 >> 24);
TxData[17] = (uint8_t)(IPv6_B0 >> 16);
TxData[18] = (uint8_t)(IPv6_B0 >> 8);
TxData[19] = (uint8_t)(IPv6_B0);
uint8_t RequestError = this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnIPv4IPv6, TxData, IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length );
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else
{
memcpy(this->ModuleST.SN.VAR.IPv4, &TxData[0], IDISN_VARP_IPv4_Length);
memcpy(this->ModuleST.SN.VAR.IPv6, &TxData[4], IDISN_VARP_IPv6_Length);
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnVerifyDates(IdiDateFormat VDate, IdiDateFormat VEXPDate)
{
if ( (VDate.isValid() == 0) || (VEXPDate.isValid() == 0) ) { return IDIERMST_INVALID_TX_PARAM; }
uint8_t TxData[IDIDATE_FORMAT_LENGTH * 2];
VDate.getBufForMMES(&TxData[0]);
VEXPDate.getBufForMMES(&TxData[IDIDATE_FORMAT_LENGTH]);
uint8_t RequestError = this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnVerifyDates, TxData, IDIDATE_FORMAT_LENGTH * 2 );
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else
{
this->ModuleST.SN.VAR.VerifDate = VDate;
this->ModuleST.SN.VAR.VerifExpDate = VEXPDate;
return IDIER_NOPE;
}
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_WriteSnAES256(uint8_t *AES256_key) { return this->SendModuleSimpleSetCommand(IDIMMES_COM_C_WriteSnAES256, AES256_key, IDISN_VARP_AES256_Length); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_CheckModuleLongOp(void)
{
IdiBusMMESG MMESG (this->Address);
MMESG.ComFunc = IDIMMES_COM_C_CheckModuleLongOp;
uint8_t RequestError = this->SendRequestMMESG(&MMESG);
if ( RequestError != IDIER_NOPE ) { return RequestError; }
else if ( MMESG.RxDataLength != (IDILONGOP_MES_DATA_LENGTH + 1) ) { return IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMESG.RxData[0] != IDIER_NOPE ) { return MMESG.RxData[0]; }
else
{
uint8_t DataPos = 1;
this->ModuleLongOpData.State = MMESG.RxData[DataPos + IDILONGOP_STATE_Pos];
this->ModuleLongOpData.Timeout = ((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 0] << 24) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 1] << 16) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 2] << 8 ) |
((uint32_t)MMESG.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 3] );
return IDIER_NOPE;
}
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::c_Dummy(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.ComFunc = IDIMMES_COM_C_Dummy;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { CHNL->MMES_Error = MMES.RxData[0]; }
return CHNL->MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_AssignGroup(uint8_t Device, uint8_t Channel, uint8_t Group)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
if ( Group > IDIBUS_GROUP_LAST_NUMBER ) { CHNL->MMES_Error = IDIERMST_INVALID_TX_PARAM; }
else
{
IdiBusMMES MMES(this->Address, &Group, 1);
MMES.ComFunc = IDIMMES_COM_C_AssignGroup;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else { CHNL->MMES_Error = MMES.RxData[0]; }
}
return CHNL->MMES_Error;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint8_t IdiBusSlave::c_CheckChannelLongOp(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( (DEV = this->getDevice(Device)) == NULL ) { return IDIERMST_INVALID_DEV_NUM; }
if ( (CHNL = DEV->getChannel(Channel)) == NULL ) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.ComFunc = IDIMMES_COM_C_CheckChannelLongOp;
MMES.DEV.NUM = Device;
MMES.CHNL.NUM = Channel;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { CHNL->MMES_Error = RequestError; }
else if ( MMES.RxDataLength != (IDILONGOP_MES_DATA_LENGTH + 1) ) { CHNL->MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else if ( MMES.RxData[0] != IDIER_NOPE ) { CHNL->MMES_Error = MMES.RxData[0]; }
else
{
CHNL->MMES_Error = IDIER_NOPE;
uint8_t DataPos = 1;
CHNL->LONG_OP.State = MMES.RxData[DataPos + IDILONGOP_STATE_Pos];
CHNL->LONG_OP.Timeout = ((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 0] << 24) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 1] << 16) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 2] << 8 ) |
((uint32_t)MMES.RxData[DataPos + IDILONGOP_REMAIN_TIME_Pos + 3] );
}
return CHNL->MMES_Error;
}
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
uint8_t IdiBusSlave::getAddress(void) { return this->Address; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void IdiBusSlave::setAes256ToSn(uint8_t *AES256_key) { memcpy(this->ModuleST.SN.VAR.AES, AES256_key, IDISN_VARP_AES256_Length); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusLongOpData IdiBusSlave::getModuleLongOpData(void) { return this->ModuleLongOpData; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiBusLongOpData IdiBusSlave::getChLongOpData(uint8_t Device, uint8_t Channel)
{
IdiBusDevice *DEV;
IdiBusChannel *CHNL;
if ( ((DEV = this->getDevice(Device)) != NULL) && ((CHNL = DEV->getChannel(Channel)) != NULL) )
{
return CHNL->LONG_OP;
}
IdiBusLongOpData NewData;
return NewData;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IdiMasterState IdiBusSlave::getModuleSN(void) { return this->ModuleST; }
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
void IdiMasterState::parseSmesDataNoAes(uint8_t *Data)
{
this->STATE.B0S.StError = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_ST_ERROR_Pos) & 0x01;
this->STATE.B0S.StState = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_ST_STATE_Pos) & IDISTATUS_B0S_ST_STATE_Msk;
this->STATE.B0S.AesSupported = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_AES_SUPPORTED_Pos) & 0x01;
this->STATE.B0S.AesInstalled = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_AES_INSTALLED_Pos) & 0x01;
this->STATE.B0S.SendAlarmL0 = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_SEND_ALARM_L0_Pos) & 0x01;
this->STATE.B0S.SendAlarmL1 = (Data[IDISTATUS_B0S_Pos] >> IDISTATUS_B0S_SEND_ALARM_L1_Pos) & 0x01;
this->STATE.B1S.ModuleType = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_MODULE_TYPE_Pos) & IDISTATUS_B1S_MODULE_TYPE_Msk;
this->STATE.B1S.BridgeConnected = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_BRIDGE_CONNECTED_Pos) & 0x01;
this->STATE.B1S.SelfInit = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_SELF_INIT_Pos) & 0x01;
this->STATE.B1S.TimeoutLed = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_TIMEOUT_LED_Pos) & 0x01;
this->STATE.B1S.NoMMESTimeout = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_NO_MMES_TIMEOUT_Pos) & 0x01;
this->STATE.B1S.CatchAlarmL0 = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_CATCH_ALARM_L0_Pos) & 0x01;
this->STATE.B1S.CatchAlarmL1 = (Data[IDISTATUS_B1S_Pos] >> IDISTATUS_B1S_CATCH_ALARM_L1_Pos) & 0x01;
memcpy(this->SN.FIX.GS1_country, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_GS1_COUNTRY_Pos], IDISN_FIXP_GS1_COUNTRY_Length);
memcpy(this->SN.FIX.GS1_company, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_GS1_COMPANY_Pos], IDISN_FIXP_GS1_COMPANY_Length);
memcpy(this->SN.FIX.ModuleType, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_MODULE_TYPE_Pos], IDISN_FIXP_MODULE_TYPE_Length);
memcpy(this->SN.FIX.HW_rev, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_HW_REV_Pos], IDISN_FIXP_HW_REV_Length);
memcpy(this->SN.FIX.Serial, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_SERIAL_Pos], IDISN_FIXP_SERIAL_Length);
memcpy(this->SN.FIX.MAC, &Data[IDISTATUS_SN_Pos + IDISN_FIXP_MAC_Pos], IDISN_FIXP_MAC_Length);
memcpy(this->SN.VAR.SW_rev, &Data[IDISTATUS_SN_Pos + IDISN_VARP_SW_REV_Pos], IDISN_VARP_SW_REV_Length);
memcpy(this->SN.VAR.IPv4, &Data[IDISTATUS_SN_Pos + IDISN_VARP_IPv4_Pos], IDISN_VARP_IPv4_Length);
memcpy(this->SN.VAR.IPv6, &Data[IDISTATUS_SN_Pos + IDISN_VARP_IPv6_Pos], IDISN_VARP_IPv6_Length);
uint8_t *VerifDateP = &Data[IDISTATUS_SN_Pos + IDISN_VARP_VERIF_DATE_Pos];
uint8_t *VerifExpDateP = &Data[IDISTATUS_SN_Pos + IDISN_VARP_EXPIR_DATE_Pos];
IdiDateFormat verifDate(VerifDateP[0], VerifDateP[1], VerifDateP[2], VerifDateP[3]);
IdiDateFormat verifExpDate(VerifExpDateP[0], VerifExpDateP[1], VerifExpDateP[2], VerifExpDateP[3]);
this->SN.VAR.VerifDate = verifDate;
this->SN.VAR.VerifExpDate = verifExpDate;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//#############################################################################################################################################################################################################

@ -0,0 +1,122 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SLAVE_H_
#define _IDIBUS_SLAVE_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "IdiBusSystem.h"
#include "IdiBusDateTime.h"
#include "IdiBusMes.h"
#include "IdiBusSerialLine.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiMasterState {
public :
IDISTATUS_STATE_TYPE STATE;
struct {
struct {
uint8_t GS1_country[3];
uint8_t GS1_company[6];
uint8_t ModuleType[3];
uint8_t HW_rev[2];
uint8_t Serial[7];
uint8_t MAC[6];
} FIX;
struct VAR {
VAR() : VerifDate(0,0,0,0), VerifExpDate(0,0,0,0) {}
uint8_t SW_rev[2];
IdiDateFormat VerifDate;
IdiDateFormat VerifExpDate;
uint8_t IPv4[4];
uint8_t IPv6[16];
uint8_t AES[32];
} VAR;
} SN;
void parseSmesDataNoAes(uint8_t *Data);
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBusLongOpData {
public :
IdiBusLongOpData() { this->State = IDILONGOP_STATE_COMPLETE_NO_ERR; this->Timeout = 0; }
uint8_t State;
uint32_t Timeout;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusChannel {
public :
IdiBusChannel() { this->MMES_Error = IDIER_NOPE; }
IdiBusLongOpData LONG_OP;
uint8_t MMES_Error;
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class IdiBusDevice {
public :
IdiBusDevice (void *ParentModule) { this->Module = ParentModule; }
virtual IdiBusChannel *getChannel(uint8_t Num) { return NULL; }
protected :
void *Module;
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
class IdiBusSlave {
public :
// Constructors and init
IdiBusSlave(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress);
IdiBusSlave(void);
void Init(IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress);
// Standard communication API
uint8_t SendRequestMMES(IdiBusMMES *MMES);
uint8_t SendRequestMMESG(IdiBusMMESG *MMESG);
//Module commands (return ErrorCode)
uint8_t c_Init (void);
uint8_t c_Init (uint8_t Gpoup);
uint8_t c_ShtDown (void);
uint8_t c_Freeze (void);
uint8_t c_Resume (void);
uint8_t c_ReadDevFullSN_MS(void);
uint8_t c_WriteSnIPv4IPv6(uint32_t IPv4, uint32_t IPv6_B3, uint32_t IPv6_B2, uint32_t IPv6_B1, uint32_t IPv6_B0);
uint8_t c_WriteSnVerifyDates(IdiDateFormat VDate, IdiDateFormat VEXPDate);
uint8_t c_WriteSnAES256(uint8_t *AES256_key);
uint8_t c_SendTimeDate(IdiTimeFormat Time, IdiDateFormat Date);
uint8_t c_DummyModule(void);
uint8_t c_CheckModuleLongOp(void);
// Channel Commands
uint8_t c_Dummy(uint8_t Device, uint8_t Channel);
uint8_t c_AssignGroup(uint8_t Device, uint8_t Channel, uint8_t Group);
uint8_t c_CheckChannelLongOp(uint8_t Device, uint8_t Channel);
// Utils
uint8_t getAddress(void);
void setAes256ToSn(uint8_t *AES256_key);
IdiBusLongOpData getModuleLongOpData(void);
IdiBusLongOpData getChLongOpData(uint8_t Device, uint8_t Channel);
IdiMasterState getModuleSN(void);
// Interface - must be overridden in derived classes
virtual IdiBusDevice *getDevice(uint8_t Num) { return NULL; }
protected :
IdiBusSerialLine *Line;
uint8_t Address;
IdiMasterState ModuleST;
uint8_t ModuleError;
IdiBusLongOpData ModuleLongOpData;
uint8_t CRC_MultipleError;
struct {
uint8_t CRC_ErrAvrBuf[16];
uint8_t CRC_ErrAvrBufCounter;
uint8_t CRC_ErrAvrBufPos;
uint8_t CRC_ErrAvrBufSum;
} CRC_AVR;
uint8_t SendModuleSimpleSetCommand(uint8_t Command);
uint8_t SendModuleSimpleSetCommand(uint8_t Command, uint8_t *TxData, uint16_t TxDataLength);
void CrcAvrErrorCalc(uint8_t ErrorCode);
};
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _IDIBUS_SLAVE_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,25 @@
//#############################################################################################################################################################################################################
#ifndef _IDIBUS_SYSTEM_H_
#define _IDIBUS_SYSTEM_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "Arduino.h"
#include "pins_arduino.h"
#include <inttypes.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "IdiBusDefs.h"
#include "MODBUS_CRC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#ifndef F_CPU
#error "IdibusSerial: F_CPU not defined!"
#endif
#if defined __AVR_ATmega2560__
#else
#error "IdibusSerial: Unsupported ControllerType!"
#endif
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#ifndef _IDIBUS_SYSTEM_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,446 @@
//#############################################################################################################################################################################################################
#ifndef _INC_IDIBUS_DEFS_H_
#define _INC_IDIBUS_DEFS_H_
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <inttypes.h>
#include "MODBUS_CRC.h"
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_BAUDRATE_DSW_CODE_19200B 0x00
#define IDIBUS_BAUDRATE_DSW_CODE_500K 0x01
#define IDIBUS_BAUDRATE_DSW_CODE_2400B 0x02
#define IDIBUS_BAUDRATE_DSW_CODE_9600B 0x03
#define IDIBUS_BAUDRATE_DSW_CODE_115200B 0x04
#define IDIBUS_BAUDRATE_DSW_CODE_250K 0x05
#define IDIBUS_BAUDRATE_DSW_CODE_1M 0x06
#define IDIBUS_BAUDRATE_DSW_CODE_10M 0x07
// Full timeout will be (InterframeTimeout + ResponseTimeout) for request(Write + Read) or InterframeTimeout for write(Write only)
#define IDIBUS_2400B_INTERFRAME_TIMEOUT_US 16042ULL //11 * 3.5 / Baudrate
#define IDIBUS_9600B_INTERFRAME_TIMEOUT_US 4011ULL
#define IDIBUS_19200B_INTERFRAME_TIMEOUT_US 2006ULL
#define IDIBUS_115200B_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_250K_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_500K_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_1M_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_10M_INTERFRAME_TIMEOUT_US 1750ULL
#define IDIBUS_2400B_ALARM_TIMEOUT_US 34375ULL //11 * 3.5 / Baudrate
#define IDIBUS_9600B_ALARM_TIMEOUT_US 8594ULL
#define IDIBUS_19200B_ALARM_TIMEOUT_US 4297ULL
#define IDIBUS_115200B_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_250K_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_500K_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_1M_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_10M_ALARM_TIMEOUT_US 1750ULL
#define IDIBUS_2400B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_2400B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_9600B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_9600B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_19200B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_19200B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_115200B_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_115200B_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_250K_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_250K_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_500K_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_500K_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_1M_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_1M_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_10M_MASTER_RESPONSE_TIMEOUT_US (IDIBUS_10M_INTERFRAME_TIMEOUT_US * 3 / 2 )
#define IDIBUS_2400B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_2400B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_9600B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_9600B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_19200B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_19200B_INTERFRAME_TIMEOUT_US )
#define IDIBUS_115200B_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_115200B_INTERFRAME_TIMEOUT_US)
#define IDIBUS_250K_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_250K_INTERFRAME_TIMEOUT_US )
#define IDIBUS_500K_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_500K_INTERFRAME_TIMEOUT_US )
#define IDIBUS_1M_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_1M_INTERFRAME_TIMEOUT_US )
#define IDIBUS_10M_SLAVE_RESPONSE_TIMEOUT_US (IDIBUS_10M_INTERFRAME_TIMEOUT_US )
enum IDIBUS_SERIAL_BAUDRATE {
IDIBUS_BAUDRATE_2400 = IDIBUS_BAUDRATE_DSW_CODE_2400B,
IDIBUS_BAUDRATE_9600 = IDIBUS_BAUDRATE_DSW_CODE_9600B,
IDIBUS_BAUDRATE_19200 = IDIBUS_BAUDRATE_DSW_CODE_19200B,
IDIBUS_BAUDRATE_115200 = IDIBUS_BAUDRATE_DSW_CODE_115200B,
IDIBUS_BAUDRATE_250K = IDIBUS_BAUDRATE_DSW_CODE_250K,
IDIBUS_BAUDRATE_500K = IDIBUS_BAUDRATE_DSW_CODE_500K,
IDIBUS_BAUDRATE_1M = IDIBUS_BAUDRATE_DSW_CODE_1M,
IDIBUS_BAUDRATE_10M = IDIBUS_BAUDRATE_DSW_CODE_10M
};
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_SEC 60U
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_MS ( IDIBUS_LINK_LED_NO_MMES_TIMEOUT_0_SEC * 1000U )
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_SEC 15U
#define IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_MS ( IDIBUS_LINK_LED_NO_MMES_TIMEOUT_1_SEC * 1000U )
enum IDIBUS_RXTIMER_TIMEOUT_MODE {
IDIBUS_TIMER_MODE_RX_TIMEOUT = 0x00,
IDIBUS_TIMER_MODE_ALARM_TIMEOUT,
IDIBUS_TIMER_MODE_RESPONSE_TIMEOUT
};
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISN_FIXP_Pos 0U
#define IDISN_FIXP_GS1_COUNTRY_Pos ( IDISN_FIXP_Pos + 0U)
#define IDISN_FIXP_GS1_COUNTRY_Length 3
#define IDISN_FIXP_GS1_COMPANY_Pos ( IDISN_FIXP_GS1_COUNTRY_Pos + IDISN_FIXP_GS1_COUNTRY_Length )
#define IDISN_FIXP_GS1_COMPANY_Length 6
#define IDISN_FIXP_MODULE_TYPE_Pos ( IDISN_FIXP_GS1_COMPANY_Pos + IDISN_FIXP_GS1_COMPANY_Length )
#define IDISN_FIXP_MODULE_TYPE_Length 3
#define IDISN_FIXP_HW_REV_Pos ( IDISN_FIXP_MODULE_TYPE_Pos + IDISN_FIXP_MODULE_TYPE_Length )
#define IDISN_FIXP_HW_REV_Length 2
#define IDISN_FIXP_SERIAL_Pos ( IDISN_FIXP_HW_REV_Pos + IDISN_FIXP_HW_REV_Length )
#define IDISN_FIXP_SERIAL_Length 7
#define IDISN_FIXP_MAC_Pos ( IDISN_FIXP_SERIAL_Pos + IDISN_FIXP_SERIAL_Length )
#define IDISN_FIXP_MAC_Length 6
#define IDISN_FIXP_LENGTH ( IDISN_FIXP_GS1_COUNTRY_Length + IDISN_FIXP_GS1_COMPANY_Length + IDISN_FIXP_MODULE_TYPE_Length + \
IDISN_FIXP_HW_REV_Length + IDISN_FIXP_SERIAL_Length + IDISN_FIXP_MAC_Length )
#define IDISN_VARP_Pos IDISN_FIXP_LENGTH
#define IDISN_VARP_SW_REV_Pos ( IDISN_VARP_Pos + 0U )
#define IDISN_VARP_SW_REV_Length 2U
#define IDISN_VARP_VERIF_DATE_Pos ( IDISN_VARP_SW_REV_Pos + IDISN_VARP_SW_REV_Length )
#define IDISN_VARP_VERIF_DATE_Length 4U
#define IDISN_VARP_EXPIR_DATE_Pos ( IDISN_VARP_VERIF_DATE_Pos + IDISN_VARP_VERIF_DATE_Length )
#define IDISN_VARP_EXPIR_DATE_Length 4U
#define IDISN_VARP_IPv4_Pos ( IDISN_VARP_EXPIR_DATE_Pos + IDISN_VARP_EXPIR_DATE_Length )
#define IDISN_VARP_IPv4_Length 4U
#define IDISN_VARP_IPv6_Pos ( IDISN_VARP_IPv4_Pos + IDISN_VARP_IPv4_Length )
#define IDISN_VARP_IPv6_Length 16U
#define IDISN_VARP_AES256_Pos ( IDISN_VARP_IPv6_Pos + IDISN_VARP_IPv6_Length )
#define IDISN_VARP_AES256_Length 32U
#define IDISN_VARP_LENGTH ( IDISN_VARP_SW_REV_Length + IDISN_VARP_VERIF_DATE_Length + IDISN_VARP_EXPIR_DATE_Length + \
IDISN_VARP_IPv4_Length + IDISN_VARP_IPv6_Length + IDISN_VARP_AES256_Length )
#define IDISN_FULL_LENGTH ( IDISN_FIXP_LENGTH + IDISN_VARP_LENGTH )
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define ISIBUS_MASTER_MAIN_ADDR 255U
#define ISIBUS_MASTER_SPARE_ADDR 254U
#define IDIBUS_SLAVE_ADDR_MIN 1U
#define IDIBUS_SLAVE_ADDR_MAX 229U
#define IDIBUS_DEVELOPER_ADDR_0 250U
#define IDIBUS_DEVELOPER_ADDR_1 251U
#define IDIBUS_DEVELOPER_ADDR_2 252U
#define IDIBUS_DEVELOPER_ADDR_3 253U
#define IDIBUS_GROUP_0_ADDR 230U
#define IDIBUS_GROUP_1_ADDR 231U
#define IDIBUS_GROUP_2_ADDR 232U
#define IDIBUS_GROUP_3_ADDR 233U
#define IDIBUS_GROUP_4_ADDR 234U
#define IDIBUS_GROUP_5_ADDR 235U
#define IDIBUS_GROUP_6_ADDR 236U
#define IDIBUS_GROUP_7_ADDR 237U
#define IDIBUS_GROUP_8_ADDR 238U
#define IDIBUS_GROUP_9_ADDR 239U
#define IDIBUS_GROUP_10_ADDR 240U
#define IDIBUS_GROUP_11_ADDR 241U
#define IDIBUS_GROUP_12_ADDR 242U
#define IDIBUS_GROUP_13_ADDR 243U
#define IDIBUS_GROUP_14_ADDR 244U
#define IDIBUS_GROUP_15_ADDR 245U
#define IDIBUS_GROUPS_NUMBER 16U
#define IDIBUS_GROUP_FIRST_NUMBER 0U
#define IDIBUS_GROUP_LAST_NUMBER 15U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIMMES_ADDR_Pos 00U
#define IDIMMES_MMPS_Pos 01U
#define IDIMMES_MMPS_LONG_MES_Pos 0U
#define IDIMMES_MMPS_LONG_MES_Msk 0x01U
#define IDIMMES_MMPS_MES_TYPE_Pos 1U
#define IDIMMES_MMPS_MES_TYPE_Msk 0x02U
#define IDIMMES_MMPS_MES_TYPE_MMES 0x00U
#define IDIMMES_MMPS_MES_TYPE_MMESG 0x01U
#define IDIMMES_MMPS_FAST_FUNC_Pos 2U
#define IDIMMES_MMPS_FAST_FUNC_Msk 0x3CU
#define IDIMMES_MMPS_ALARM_FRAME_Pos 6U
#define IDIMMES_MMPS_ALARM_FRAME_Msk 0x40U
#define IDIMMES_MMPS_ENCRYPTED_AES_Pos 7U
#define IDIMMES_MMPS_ENCRYPTED_AES_Msk 0x80U
#define IDIMMES_DEV_Pos 02U
#define IDIMMES_DEV_NUM_Pos 0U
#define IDIMMES_DEV_NUM_Msk 0x1FU
#define IDIMMES_DEV_ALLCH_Pos 5U
#define IDIMMES_DEV_ALLCH_Msk 0x20U
#define IDIMMES_CHNL_Pos 03U
#define IDIMMES_CHNL_NUM_Pos 0U
#define IDIMMES_CHNL_NUM_Msk 0x7FU
#define IDIMMES_CHNL_ALLSAME_Pos 7U
#define IDIMMES_CHNL_ALLSAME_Msk 0x80U
#define IDIMMES_DATA_FUNC_COM_DATA_Pos 04U
#define IDIMMES_MAX_HEADER_LENGTH (IDIMMES_DATA_FUNC_COM_DATA_Pos + 1)
#define IDIMMES_MAX_DATA_SIZE 256U
#define IDIMMES_MAX_MES_SIZE (IDIMMES_MAX_DATA_SIZE + IDIMMES_MAX_HEADER_LENGTH + MODBUS_CRC16_SIZE)
#define IDIMMES_MIN_MES_SIZE (IDIMMES_DATA_FUNC_COM_DATA_Pos + MODBUS_CRC16_SIZE)
#define IDIMMESG_DATA_COM_FUNC_Pos 02U
#define IDIMMESG_MAX_HEADER_LENGTH (IDIMMESG_DATA_COM_FUNC_Pos + 1)
#define IDIMMESG_MAX_DATA_SIZE IDIMMES_MAX_DATA_SIZE
#define IDIMMESG_MAX_MES_SIZE (IDIMMESG_MAX_DATA_SIZE + IDIMMESG_MAX_HEADER_LENGTH + MODBUS_CRC16_SIZE)
#define IDIMMESG_MODULE_MIN_MES_SIZE (IDIMMESG_DATA_COM_FUNC_Pos + 1 + MODBUS_CRC16_SIZE)
#define IDIMMESG_GROUP_MIN_MES_SIZE (IDIMMESG_DATA_COM_FUNC_Pos + MODBUS_CRC16_SIZE)
#define IDIMMES_LMES_MSIZE_Pos 0U
#define IDIMMES_LMES_BSIZE_Pos (IDIMMES_LMES_MSIZE_Pos + 4U)
#define IDIMMES_LMES_IDENTIFIER_LENGTH (IDIMMES_LMES_BSIZE_Pos + 1U)
#define IDIMMES_LMES_BSIZE_256B 0U
#define IDIMMES_LMES_BSIZE_1K 1U
#define IDIMMES_LMES_BSIZE_4K 2U
#define IDIMMES_LMES_BSIZE_8K 3U
#define IDIMMES_LMES_BSIZE_16K 4U
#define IDIMMES_LMES_BSIZE_32K 5U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISMES_ADDR_Pos 00U
#define IDISMES_SMPS_Pos 01U
#define IDISMES_SMPS_ERROR_BIT_Pos 0U
#define IDISMES_SMPS_LONG_MES_Pos 1U
#define IDISMES_SMPS_LONG_OP_Pos 2U
#define IDISMES_ERROR_Pos 02U
#define IDISMES_DATA_Pos 03U
#define IDISMES_MAX_DATA_SIZE 256U
#define IDISMES_MIN_MES_SIZE (IDISMES_DATA_Pos + MODBUS_CRC16_SIZE)
#define IDISMES_MAX_MES_SIZE (IDISMES_DATA_Pos + IDISMES_MAX_DATA_SIZE + MODBUS_CRC16_SIZE)
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDILONGOP_STATE_COMPLETE_NO_ERR 0x00U
#define IDILONGOP_STATE_IN_PROC 0x01U
#define IDILONGOP_STATE_COMPLETE_WITH_ERR 0x02U
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDILONGOP_MES_DATA_LENGTH 5U
#define IDILONGOP_STATE_Pos 0U
#define IDILONGOP_REMAIN_TIME_Pos 1U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDISTATUS_B0S_Pos 00U
#define IDISTATUS_B0S_ST_ERROR_Pos 0U
#define IDISTATUS_B0S_ST_STATE_Pos 1U
#define IDISTATUS_B0S_ST_STATE_Msk 0x07U
#define IDISTATUS_B0S_ST_STATE_StNoInit 0x00U
#define IDISTATUS_B0S_ST_STATE_StOperate 0x01U
#define IDISTATUS_B0S_ST_STATE_StFreeze 0x02U
#define IDISTATUS_B0S_ST_STATE_StVirtual 0x03U
#define IDISTATUS_B0S_ST_STATE_StFirmwareUpd 0x04U
#define IDISTATUS_B0S_ST_STATE_StReservedMaster 0x05U
#define IDISTATUS_B0S_ST_STATE_StBroken 0x06U
#define IDISTATUS_B0S_ST_STATE_StReserved0 0x07U
#define IDISTATUS_B0S_AES_SUPPORTED_Pos 4U
#define IDISTATUS_B0S_AES_INSTALLED_Pos 5U
#define IDISTATUS_B0S_SEND_ALARM_L0_Pos 6U
#define IDISTATUS_B0S_SEND_ALARM_L1_Pos 7U
#define IDISTATUS_B1S_Pos 01U
#define IDISTATUS_B1S_MODULE_TYPE_Pos 0U
#define IDISTATUS_B1S_MODULE_TYPE_Msk 0x03U
#define IDISTATUS_B1S_MODULE_TYPE_Master 0x00U
#define IDISTATUS_B1S_MODULE_TYPE_SpareMaster 0x01U
#define IDISTATUS_B1S_MODULE_TYPE_Slave 0x02U
#define IDISTATUS_B1S_MODULE_TYPE_Bridge 0x03U
#define IDISTATUS_B1S_BRIDGE_CONNECTED_Pos 2U
#define IDISTATUS_B1S_SELF_INIT_Pos 3U
#define IDISTATUS_B1S_TIMEOUT_LED_Pos 4U
#define IDISTATUS_B1S_NO_MMES_TIMEOUT_Pos 5U
#define IDISTATUS_B1S_CATCH_ALARM_L0_Pos 6U
#define IDISTATUS_B1S_CATCH_ALARM_L1_Pos 7U
#define IDISTATUS_SN_Pos 02U
#define IDISTATUS_LENGTH ( IDISTATUS_SN_Pos + IDISN_FULL_LENGTH )
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIMMES_NOT_FAST_FUNC 0U
#define IDIMMES_MAX_FAST_FUNC_NUM 15U
#define IDIMMES_COM_START_NUM 220U
#define IDIMMES_COM_C_Init 220U
#define IDIMMES_COM_C_ShtDown 221U
#define IDIMMES_COM_C_Freeze 222U
#define IDIMMES_COM_C_Resume 223U
#define IDIMMES_COM_C_Dummy 224U
#define IDIMMES_COM_C_AssignGroup 225U
#define IDIMMES_COM_C_SetAlarmL12 226U
#define IDIMMES_COM_C_SetAlarmL 227U
#define IDIMMES_COM_C_Virtual 228U
#define IDIMMES_COM_C_SyncReadChnl 229U
#define IDIMMES_COM_C_SyncRead 230U
#define IDIMMES_COM_C_SyncDoChnl 231U
#define IDIMMES_COM_C_SyncDo 232U
#define IDIMMES_COM_C_SyncClear 233U
#define IDIMMES_COM_C_BurstReadCnt 234U
#define IDIMMES_COM_C_BurstReadTime 235U
#define IDIMMES_COM_C_SendTimeDate 236U
#define IDIMMES_COM_C_MkTimedMaster 237U
#define IDIMMES_COM_C_FmwUpd 238U
#define IDIMMES_COM_C_EndFmwUpd 239U
#define IDIMMES_COM_C_FmwWrite 240U
#define IDIMMES_COM_C_ReadDevFullSN_MS 241U
#define IDIMMES_COM_C_WriteSnIPv4IPv6 242U
#define IDIMMES_COM_C_WriteSnVerifyDates 243U
#define IDIMMES_COM_C_WriteSnAES256 244U
#define IDIMMES_COM_C_SendLongMessage 245U
#define IDIMMES_COM_C_GetLondMessage 246U
#define IDIMMES_COM_C_DummyModule 247U
#define IDIMMES_COM_C_CheckModuleLongOp 248U
#define IDIMMES_COM_C_CheckChannelLongOp 249U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIER_MODBUS_NUM_START 1U
#define IDIER_MODBUS_NUM_END 9U
#define IDIER_MODULE_MASTER_NUM_START 10U
#define IDIER_MODULE_MASTER_NUM_END 32U
#define IDIER_MODULE_SLAVE_NUM_START 33U
#define IDIER_MODULE_SLAVE_NUM_END 71U
#define IDIER_MODULE_NUM_START IDIER_MODULE_MASTER_NUM_START
#define IDIER_MODULE_NUM_END IDIER_MODULE_SLAVE_NUM_END
#define IDIER_DEVICE_NUM_START 72U
#define IDIER_DEVICE_NUM_END 89U
#define IDIER_NOPE 0U
#define MODBUSER_WRONGFUNC 1U
#define MODBUSER_WRONGADDR 2U
#define MODBUSER_WRONGDATA 3U
#define MODBUSER_BROKE 4U
#define MODBUSER_LONGCOMMAND 5U
#define MODBUSER_BUSY 6U
#define MODBUSER_CANTDOFUNC 7U
#define MODBUSER_EXTMEMORYERROR 8U
#define MODBUSER_RESERVED 9U
#define IDIERMST_INVALID_ADDR_NUM 10U
#define IDIERMST_INVALID_DEV_NUM 11U
#define IDIERMST_INVALID_CHN_NUM 12U
#define IDIERMST_INVALID_FUNC_NUM 13U
#define IDIERMST_INVALID_TX_REQUEST_FORMAT 14U
#define IDIERMST_INVALID_TX_PARAM 15U
#define IDIERMST_TX_MES 16U
#define IDIERMST_RCV_TIMEOUT 17U
#define IDIERMST_MES_RX_INTEGRITY 18U
#define IDIERMST_CRC 19U
#define IDIERMST_MULTIPLE_CRC 20U
#define IDIERMST_INVALID_RX_REQUEST_FORMAT 21U
#define IDIERMST_INVALID_RX_PARAM 22U
#define IDIERMST_RESEVED_23 23U
#define IDIERMST_RESEVED_24 24U
#define IDIERMST_RESEVED_25 25U
#define IDIERMST_RESEVED_26 26U
#define IDIERMST_RESEVED_27 27U
#define IDIERMST_EXTRA_28 28U
#define IDIERMST_EXTRA_29 29U
#define IDIERMST_EXTRA_30 30U
#define IDIERMST_EXTRA_31 31U
#define IDIERMST_EXTRA_32 32U
#define IDIERSLV_RESEVED_33 33U
#define IDIERSLV_ENCRYPTION_NOT_SUPPORTED 34U
#define IDIERSLV_ENCRYPTION_NOT_INSTALLED 35U
#define IDIERSLV_JUMBO_NOT_SUPPORTED 36U
#define IDIERSLV_UNSUPPORTED_FUNC_NUM 37U
#define IDIERSLV_INVALID_RX_REQUEST_FORMAT 38U
#define IDIERSLV_INVALID_RX_PARAM 39U
#define IDIERSLV_IN_FREEZE 40U
#define IDIERSLV_RESERVED_41 41U
#define IDIERSLV_RESERVED_42 42U
#define IDIERSLV_RESERVED_43 43U
#define IDIERSLV_RESERVED_44 44U
#define IDIERSLV_RESERVED_45 45U
#define IDIERSLV_EXTRA_46 46U
#define IDIERSLV_EXTRA_47 47U
#define IDIERSLV_EXTRA_48 48U
#define IDIERSLV_EXTRA_49 49U
#define IDIERSLV_EXTRA_50 50U
#define IDIERSLV_BROKE 51U
#define IDIERSLV_NO_FIRMWARE 52U
#define IDIERSLV_NO_INIT 53U
#define IDIERSLV_OVERHEAT 54U
#define IDIERSLV_INP_VOLTAGE 55U
#define IDIERSLV_BRIDGE_OVERFLOW 56U
#define IDIERSLV_BRIDGE_NOT_CONF 57U
#define IDIERSLV_VERIF_DATE 58U
#define IDIERSLV_RTC 59U
#define IDIERSLV_LONG_OP_IN_PROC 60U
#define IDIERSLV_RESERVED_61 61U
#define IDIERSLV_RESERVED_62 62U
#define IDIERSLV_RESERVED_63 63U
#define IDIERSLV_RESERVED_64 64U
#define IDIERSLV_RESERVED_65 65U
#define IDIERSLV_RESERVED_66 66U
#define IDIERSLV_EXTRA_67 67U
#define IDIERSLV_EXTRA_68 68U
#define IDIERSLV_EXTRA_69 69U
#define IDIERSLV_EXTRA_70 70U
#define IDIERSLV_EXTRA_71 71U
#define IDIERDEV_INVALID_DEV_NUM 72U
#define IDIERDEV_INVALID_CHN_NUM 73U
#define IDIERDEV_INVALID_FUNC_NUM 74U
#define IDIERDEV_LONG_OP_IN_PROC 75U
#define IDIERDEV_RESERVED_76 76U
#define IDIERDEV_PARAM_LOW_ST_TIMEOUT 77U
#define IDIERDEV_PARAM_HIGH_ST_TIMEOUT 78U
#define IDIERDEV_PARAM_NOT_CHANGE_TIMEOUT 79U
#define IDIERDEV_RESERVED_80 80U
#define IDIERDEV_RESERVED_81 81U
#define IDIERDEV_RESERVED_82 82U
#define IDIERDEV_RESERVED_83 83U
#define IDIERDEV_RESERVED_84 84U
#define IDIERDEV_RESERVED_85 85U
#define IDIERDEV_RESERVED_86 86U
#define IDIERDEV_RESERVED_87 87U
#define IDIERDEV_RESERVED_88 88U
#define IDIERDEV_RESERVED_89 89U
#define IDIER_MULTIPLE_CRC_AVRBUF_SIZE 16U
#define IDIER_MULTIPLE_CRC_AVRBUF_THR 5U
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
#define IDIDATE_FORMAT_DAY_Pos 0U
#define IDIDATE_FORMAT_MONTH_Pos 1U
#define IDIDATE_FORMAT_CENTURY_Pos 2U
#define IDIDATE_FORMAT_YEAR99_Pos 3U
#define IDIDATE_FORMAT_LENGTH 4U
#define IDITIME_FORMAT_SECONDS_Pos 0U
#define IDITIME_FORMAT_MINUTES_Pos 1U
#define IDITIME_FORMAT_HOURS_Pos 2U
#define IDITIME_FORMAT_TIMEZONE_Pos 3U
#define IDITIME_FORMAT_LENGTH 4U
#define IDITIME_FORMAT_TIMEZONE_MIN (-12)
#define IDITIME_FORMAT_TIMEZONE_MAX 14
#define IDIMMES_C_DATETIME_TIME_Pos 0
#define IDIMMES_C_DATETIME_DATE_Pos (IDIMMES_C_DATETIME_TIME_Pos + IDIDATE_FORMAT_LENGTH)
#define IDIMMES_C_DATETIME_LENGTH (IDIDATE_FORMAT_LENGTH + IDITIME_FORMAT_LENGTH)
//=============================================================================================================================================================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//=============================================================================================================================================================================================================
typedef struct {
struct {
uint8_t StError : 1;
uint8_t StState : 3;
uint8_t AesSupported : 1;
uint8_t AesInstalled : 1;
uint8_t SendAlarmL0 : 1;
uint8_t SendAlarmL1 : 1;
} B0S;
struct {
uint8_t ModuleType : 2;
uint8_t BridgeConnected : 1;
uint8_t SelfInit : 1;
uint8_t TimeoutLed : 1;
uint8_t NoMMESTimeout : 1;
uint8_t CatchAlarmL0 : 1;
uint8_t CatchAlarmL1 : 1;
} B1S;
} IDISTATUS_STATE_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------s
typedef struct {
IDISTATUS_STATE_TYPE STATE;
uint8_t SN[IDISN_FULL_LENGTH];
} IDISTATUS_SLAVE_TYPE;
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#endif //_INC_IDIBUS_DEFS_H_
//#############################################################################################################################################################################################################

@ -0,0 +1,134 @@
//###################################################################################################################################################
#include "MODBUS_CRC.h"
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Table of CRC values for highorder byte FLASH Variant
const uint8_t MODBUS_auchCRCHi_PR[] PROGMEM = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
// Table of CRC values for loworder byte
const uint8_t MODBUS_auchCRCLo_PR[] PROGMEM = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
// Table of CRC values for highorder byte RAM Variant
uint8_t MODBUS_auchCRCHi_R[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
// Table of CRC values for loworder byte
uint8_t MODBUS_auchCRCLo_R[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_TF(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen)
{
uint8_t MODBUS_uchCRCHi = 0xFF; // high byte of CRC initialized
uint8_t MODBUS_uchCRCLo = 0xFF; // low byte of CRC initialized
uint8_t MODBUS_uIndex;
while (MODBUS_usDataLen--)
{
MODBUS_uIndex = MODBUS_uchCRCLo ^ (*MODBUS_puchMsg++); // calculate the CRC
MODBUS_uchCRCLo = MODBUS_uchCRCHi ^ pgm_read_byte(&MODBUS_auchCRCHi_PR[MODBUS_uIndex]);
MODBUS_uchCRCHi = pgm_read_byte(&MODBUS_auchCRCLo_PR[MODBUS_uIndex]);
}
return ( ((uint16_t)MODBUS_uchCRCHi << 8 ) | MODBUS_uchCRCLo );
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_TR(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen)
{
uint8_t MODBUS_uchCRCHi = 0xFF; // high byte of CRC initialized
uint8_t MODBUS_uchCRCLo = 0xFF; // low byte of CRC initialized
uint8_t MODBUS_uIndex;
while (MODBUS_usDataLen--)
{
MODBUS_uIndex = MODBUS_uchCRCLo ^ (*MODBUS_puchMsg++); // calculate the CRC
MODBUS_uchCRCLo = MODBUS_uchCRCHi ^ MODBUS_auchCRCHi_R[MODBUS_uIndex];
MODBUS_uchCRCHi = MODBUS_auchCRCLo_R[MODBUS_uIndex];
}
return (((uint16_t)MODBUS_uchCRCHi << 8) | MODBUS_uchCRCLo);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
uint16_t MODBUS_CRC16::CRC16_S(uint8_t *MODBUS_buf, uint16_t MODBUS_len)
{
uint16_t MODBUS_crc = 0xFFFF;
for (uint16_t MODBUS_pos = 0; MODBUS_pos < MODBUS_len; MODBUS_pos++)
{
MODBUS_crc ^= MODBUS_buf[MODBUS_pos]; // XOR byte into least sig. byte of crc
for (uint8_t MODBUS_i = 8; MODBUS_i != 0; MODBUS_i--) // Loop over each bit
{
if ((MODBUS_crc & 0x0001) != 0) { MODBUS_crc >>= 1; MODBUS_crc ^= 0xA001; } // If the LSB is set // Shift right and XOR 0xA001
else { MODBUS_crc >>= 1; } // Else LSB is not set // Just shift right
}
}
return MODBUS_crc;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------
//###################################################################################################################################################

@ -0,0 +1,20 @@
//###################################################################################################################################################
#ifndef _MODBUS_CRC_H_
#define _MODBUS_CRC_H_
//---------------------------------------------------------------------------------------------------------------------------------------------------
#include "avr/io.h"
#include <avr/pgmspace.h>
#include <inttypes.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------
#define MODBUS_CRC16_SIZE 2
//---------------------------------------------------------------------------------------------------------------------------------------------------
class MODBUS_CRC16 {
public :
static uint16_t CRC16_TF(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen);
static uint16_t CRC16_TR(uint8_t *MODBUS_puchMsg, uint16_t MODBUS_usDataLen);
static uint16_t CRC16_S(uint8_t *MODBUS_buf, uint16_t MODBUS_len);
private :
};
//---------------------------------------------------------------------------------------------------------------------------------------------------
#endif //#define _CRC_MODBUS_
//###################################################################################################################################################

@ -0,0 +1,157 @@
#include "IDIBUS_1Wire.h"
IdiBus_1Wire::IdiBus_1Wire (IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress) : IdiBusSlave(SlaveLine, SlaveAddress)
{
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = 0;
this->CH[I].Temperature = 0;
//this->CH[I].STATUS.Enable = 0;
}
}
IdiBus_1Wire::IdiBus_1Wire () : IdiBusSlave()
{
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = 0;
this->CH[I].Temperature = 0;
//this->CH[I].STATUS.Enable = 0;
}
}
IDIBUS_1Wire_DATA_TYPE IdiBus_1Wire::getChData(uint8_t ChNum){
if ( ChNum < IDIBUS_1Wire_CH_COUNT ) { return this->CH[ChNum]; }
else { return this->CH[IDIBUS_1Wire_CH3_NUM]; }
}
void IdiBus_1Wire::changeAllAutomatiocConversionStates()
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1Wire_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x01;
uint8_t ChDataSize = 1;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_1Wire_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_1Wire_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_1Wire_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
}
}
void IdiBus_1Wire::startAllOneShotConversions()
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1Wire_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x02;
uint8_t ChDataSize = 0;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_1Wire_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_1Wire_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_1Wire_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
}
}
uint8_t IdiBus_1Wire::getTemperature(uint8_t ChNum)
{
if (ChNum >= IDIBUS_1Wire_CH_COUNT) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1Wire_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = 0x03; //Get Value
uint8_t ChDataSize = 2; //int16_t
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE )
{
this->CH[ChNum].Temperature = (int16_t) ( ((int16_t)MMES.RxData[1]<<8) |
((int16_t)MMES.RxData[2]));
}
}
return this->CH[ChNum].MMES_Error;
}
void IdiBus_1Wire::getAllChTemperature(void)
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1Wire_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x03;
uint8_t ChDataSize = 2; //int16_t
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_1Wire_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_1Wire_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_1Wire_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE )
{
this->CH[I].Temperature = (uint16_t) (
(uint16_t)((uint16_t)MMES.RxData[DataPos] << 8) |
(uint16_t)((uint16_t)MMES.RxData[DataPos+1]) );
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
void IdiBus_1Wire::setAllChErr(uint8_t ErrCode)
{
for (uint8_t I=0; I<IDIBUS_1Wire_CH_COUNT; I++) { this->CH[I].MMES_Error = ErrCode; }
}
/*
void IdiBus_1Wire::initAllChs(void)
{
//uint8_t TxData[2];
//TxData[0] = (uint8_t)(CurrentLimit >> 8);
//TxData[1] = (uint8_t)(CurrentLimit);
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1Wire_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x01;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_1Wire_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_1Wire_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
//if ( this->CH[I].MMES_Error == IDIER_NOPE )
}
}
}
*/

@ -0,0 +1,51 @@
#ifndef IDIBUS_1Wire_H_
#define IDIBUS_1Wire_H_
#include "IdiBusSlave.h" // Common slave defines
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_SETTINGS_ERROR 100U
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_CRC_ERROR 101U
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_NO_DATA 102U
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_NO_SENSOR 103U
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_AUTOCONVERSION_ENABLED 105U
#define IDIBUS_CUSTDEF_ERCODE_OneWIRE_CHANNEL_ONESHOT_IN_PROGRESS 106U
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
enum IDIBUS_1Wire_MODULE_DEVICES_LIST { // Describe devices on module
IDIBUS_1Wire_CNTRL_DEV = 0, // ADC device ID
IDIBUS_1Wire_DEVICES_NUMBER // Device count on module
};
enum { // Describe channel configuration for device (1Wire)
IDIBUS_1Wire_CH0_NUM = 0, // Name for 1st channel
IDIBUS_1Wire_CH1_NUM, // 2nd ...
IDIBUS_1Wire_CH2_NUM, //
IDIBUS_1Wire_CH3_NUM, //
IDIBUS_1Wire_CH_COUNT, // Module channel count
};
typedef struct {
int16_t Temperature; // Last voltage
uint8_t MMES_Error; // Last error
} IDIBUS_1Wire_DATA_TYPE; // Data structure for ADC channels
class IdiBus_1Wire : public IdiBusSlave { // ADC module class
public: // Public methods
IdiBus_1Wire ( IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress); // Init object with specified bus line and addr
IdiBus_1Wire (); // init without specified line and addr (default value line=NULL,addr=1)
void startAllOneShotConversions();
void changeAllAutomatiocConversionStates();
uint8_t getTemperature(uint8_t ChNum); // Sends MMES and gets Ch voltage (writes to CH structure and return error code)
void getAllChTemperature(void); // Sends MMES and gets all Ch voltages (writes to CH structure)
//void initAllChs(void); // Inits all adc channels on module
IDIBUS_1Wire_DATA_TYPE getChData(uint8_t ChNum); // Returns data structure for ADC channel
protected : // 'Private' methods and structures
IDIBUS_1Wire_DATA_TYPE CH[IDIBUS_1Wire_CH_COUNT]; // Data structure array
void setAllChErr(uint8_t ErrCode); // Set error code for all channels
};
#endif /* IDIBUS_41Wire_H_ */

@ -0,0 +1,52 @@
#include "IDIBUS_1xGen.h"
IdiBus_1xGen::IdiBus_1xGen (IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress) : IdiBusSlave(SlaveLine, SlaveAddress)
{
TMP.MMES_Error = 0;
TMP.RXlen = 0;
}
IdiBus_1xGen::IdiBus_1xGen () : IdiBusSlave()
{
TMP.MMES_Error = 0;
TMP.RXlen = 0;
}
IDIBUS_1xGEN_DATA_TYPE IdiBus_1xGen::getData(void)
{
return this->TMP;
}
uint8_t IdiBus_1xGen::start_SPI(uint8_t *buf) {
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1xGen_DEV;
MMES.CHNL.NUM = 0;
MMES.ComFunc = 0x01;
MMES.TxDataLength = 10;
MMES.TxData = buf;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->TMP.MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->TMP.MMES_Error = MMES.RxData[0]; }
else {
this->TMP.MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT;
}
return this->TMP.MMES_Error;
}
uint8_t IdiBus_1xGen::reset_STM() {
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_1xGen_DEV;
MMES.CHNL.NUM = 0;
MMES.ComFunc = 0x02;
uint8_t ChDataSize = 0;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->TMP.MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->TMP.MMES_Error = MMES.RxData[0]; }
else {
this->TMP.MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT;
}
return this->TMP.MMES_Error;
}

@ -0,0 +1,47 @@
#ifndef IDIBUS_1XGEN_H_
#define IDIBUS_1XGEN_H_
#include "IdiBusSlave.h"
typedef struct {
uint8_t first_mode_time;
uint16_t first_mode_pwm_value;
uint8_t first_mode_f;
uint8_t first_mode_invert;
//uint8_t first_mode_R1;
uint8_t second_mode_time;
uint16_t second_mode_pwm_value;
uint8_t second_mode_f;
uint8_t second_mode_invert;
//uint8_t second_mode_R1;
} Inputs;
enum IDIBUS_1xGen_MODULE_DEVICES_LIST {
IDIBUS_1xGen_DEV = 0x00,
IDIBUS_1xGen_DEVICES_NUMBER
};
typedef struct {
uint8_t RXlen;
uint8_t RXbuf[255];
uint8_t MMES_Error; // Last error
} IDIBUS_1xGEN_DATA_TYPE;
class IdiBus_1xGen : public IdiBusSlave {
public:
IdiBus_1xGen (IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress);
IdiBus_1xGen();
uint8_t start_SPI(uint8_t *buf);
uint8_t reset_STM();
//virtual IdiBusDevice *getDevice(uint8_t Num); // !!!
IDIBUS_1xGEN_DATA_TYPE getData();
protected:
IDIBUS_1xGEN_DATA_TYPE TMP;
};
#endif /* IDIBUS_1XGEN_H_ */

@ -0,0 +1,160 @@
#include "IDIBUS_2SALTMETER.h"
IdiBus_2SALT::IdiBus_2SALT (IdiBusSerialLine *SlaveLine, uint8_t SlaveAddress) : IdiBusSlave(SlaveLine, SlaveAddress)
{
for (uint8_t I=0; I<IDIBUS_2SALT_CH_COUNT; I++)
{
this->CH[I].MMES_Error = 0;
this->CH[I].Voltage = 0;
}
}
IdiBus_2SALT::IdiBus_2SALT () : IdiBusSlave()
{
for (uint8_t I=0; I<IDIBUS_2SALT_CH_COUNT; I++)
{
this->CH[I].MMES_Error = 0;
this->CH[I].Voltage = 0;
}
}
IDIBUS_2SALT_DATA_TYPE IdiBus_2SALT::getChData(uint8_t ChNum){
if ( ChNum < IDIBUS_2SALT_CH_COUNT ) { return this->CH[ChNum]; }
else { return this->CH[IDIBUS_2SALT_CH1_NUM]; }
}
uint8_t IdiBus_2SALT::getChSaltData(uint8_t ChNum)
{
if (ChNum >= IDIBUS_2SALT_CH_COUNT) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = 0x03; //Get Value
uint8_t ChDataSize = 2; //uint16_t
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength == 1 ) { this->CH[ChNum].MMES_Error = MMES.RxData[0]; }
else if ( MMES.RxDataLength != (ChDataSize + 1) ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
if ( this->CH[ChNum].MMES_Error == IDIER_NOPE )
{
this->CH[ChNum].Voltage = (uint16_t) (
((uint16_t)MMES.RxData[1] << 8 ) |
((uint16_t)MMES.RxData[2]) );
}
}
return this->CH[ChNum].MMES_Error;
}
void IdiBus_2SALT::getAllChsSaltData(void)
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x03;
uint8_t ChDataSize = 2; //uint16_t
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); return; }
else if (MMES.RxDataLength < IDIBUS_2SALT_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
else {
uint8_t ExpDataLength = IDIBUS_2SALT_CH_COUNT; // Errors
for (uint8_t I=0; I<IDIBUS_2SALT_CH_COUNT; I++) { if ( MMES.RxData[I] == IDIER_NOPE ) { ExpDataLength = (uint16_t)(ExpDataLength + ChDataSize); } }
if ( ExpDataLength != MMES.RxDataLength ) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); return; }
}
uint8_t ErrorPos = 0;
uint8_t DataPos = ErrorPos + IDIBUS_2SALT_CH_COUNT;
for (uint8_t I = 0; I < IDIBUS_2SALT_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[ErrorPos];
ErrorPos = (uint8_t)(ErrorPos + 1);
if ( this->CH[I].MMES_Error == IDIER_NOPE ) {
this->CH[I].Voltage = (uint16_t) (
((uint16_t)MMES.RxData[DataPos] << 8) |
((uint16_t)MMES.RxData[DataPos+1]) );
DataPos = (uint8_t)(DataPos + ChDataSize);
}
}
}
void IdiBus_2SALT::setAllChErr(uint8_t ErrCode)
{
for (uint8_t I=0; I<IDIBUS_2SALT_CH_COUNT; I++) { this->CH[I].MMES_Error = ErrCode; }
}
uint8_t IdiBus_2SALT::setCh(uint8_t ChNum, uint8_t state)
{
if (ChNum >= IDIBUS_2SALT_CH_COUNT) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = 0x01; //init
MMES.TxDataLength = 1;
MMES.TxData = &state;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
}
return this->CH[ChNum].MMES_Error;
}
void IdiBus_2SALT::setAllCh(uint8_t state)
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x01; //init
MMES.TxDataLength = 1;
MMES.TxData = &state;
MMES.CHNL.ALLSAME = 1;
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_2SALT_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_2SALT_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
}
}
}
uint8_t IdiBus_2SALT::startOneShot(uint8_t ChNum)
{
if (ChNum >= IDIBUS_2SALT_CH_COUNT) { return IDIERMST_INVALID_CHN_NUM; }
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.CHNL.NUM = ChNum;
MMES.ComFunc = 0x02; //init
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->CH[ChNum].MMES_Error = RequestError; }
else if ( MMES.RxDataLength != 1 ) { this->CH[ChNum].MMES_Error = IDIERMST_INVALID_RX_REQUEST_FORMAT; }
else {
this->CH[ChNum].MMES_Error = MMES.RxData[0];
}
return this->CH[ChNum].MMES_Error;
}
void IdiBus_2SALT::startAllOneShot(void)
{
IdiBusMMES MMES(this->Address);
MMES.DEV.NUM = IDIBUS_2SALT_CNTRL_DEV;
MMES.DEV.ALLCH = 1;
MMES.ComFunc = 0x02; //init
uint8_t RequestError = this->SendRequestMMES(&MMES);
if ( RequestError != IDIER_NOPE ) { this->setAllChErr(RequestError); }
else if (MMES.RxDataLength != IDIBUS_2SALT_CH_COUNT) { this->setAllChErr(IDIERMST_INVALID_RX_REQUEST_FORMAT); }
else
{
for (uint8_t I = 0; I < IDIBUS_2SALT_CH_COUNT; I++)
{
this->CH[I].MMES_Error = MMES.RxData[I];
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save