|
|
/*
|
|
|
* 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;
|
|
|
}
|
|
|
|