macchina/LIN

Need help to port this library for ATmega32M1

Opened this issue · 0 comments

I am not an expert programmer, and I need a lin bus library for the atmega32M1, could anyone help me to modify it? I made some changes in lin_stack.cpp to change the Tx and Rx ports for the atmega32M1 but it does't work.
Link to atmega32m1 datasheet: http://www.atmel.com/Images/Atmel-7647-Automotive-Microcontrollers-ATmega16M1-32M1-64M1-32C1-64C1_datasheet.pdf
This is the code that I modify:

#include <lin_stack.h>
const unsigned long bound_rate = 10417;

// CONSTRUCTORS
lin_stack::lin_stack(byte Ch){
	sleep_config(Ch); // Configurating Sleep pin for transceiver
}

lin_stack::lin_stack(byte Ch, byte ident){
	sleep_config(Ch); // Configuration of Sleep pin for transceiver
	identByte = ident; // saving idet to private variable
	sleep(1); // Transceiver is always in Normal Mode
}

// PUBLIC METHODS
// WRITE methods
// Creates a LIN packet and then send it via USART(Serial) interface.
int lin_stack::write(byte ident, byte data[], byte data_size){
	// Calculate checksum
	byte suma = 0;
	for(int i=0;i<data_size;i++) suma = suma + data[i];
	suma = suma + 1;
	byte checksum = 255 - suma;
	// Start interface
	sleep(1); // Go to Normal mode
	// Synch Break
	serial_pause(13);
	// Send data via Serial interface
	if(ch==1){ // For LIN1 or Serial
		Serial.begin(bound_rate); // config Serial
		Serial.write(0x55); // write Synch Byte to serial
		Serial.write(ident); // write Identification Byte to serial
		for(int i=0;i<data_size;i++) Serial.write(data[i]); // write data to serial
		Serial.write(checksum); // write Checksum Byte to serial
		Serial.end(); // clear Serial config
	}
	sleep(0); // Go to Sleep mode
	return 1;
}

int lin_stack::writeRequest(byte ident){
	// Create Header
	byte header[2]= {0x55, ident};
	// Start interface
	sleep(1); // Go to Normal mode
	// Synch Break
	serial_pause(13);
	// Send data via Serial interface
	if(ch==1){ // For LIN1 or Serial
		Serial.begin(bound_rate); // config Serial
		Serial.write(header,2); // write data to serial
		Serial.end(); // clear Serial config
	}
	sleep(0); // Go to Sleep mode
	return 1;
}

int lin_stack::writeResponse(byte data[], byte data_size){
	// Calculate checksum
	byte suma = 0;
	for(int i=0;i<data_size;i++) suma = suma + data[i];
	suma = suma + 1;
	byte checksum = 255 - suma;
	// Start interface
	sleep(1); // Go to Normal mode
	// Send data via Serial interface
	if(ch==1){ // For LIN1 or Serial
		Serial.begin(bound_rate); // config Serial
		Serial.write(data, data_size); // write data to serial
		Serial.write(checksum); // write data to serial
		Serial.end(); // clear Serial config
	}
	sleep(0); // Go to Sleep mode
	return 1;
}

int lin_stack::writeStream(byte data[], byte data_size){
	// Start interface
	sleep(1); // Go to Normal mode
	// Synch Break
	serial_pause(13);
	// Send data via Serial interface
	if(ch==1){ // For LIN1 or Serial
		Serial.begin(bound_rate); // config Serial
		for(int i=0;i<data_size;i++) Serial.write(data[i]);
		Serial.end(); // clear Serial config
	}
	sleep(0); // Go to Sleep mode
	return 1;
}

// READ methods
// Read LIN traffic and then proces it.
int lin_stack::setSerial(){ // Only needed when receiving signals
	if(ch==1){ // For LIN1 (Channel 1)
		Serial.begin(10417); // Configure Serial
		PORTD|= _BV(PD4); // We need software Pull-Up because there is no hardware Pull-Up resistor
	} 
}

int lin_stack::read(byte data[], byte data_size){
	byte rec[data_size+3];
	if(ch==1){ // For LIN1 or Serial
		if(Serial.read() != -1){ // Check if there is an event on LIN bus
			Serial.readBytes(rec,data_size+3);
			if((validateParity(rec[1]))&(validateChecksum(rec,data_size+3))){
				for(int j=0;j<data_size;j++){
				data[j] = rec[j+2];
				}
				return 1;
			}else{
				return -1;
			}	
		}
	}
	return 0;
}

int lin_stack::readStream(byte data[],byte data_size){
	byte rec[data_size];
	if(ch==1){ // For LIN1 or Serial
		if(Serial.read() != -1){ // Check if there is an event on LIN bus
			Serial.readBytes(rec,data_size);
			for(int j=0;j<data_size;j++){
				data[j] = rec[j];
			}
			return 1;
		}
	}
	return 0;
}


// PRIVATE METHODS
int lin_stack::serial_pause(int no_bits){
	// Calculate delay needed for 13 bits, depends on bound rate
	unsigned int del = period*no_bits; // delay for number of bits (no-bits) in microseconds, depends on period
	if(ch=1){
		DDRD = (1<<PD3);
		PORTD&= ~_BV(PD3); // clear PD3
		delayMicroseconds(del); // delay
		PORTD|= _BV(PD3); // set pin high
		//PIOD->PIO_PDR = PIO_PD3; // clear configuration for PIO, needs to be done because Serial wont work with it
	}
	return 1;
}

int lin_stack::sleep(byte sleep_state){
	if(sleep_state==1){ // Go to Normal mode
		if(ch==1) PORTB|= _BV(PB1); // Set PB1, high state, normal mode
		
	}else if(sleep_state==0){ // Go to Sleep mode
		if(ch==1) PORTB&= ~_BV(PB1); // Clear PB1, low state, sleep mode
		
	}
	delayMicroseconds(20); // According to TJA1021 datasheet this is needed for propper working
	return 1;
}

int lin_stack::sleep_config(byte serial_No){
	if(serial_No==1){ // When using LIN1 channel - usign Serial and pin PB4 for Sleep
		DDRB = (1<<PB1); // enable PIO register on pin PB1
		//PIOB->PIO_OER = PIO_PB1; // set PB1 as output
		PORTB&= ~_BV(PB1); // disable pull-up
		ch=1; // saved as private variable, used for determening Serial port
	}
	return 1;
}

boolean lin_stack::validateParity(byte ident) {
	if(ident == identByte)
		return true;
	else
		return false;
}

boolean lin_stack::validateChecksum(unsigned char data[], byte data_size){
	byte checksum = data[data_size-1];
	byte suma = 0;
	for(int i=2;i<data_size-1;i++) suma = suma + data[i];
	byte v_checksum = 255 - suma - 1;
	if(checksum==v_checksum)
		return true;
	else
		return false;
}