Go Down

Topic: [Solved] using a mask bit dallas rtc (Read 686 times) previous topic - next topic

grendle

Apr 25, 2013, 04:33 am Last Edit: May 03, 2013, 06:00 pm by grendle Reason: 1
Hello all,
if i have a byte, say dec17 , B00010001, but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17. im thinking im to use |= to change bit 6, but im not having any luck doing it. this is for an rtc which uses bcd. i have my bcd code in place
Code: [Select]
writeRegister(MINUTES_REG,decToBcd(17));
void writeRegister(byte thisRegister, char thisValue)
{
 digitalWrite(SLAVESELECT, HIGH);
 SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
 SPI.transfer(thisValue);
 digitalWrite(SLAVESELECT, LOW);
}
byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}

and the clock is set and running fine, to enable alarms bit 6 in hours,days, and minutes register has to be "1". im not using a library for the device (ds1305)http://datasheets.maximintegrated.com/en/ds/DS1305.pdf but am looking at the ds1302 library to see how the bits are handled but im not understanding it. thank you.

lloyddean

#1
Apr 25, 2013, 07:15 am Last Edit: Apr 25, 2013, 07:44 am by lloyddean Reason: 1
Untested but something along the line of -

Code: [Select]

#define setBit(VALUE, BIT)       ((VALUE) |=  (1 << BIT))
#define clearBit(VALUE, BIT)     ((VALUE) &= ~(1 << BIT))

Grumpy_Mike

Quote
but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17.

Yes it will. The number 17 is only one way of interpreting what is after all only a pattern of bits. But if you set bit 6 then all the other bits remain the same and that is what matters if I understand your context correctly.

grendle


Quote
but bit 6 is a mask bit so if i set bit6 high i get B01010001(dec83), which totally changes my original 17.

Yes it will. The number 17 is only one way of interpreting what is after all only a pattern of bits. But if you set bit 6 then all the other bits remain the same and that is what matters if I understand your context correctly.


ya but the clock then runs with "83" (or whatever 83 converts to from bcd).


Untested but something along the line of -

Code: [Select]

#define setBit(VALUE, BIT)       ((VALUE) |=  (1 << BIT))
#define clearBit(VALUE, BIT)     ((VALUE) &= ~(1 << BIT))



im gonna give this a shot. thank you.

AWOL

Quote
(or whatever 83 converts to from bcd).

Woah!
Don't confuse hex with BCD or decimal.

0b10000011 is 0x83 and BCD 83, but 131 decimal.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

CrossRoads

I like using a more direct approach:

value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6

I often do this to clear/set a PORTx pin for SPI transfers, vs doing a digitalWrite of a pin.
PORTD = PORTD & B11111011; // using PD2 for SS pin
SPI.transfer(someValue);        // transfer the data
PORTD = PORTD | B00000100;  // SS pin high
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

grendle


Quote
(or whatever 83 converts to from bcd).

Woah!
Don't confuse hex with BCD or decimal.

0b10000011 is 0x83 and BCD 83, but 131 decimal.



yes, and it is confusing for someone just learning (my lesson is getting an spi device to work from reading the datasheet and not using a library) but im careful with the numbers and constantly using the debug window to see whats coming out. also mike, im gonna post the full code, but at this point its just writing and reading a couple registers. the bcd conversion function is by someone else i cant take credit for that, and some of the code is by others also.

Code: [Select]

#include <SPI.h>
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

#define CONTROL_REG 0x0F
#define DS1305_ADDRESS_OFFSET 0x80
#define SECONDS_REG 0x00
#define MINUTES_REG 0x01
#define HOURS_REG 0x02

SPI.begin();
digitalWrite(SLAVESELECT,LOW);
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK,OUTPUT);
 pinMode(SLAVESELECT,OUTPUT);
 SPI.setClockDivider(SPI_CLOCK_DIV16);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE1);
 // initialize SPI:

Serial.begin(9600);
 digitalWrite(SLAVESELECT, HIGH);
  writeRegister(CONTROL_REG,0x07);
 unsigned int r = readRegister(CONTROL_REG);
 Serial.println("CONTROL = ");
 Serial.println(r,BIN);
 writeRegister(SECONDS_REG,0);
 writeRegister(MINUTES_REG,decToBcd(17));
 char hn = B00010001;                                    //next few lines is me experimenting, this didnt work so needs to be rewritten
 char mask = B01010001;
writeRegister(HOURS_REG,decToBcd(hn));
 hn|=mask;
 writeRegister(HOURS_REG,decToBcd(hn));
}

void loop(){
 
 delay(1000);

 

 byte seconds = bcdToDec(readRegister(SECONDS_REG));
 byte minutes = bcdToDec(readRegister(MINUTES_REG));
 byte hours = bcdToDec(readRegister(HOURS_REG));
 Serial.print(hours,DEC);
 Serial.print(":");
 Serial.print(minutes,DEC);
 Serial.print(":");
 Serial.println(seconds,DEC);

 
}

unsigned int readRegister(byte thisRegister)
{
 byte inByte = 0;
 unsigned int result = 0;

 digitalWrite(SLAVESELECT, HIGH);
 SPI.transfer(thisRegister);
 result = SPI.transfer(0x00);
 digitalWrite(SLAVESELECT, LOW);
 return(result);
}

void writeRegister(byte thisRegister, char thisValue)
{
 digitalWrite(SLAVESELECT, HIGH);
 SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
 SPI.transfer(thisValue);
 digitalWrite(SLAVESELECT, LOW);
}
byte bcdToDec(byte val)
{
 return ( (val/16*10) + (val%16) );
}

byte decToBcd(byte val)
{
 return ( (val/10*16) + (val%10) );
}




grendle


I like using a more direct approach:

value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6

I often do this to clear/set a PORTx pin for SPI transfers, vs doing a digitalWrite of a pin.
PORTD = PORTD & B11111011; // using PD2 for SS pin
SPI.transfer(someValue);        // transfer the data
PORTD = PORTD | B00000100;  // SS pin high


hmm, interesting. very. im gonna toy around with this especially since ive seen your work before and like it alot. thx crossroads.

AWOL

Code: [Select]
value = value | B01000000;  // set bit 6
value = vaue & B10111111; // clear bit 6


C has the _BV (Bit Value) macros to handle this sort of stuff, without having to resort to writing numbers out in binary.
Code: [Select]
value |= _BV(6); //no need for a comment, the operation is obvious
value &= ~_BV(6); // clear bit 6, similarly clear without comment


Want to set bits six and 4?
Code: [Select]
value |= _BV(6) | _BV(4);
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

CrossRoads

Well, I'm gonna admit to not really being a programmer or having indepth knowledge of C macros & classes & things like

value |= _BV(6) | _BV(4);

without having to look them up somewhere every time.  I'll stick with my more expanded form and let the compiler deal with it 8)
Drives my wife nuts - I tell her I've never written a function or macro or class or a library - she'll counter that I use them all the time. Yes, but I've  never written one!
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

grendle

wow great replies, i thank you all, awol & crossroads also, thanks so much great information. i have a feeling from my simple lesson im going to learn much more than i anticipated, this is great, good stuff to work with. cheers all

and dont let crossroads fool ya lol, some awesome boards the man has

grendle

#11
May 03, 2013, 06:05 pm Last Edit: May 03, 2013, 06:16 pm by grendle Reason: 1
finally figured this out, all the posts were correct, clearing the mask bits when reading was the key. sorry this stuff was hard for me but i learned alot.
setting the clock for 8pm

Code: [Select]
writeRegister(HOURS_REG,B01101000);
lowbyte 1000 is bcd for 8, bits 6 is 12 hour mode, bit 5 is am/pm..
to read..
Code: [Select]
byte hours = readRegister(HOURS_REG);
 byte ampm=bitRead(hours,5);
 if (ampm==1){
   meridian=1;
 }
 else{
   meridian=0;
 }
 hours=hours &B10011111; // CLEAR THE MASK BITS HERE
 byte days = readRegister(0x10);
 Serial.print(bcdToDec(hours),DEC);


still working on it, alarm registers etc, there is a library for this particular clock (ds1305) but i wont learn how to deal with the chip directly by using it all the time. and ill never be able to write my own libraries without being able to talk to the chip. next up when im done with 1305 is ds1615 and ds2404. thanks again to all the posters here who helped me.

entire sloppy test code, im just testing and its not optimized, just fyi.
Code: [Select]
#include <avr/interrupt.h>
#include <SPI.h>
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss
#define control 240 //READ
#define CONTROL_REG 0x0F
#define DS1305_ADDRESS_OFFSET 0x80
#define SECONDS_REG 0x00
#define MINUTES_REG 0x01
#define HOURS_REG 0x02
#define DAY_REG 0x03
#define DAY_ALARM 0x0A
#define SECONDS_ALARM 0x07
#define MINUTES_ALARM 0x08
#define HOURS_ALARM 0x09
#define DS1305_SR 0x10
#define DS1305_SR_IRQF1 1
#define DS1305_SR_IRQF0 0
boolean meridian;
void setup() {
  // set the slaveSelectPin as an output:

  unsigned int data;
  unsigned int address = 0xF0;
  SPI.begin();
  digitalWrite(SLAVESELECT,LOW);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);
  // initialize SPI:
  pinMode(2, INPUT);
  digitalWrite(2,HIGH);
  attachInterrupt(0, alarmTriggered, FALLING);
  interrupts();
  Serial.begin(9600);
  digitalWrite(SLAVESELECT, HIGH);
  writeRegister(CONTROL_REG,0x03);
  //  unsigned int r = readRegister(CONTROL_REG);
  //  Serial.println("CONTROL = ");
  //  Serial.println(r,BIN);
  //  writeRegister(SECONDS_REG,decToBcd(30));
  //  writeRegister(MINUTES_REG,decToBcd(40));
  // 
  //   
  //   
  //writeRegister(HOURS_REG,B01101000);

  writeRegister(DAY_REG,1);
  writeRegister(HOURS_ALARM,B10010010);
  writeRegister(MINUTES_ALARM,B10010010);
  writeRegister(DAY_ALARM,B10010010);
  writeRegister(SECONDS_ALARM,B1110000);

}

void loop(){

  delay(1000);



  byte seconds = bcdToDec(readRegister(SECONDS_REG));
  byte minutes = bcdToDec(readRegister(MINUTES_REG));
  //  byte hours = bcdToDec(readRegister(HOURS_REG));
  byte hours = readRegister(HOURS_REG);
  byte ampm=bitRead(hours,5);
  if (ampm==1){
    meridian=1;
  }
  else{
    meridian=0;
  }
  hours=hours &B10011111;
  byte days = readRegister(0x10);
  Serial.print(bcdToDec(hours),DEC);
  Serial.print(":");
  Serial.print(minutes,DEC);
  Serial.print(":");
  Serial.print(seconds);
  if (meridian==1){
    Serial.println(" PM");
  }
  else{
    Serial.println(" AM");
  }


  //  writeRegister(0x20,0x30);
  //  r = readRegister(0x20);
  //  Serial.println("0x20 = ");
  //  Serial.println(r,HEX);
}

unsigned int readRegister(byte thisRegister)
{
  byte inByte = 0;
  unsigned int result = 0;

  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister);
  result = SPI.transfer(0x00);
  digitalWrite(SLAVESELECT, LOW);
  return(result);
}

void writeRegister(byte thisRegister, char thisValue)
{
  digitalWrite(SLAVESELECT, HIGH);
  SPI.transfer(thisRegister+DS1305_ADDRESS_OFFSET);
  SPI.transfer(thisValue);
  digitalWrite(SLAVESELECT, LOW);
}
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

void alarmTriggered()
{
  Serial.println("** ALARM WENT OFF! **");
  writeRegister(DS1305_SR,0);
}

Go Up