##// END OF EJS Templates

File last commit:

r216:217
r221:222
Show More
powerEngine.c
286 lines | 5.4 KiB | text/x-c | CLexer
/*
* powerEngine.c
*
* Created on: Mar 23, 2015
* Author: shinobi
*/
#include "powerEngined.h"
#include "usi_i2c_slave.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#define DQ_HIGH DQ_PORT |= (1<<DQ_BIT)
#define DQ_LOW DQ_PORT &= ~(1<<DQ_BIT)
#define DQ_INPUT DQ_DDR &= ~(1<<DQ_BIT)
#define DQ_OUTPUT DQ_DDR |= (1<<DQ_BIT)
#define DQ_READ ((DQ_PIN&(1<<DQ_BIT))!=0)?0x01:0x00
#define US (1000000.0/ F_CPU )
#define TM0_ON TCCR0B |=(0<<CS02)|(0<<CS01)|(1<<CS00)
#define TM0_OFF TCCR0B &= ~((1<<CS02)|(1<<CS01)|(1<<CS00))
#define TM1_ON TCCR1 |= (1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10)
#define TM1_OFF TCCR1 &= ~((1<<CS13)|(1<<CS12)|(1<<CS11)|(1<<CS10))
#define MAX_TM_CYCLES 15
volatile uint8_t presenced_flg = 0;
volatile uint8_t process_flg = 0;
volatile uint8_t tm_cycles = 0;
extern char* USI_Slave_register_buffer[];
/*!
* \fn write_0_signal
* \brief genera el simbolo que corresponde a '0' logico en el protocolo
* especificatdo en el datasheet del IC DS2438Z
* \see write_1_signal
* \see write_byte
*/
void write_0_signal(){
DQ_LOW;
_delay_us(65);
DQ_HIGH;
_delay_us(1);
}
/*!
* \fn write_1_signal
* \brief genera el simbolo que corresponde a '1' logico en el protocolo
* especificatdo en el datasheet del IC DS2438Z
* \see write_0_signal
* \see write_byte
*/
void write_1_signal(){
DQ_LOW;
_delay_us(10);
DQ_HIGH;
_delay_us(56);
}
/*!
* \fn write_byte
* \brief Escribe un byte por el puerto DQ
* \param byte El byte a escribir
* \see write_0_signal
* \see write_1_signal
*/
void write_byte(uint8_t byte){
uint8_t mask = 0x00;
while(mask!=0){
if((byte&mask)!=0){
write_1_signal();
}else{
write_0_signal();
}
mask = (uint8_t)(mask << 1);
}
}
/*!
* \fn write_bytes
* \brief Escribe "len" bytes por el puerto DQ
* \param pbytes Puntero a inicio de buffer que contiene los bytes
* \param len >Numero de bytes a escribir
* \see write_byte
*/
void write_bytes(uint8_t* pbytes,uint8_t len){
do{
len-=1;
write_byte(pbytes[len]);
}while(len>0);
}
/*!
* \fn read_signal
* \brief Lee un bit del puerto DQ
* \return '1' o '0'.
* \see read_byte
*/
uint8_t read_signal(){
uint8_t bit = 0;
DQ_LOW;
_delay_us(2);
DQ_HIGH;
DQ_INPUT;
_delay_us(8);
bit = DQ_READ;
_delay_us(55);
DQ_OUTPUT;
DQ_HIGH;
_delay_us(1);
return bit;
}
/*!
* \fn read_byte
* \brief Lee un byte de el puerto DQ
* \see read_signal
* \see read_bytes
*/
uint8_t read_byte(){
uint8_t shift = 0x00;
uint8_t byte = 0x00;
uint8_t bit= 0;
while(shift< 8){
bit = read_signal();
byte |= (bit<<shift);
shift++;
}
return byte;
}
/*!
* \fn read_bytes
* \brief Lee "len" bytes de el puerto DQ
* \param pbytes puntero a buffer, contendra los bytes leidos.
* \param len Numero de bytes a leer.
* \see read_byte
*/
void read_bytes(uint8_t* pbytes, uint8_t len){
do{
len-=1;
pbytes[len] = read_byte();
}while(len>0);
}
/*!
* \fn initialization
* \brief Inicia o reinicia al IC DS2438Z
*/
void initialization(){
TCNT0 = 0x0000;
presenced_flg = 0;
DQ_LOW;
_delay_us(490);
TM0_ON;
DQ_HIGH;
while(presenced_flg != 1){}
}
/*!
* \fn memory_read
* \brief Realiza la lectura de toda la memoria del IC DS2438Z
*/
void memory_read(uint8_t* pbytes, uint8_t page_addr){
uint8_t crc;
initialization();
write_byte(SKIP_ROM);
write_byte(READ_SP);
write_byte(page_addr);
read_bytes(pbytes,8);
crc = read_byte();
initialization();
}
/*!
* \fn convert
* \brief Inicia la conversion ADC de los parametros desados
* \param cmd CONVERT_T para iniciar la conversion de temperatura. CONVERT_V
* para iniciar la conversion de voltaje.
*/
void convert(uint8_t cmd){
uint8_t bit = 0;
initialization();
write_byte(SKIP_ROM);
write_byte(cmd);
do{
bit = read_signal();
}while(bit != 1);
initialization();
}
/*!
* \fn void send_data
* \brief Envia data al sistema enbebido por puerto twi
* \param pbytes Puntero a buffer de bytes a enviar.
* \param len Numero de bytes a enviar. Debe ser menor o igual a USI_SLAVE_REGISTER_COUNT.
*/
void send_data(uint8_t* pbytes, uint8_t len){
int i;
for(i=0;i<USI_SLAVE_REGISTER_COUNT;i++){
if(i<len){
USI_Slave_register_buffer[i]=(char)(pbytes[i]);
}else{
USI_Slave_register_buffer[i]='\0';
}
}
}
//usado para cronometrar la lectura del presence pulse
ISR(TIM0_COMPA_vect ){
TM0_OFF;
}
//detecta el nivel bajo. usado para detectar el presence pulse
ISR(PCINT0_vect){
uint16_t cnt;
if((PINB&(1<<PINB3))==0x00){
if((cnt>=60*US)&&(cnt<=240*US)){
presenced_flg=1;
}
}
}
ISR(TIM1_COMPB_vect){
tm_cycles++; // cuenta de 60 segundos
if(tm_cycles>=MAX_TM_CYCLES){
process_flg = 1;
tm_cycles=0;
}
}
int main(){
uint8_t pbytes[8];
// inicializa
USI_I2C_Init(I2C_SLAVE_ADDR);
cli();
// interrupcion externa
GIMSK |= _BV(PCIE); // Turn on Pin Change interrupt
PCMSK |= _BV(PCINT3); // Which pins are affected by the interrupt
// timer0 CTC con OCRA como top. Debe interrumpir en 250us luego de
// TM0_ON
TCCR0A = (1<<COM0A1)|(1<<COM0A0)|(1<<WGM01)|(0<<WGM00);
TCCR0B = (0<<WGM02);
TM0_OFF;
OCR0A = (uint8_t)(250*US);
// timer1 CTC TOP : OCR1C ; pre-scaler 16384
TCCR1 = (1<<COM1A1)|(1<<COM1A0);
TM1_OFF;
OCR1A = (uint8_t)(244*US);// x 15 ciclo x 16384 (pre-scaler)
//Activa interrupciones de timers
TIMSK |= (1<<OCIE1A)|(1<<OCIE0A);
presenced_flg=0;
sei();
do{
process_flg = 0;
convert(CONV_T);
convert(CONV_V);
memory_read(pbytes,PAGE_0);
send_data(pbytes,8);
while(!(process_flg==1)){};
}while(1==1);
return 0;
}