/* This file is part of Repetier-Firmware. Repetier-Firmware is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Repetier-Firmware 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Repetier-Firmware. If not, see . This firmware is a nearly complete rewrite of the sprinter firmware by kliment (https://github.com/kliment/Sprinter) which based on Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. Functions in this file are used to communicate using ascii or repetier protocol. */ #ifndef HAL_H #define HAL_H /** This is the main Hardware Abstraction Layer (HAL). To make the firmware work with different processors and toolchains, all hardware related code should be packed into the hal files. */ #include #include #if CPU_ARCH == ARCH_AVR #include #else #define PROGMEM #define PGM_P const char * #define PSTR(s) s #define pgm_read_byte_near(x) (*(char*)x) #define pgm_read_byte(x) (*(char*)x) #endif #define PACK #define FSTRINGVALUE(var,value) const char var[] PROGMEM = value; #define FSTRINGVAR(var) static const char var[] PROGMEM; #define FSTRINGPARAM(var) PGM_P var #include #include /** \brief Prescale factor, timer0 runs at. All known arduino boards use 64. This value is needed for the extruder timing. */ #define TIMER0_PRESCALE 64 #define ANALOG_PRESCALER _BV(ADPS0)|_BV(ADPS1)|_BV(ADPS2) #if MOTHERBOARD==8 || MOTHERBOARD==88 || MOTHERBOARD==9 || CPU_ARCH!=ARCH_AVR #define EXTERNALSERIAL #endif //#define EXTERNALSERIAL // Force using arduino serial #ifndef EXTERNALSERIAL #define HardwareSerial_h // Don't use standard serial console #endif #include #include "Print.h" #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #define COMPAT_PRE1 #endif #if CPU_ARCH==ARCH_AVR #include "fastio.h" #else #define READ(IO) digitalRead(IO) #define WRITE(IO, v) digitalWrite(IO, v) #define SET_INPUT(IO) pinMode(IO, INPUT) #define SET_OUTPUT(IO) pinMode(IO, OUTPUT) #endif class InterruptProtectedBlock { uint8_t sreg; public: inline void protect() { cli(); } inline void unprotect() { SREG = sreg; } inline InterruptProtectedBlock(bool later = false) { sreg = SREG; if(!later) cli(); } inline ~InterruptProtectedBlock() { SREG = sreg; } }; #define EEPROM_OFFSET 0 #define SECONDS_TO_TICKS(s) (unsigned long)(s*(float)F_CPU) #define ANALOG_REDUCE_BITS 0 #define ANALOG_REDUCE_FACTOR 1 #define MAX_RAM 32767 #define bit_clear(x,y) x&= ~(1<>8)*cur->accel)>>10; return res; #else return ((timer>>8)*accel)>>10; #endif } // Multiply two 16 bit values and return 32 bit result static inline uint32_t mulu16xu16to32(unsigned int a,unsigned int b) { uint32_t res; // 18 Ticks = 1.125 us __asm__ __volatile__ ( // 0 = res, 1 = timer, 2 = accel %D2=0 ,%A1 are unused is free // Result LSB first: %A0, %B0, %A1 "clr r18 \n\t" "mul %B2,%B1 \n\t" // mul hig bytes "movw %C0,r0 \n\t" "mul %A1,%A2 \n\t" // mul low bytes "movw %A0,r0 \n\t" "mul %A1,%B2 \n\t" "add %B0,r0 \n\t" "adc %C0,r1 \n\t" "adc %D0,r18 \n\t" "mul %B1,%A2 \n\t" "add %B0,r0 \n\t" "adc %C0,r1 \n\t" "adc %D0,r18 \n\t" "clr r1 \n\t" :"=&r"(res),"=r"(a),"=r"(b) :"1"(a),"2"(b) :"r18" ); // return (long)a*b; return res; } // Multiply two 16 bit values and return 32 bit result static inline unsigned int mulu6xu16shift16(unsigned int a,unsigned int b) { #if CPU_ARCH==ARCH_AVR unsigned int res; // 18 Ticks = 1.125 us __asm__ __volatile__ ( // 0 = res, 1 = timer, 2 = accel %D2=0 ,%A1 are unused is free // Result LSB first: %A0, %B0, %A1 "clr r18 \n\t" "mul %B2,%B1 \n\t" // mul hig bytes "movw %A0,r0 \n\t" "mul %A1,%A2 \n\t" // mul low bytes "mov r19,r1 \n\t" "mul %A1,%B2 \n\t" "add r19,r0 \n\t" "adc %A0,r1 \n\t" "adc %B0,r18 \n\t" "mul %B1,%A2 \n\t" "add r19,r0 \n\t" "adc %A0,r1 \n\t" "adc %B0,r18 \n\t" "clr r1 \n\t" :"=&r"(res),"=r"(a),"=r"(b) :"1"(a),"2"(b) :"r18","r19" ); return res; #else return ((int32_t)a*b)>>16; #endif } static inline void digitalWrite(uint8_t pin,uint8_t value) { ::digitalWrite(pin,value); } static inline uint8_t digitalRead(uint8_t pin) { return ::digitalRead(pin); } static inline void pinMode(uint8_t pin,uint8_t mode) { ::pinMode(pin,mode); } static int32_t CPUDivU2(unsigned int divisor); static inline void delayMicroseconds(unsigned int delayUs) { ::delayMicroseconds(delayUs); } static inline void delayMilliseconds(unsigned int delayMs) { ::delay(delayMs); } static inline void tone(uint8_t pin,int duration) { ::tone(pin,duration); } static inline void noTone(uint8_t pin) { ::noTone(pin); } static inline void eprSetByte(unsigned int pos,uint8_t value) { eeprom_write_byte((unsigned char *)(EEPROM_OFFSET+pos), value); } static inline void eprSetInt16(unsigned int pos,int16_t value) { eeprom_write_word((unsigned int*)(EEPROM_OFFSET+pos),value); } static inline void eprSetInt32(unsigned int pos,int32_t value) { eeprom_write_dword((uint32_t*)(EEPROM_OFFSET+pos),value); } static inline void eprSetFloat(unsigned int pos,float value) { eeprom_write_block(&value,(void*)(EEPROM_OFFSET+pos), 4); } static inline uint8_t eprGetByte(unsigned int pos) { return eeprom_read_byte ((unsigned char *)(EEPROM_OFFSET+pos)); } static inline int16_t eprGetInt16(unsigned int pos) { return eeprom_read_word((uint16_t *)(EEPROM_OFFSET+pos)); } static inline int32_t eprGetInt32(unsigned int pos) { return eeprom_read_dword((uint32_t*)(EEPROM_OFFSET+pos)); } static inline float eprGetFloat(unsigned int pos) { float v; eeprom_read_block(&v,(void *)(EEPROM_OFFSET+pos),4); // newer gcc have eeprom_read_block but not arduino 22 return v; } // Faster version of InterruptProtectedBlock. // For safety it ma yonly be called from within an // interrupt handler. static inline void allowInterrupts() { sei(); } // Faster version of InterruptProtectedBlock. // For safety it ma yonly be called from within an // interrupt handler. static inline void forbidInterrupts() { cli(); } static inline unsigned long timeInMilliseconds() { return millis(); } static inline char readFlashByte(PGM_P ptr) { return pgm_read_byte(ptr); } static inline void serialSetBaudrate(long baud) { RFSERIAL.begin(baud); } static inline bool serialByteAvailable() { return RFSERIAL.available()>0; } static inline uint8_t serialReadByte() { return RFSERIAL.read(); } static inline void serialWriteByte(char b) { RFSERIAL.write(b); } static inline void serialFlush() { RFSERIAL.flush(); } static void setupTimer(); static void showStartReason(); static int getFreeRam(); static void resetHardware(); // SPI related functions static void spiBegin() { #if SDSS>=0 SET_INPUT(MISO_PIN); SET_OUTPUT(MOSI_PIN); SET_OUTPUT(SCK_PIN); // SS must be in output mode even it is not chip select SET_OUTPUT(SDSS); #if SDSSORIG >- 1 SET_OUTPUT(SDSSORIG); #endif // set SS high - may be chip select for another SPI device #if SET_SPI_SS_HIGH WRITE(SDSS, HIGH); #endif // SET_SPI_SS_HIGH #endif } static inline void spiInit(uint8_t spiRate) { uint8_t r = 0; for (uint8_t b = 2; spiRate > b && r < 6; b <<= 1, r++); SET_OUTPUT(SS); WRITE(SS,HIGH); SET_OUTPUT(SCK); SET_OUTPUT(MOSI_PIN); SET_INPUT(MISO_PIN); #ifdef PRR PRR &= ~(1<> 1); SPSR = (r & 1 || r == 6 ? 0 : 1) << SPI2X; } static inline uint8_t spiReceive(uint8_t send=0xff) { SPDR = send; while (!(SPSR & (1 << SPIF))) {} return SPDR; } static inline void spiReadBlock(uint8_t*buf,size_t nbyte) { if (nbyte-- == 0) return; SPDR = 0XFF; for (size_t i = 0; i < nbyte; i++) { while (!(SPSR & (1 << SPIF))) {} buf[i] = SPDR; SPDR = 0XFF; } while (!(SPSR & (1 << SPIF))) {} buf[nbyte] = SPDR; } static inline void spiSend(uint8_t b) { SPDR = b; while (!(SPSR & (1 << SPIF))) {} } static inline void spiSend(const uint8_t* buf , size_t n) { if (n == 0) return; SPDR = buf[0]; if (n > 1) { uint8_t b = buf[1]; size_t i = 2; while (1) { while (!(SPSR & (1 << SPIF))) {} SPDR = b; if (i == n) break; b = buf[i++]; } } while (!(SPSR & (1 << SPIF))) {} } static inline __attribute__((always_inline)) void spiSendBlock(uint8_t token, const uint8_t* buf) { SPDR = token; for (uint16_t i = 0; i < 512; i += 2) { while (!(SPSR & (1 << SPIF))) {} SPDR = buf[i]; while (!(SPSR & (1 << SPIF))) {} SPDR = buf[i + 1]; } while (!(SPSR & (1 << SPIF))) {} } // I2C Support static void i2cInit(unsigned long clockSpeedHz); static unsigned char i2cStart(unsigned char address); static void i2cStartWait(unsigned char address); static void i2cStop(void); static unsigned char i2cWrite( unsigned char data ); static unsigned char i2cReadAck(void); static unsigned char i2cReadNak(void); // Watchdog support inline static void startWatchdog() { wdt_enable(WDTO_1S); }; inline static void stopWatchdog() { wdt_disable(); } inline static void pingWatchdog() { wdt_reset(); }; inline static float maxExtruderTimerFrequency() { return (float)F_CPU/TIMER0_PRESCALE; } #if FEATURE_SERVO static unsigned int servoTimings[4]; static void servoMicroseconds(uint8_t servo,int ms); #endif static void analogStart(); #if USE_ADVANCE static void resetExtruderDirection(); #endif protected: private: }; /*#if MOTHERBOARD==6 || MOTHERBOARD==62 || MOTHERBOARD==7 #if MOTHERBOARD!=7 #define SIMULATE_PWM #endif #define EXTRUDER_TIMER_VECTOR TIMER2_COMPA_vect #define EXTRUDER_OCR OCR2A #define EXTRUDER_TCCR TCCR2A #define EXTRUDER_TIMSK TIMSK2 #define EXTRUDER_OCIE OCIE2A #define PWM_TIMER_VECTOR TIMER2_COMPB_vect #define PWM_OCR OCR2B #define PWM_TCCR TCCR2B #define PWM_TIMSK TIMSK2 #define PWM_OCIE OCIE2B #else*/ #define EXTRUDER_TIMER_VECTOR TIMER0_COMPA_vect #define EXTRUDER_OCR OCR0A #define EXTRUDER_TCCR TCCR0A #define EXTRUDER_TIMSK TIMSK0 #define EXTRUDER_OCIE OCIE0A #define PWM_TIMER_VECTOR TIMER0_COMPB_vect #define PWM_OCR OCR0B #define PWM_TCCR TCCR0A #define PWM_TIMSK TIMSK0 #define PWM_OCIE OCIE0B //#endif #endif // HAL_H