You are reading a single comment by @DrAzzy and its replies. Click here to read the full conversation.
  • 
      /*
    This module interfaces with OneWire EEPROMs like the DS24B33, DS2431, and DS28EC20.  
    
    Usage: 
    
    Setup onewire, then call:
    
    var eeprom=require("DSmem").connect(onewire, pagesize, capacity, nopartial, device)
    
    onewire is the OneWire bus object. 
    
    pagesize is the page size for page writes, in bytes. 
    
    capacity is the eeprom capacity, in kbits. 
    
    nopartial is true for devices that cannot start a write except on a page boundary, otherwise undefined or false. 
    
    device is the code identifying the device, or it's number in the search. Optional - if undefined, the first device will be assumed. 
    
    eeprom.read(address,bytes,asStr)
    Read the specified number of bytes. If asStr is true, it will return the value as a string. 
    
    eeprom.write(address,data)
    Write the specified data starting at the specified address. Writes that cross page boundaries are handled transparently.  
    
    Additionally, this includes the helper function, which converts arrays of bytes to strings:
    eeprom.aToS(array);
    
    */
    
    exports.connect = function(ow, pgsz, cap,n,device) {
    		return new OWmem(ow, pgsz, cap,n,device);
    };
    
    function OWmem(ow, pgsz, cap,n, device) {
    	this.ow = ow;
    	this.np=n;
    	this.code=(device===undefined)?ow.search()[0]:(typeof device=="string"?device:ow.search[device]);
    	this.pgsz=pgsz
    	this.cap=cap<<7;
    }
    OWmem.prototype.aToS= function(a) {
    	var s = "";
    	for (var i in a)
    		s+=String.fromCharCode(a[i]);
    	return s;
    };
    OWmem.prototype.s=function(cmd) {
    	this.ow.reset();
    	this.ow.select(this.code)
    	for (var i=0;i<cmd.length;i++) {
    		this.ow.write(cmd[i],i==3);
    	}
    }
    
    OWmem.prototype.write= function (addr, data) {
    	if(addr+data.length > this.cap) throw "Write exceeds size"; //CRITICAL to test for this, as writing to the addresses right after the normal address space can set the EEPROM read-only (forever)!
    	if(typeof data=="object"){data=this.aToS(data);}
    	if(this.np&&(addr%this.pgsz)){ //if it's a device that doesn't support writes not starting at page boundary, and that's what we're doing 
    		data=this.read(addr-(addr%this.pgsz),addr%this.pgsz,1)+data; //read the data on the page before the target address;
    		addr-=addr%this.pgsz; //and set the address to the start of the page; 
    	}
    	while (data.length>0) {
    		var l = data.length;
    		if (l>(this.pgsz-(addr%this.pgsz))) {l=this.pgsz-(addr%this.pgsz); }// Writes must align on page boundaries, so if we don't start at one, account for that. 
    		this.s([0x0F,addr&0xFF,addr>>8]); //write to spad with address
    		for (var i=0;i<l;i++) {
    			this.ow.write(data.charCodeAt(i)); //write out the data.
    		}
    		this.s([0xAA]); //read spad.
    		//room for improvement: Manufacturer recommends reading back the scratch pad completely, and verifying it aginast the data, before comitting it. 
    		this.s([0x55,this.ow.read(),this.ow.read(),this.ow.read()]); 
    		var et=getTime()+0.07; while (getTime() < et) {"";} //delay(7) - it says it needs 5, but let's not rush it.
    		if (this.ow.read()==170) { //check for the indication of successful write - if not, we'll try again per datasheet. 
    			// get ready for next iteration, if there is one
    			data=data.substr(l);
    			addr+=l;
    		}
    	}
    }
    OWmem.prototype.read = function (addr, cnt, asStr) {
    	this.s([0xF0,addr&0xFF,addr>>8]);//select address
    	var res = new Uint8Array(cnt);
    	for (i=0;i<cnt;i++){
    		res[i]=this.ow.read();
    	}
    	return (asStr?this.aToS(res):res);
    }
    
    

    Thoughts on naming? writing more efficient JS?

    Tested with DS24B33 and DS28EC20, and should work on DS2431, if i followed the datasheet correctly.

About

Avatar for DrAzzy @DrAzzy started