1616#include < EEPROM.h>
1717#include " SpdReaderWriterSettings.h" // Settings
1818
19- #define VERSION 20211119 // Version number (YYYYMMDD)
19+ #define VERSION 20211201 // Version number (YYYYMMDD)
2020
2121// RSWP RAM support bitmasks
2222#define DDR5 (1 << 5 ) // Offline mode control
102102#define GETVERSION ' v' // Get FW version
103103#define TESTCOMM ' t' // Test communication
104104#define RSWPREPORT ' f' // Initial supported RSWP capabilities
105+ #define RETESTRSWP ' e' // Reevaluate supported RSWP capabilities
105106#define DDR4DETECT ' 4' // DDR4 detection test
106107#define DDR5DETECT ' 5' // DDR5 detection test
107- #define RETESTRSWP ' e' // Reevaluate RSWP capabilities
108108#define FACTORYRESET ' -' // Factory reset device settings
109109#pragma endregion
110110
111- // Device pin names
112- #define OFFLINE_MODE_SWITCH 0 // Pin to toggle SPD5 offline mode
113- #define SA1_SWITCH 1 // Pin to toggle SA1 state
114- #define HIGH_VOLTAGE_SWITCH 9 // Pin to toggle VHV on SA0 pin
115-
116- // Device responses
117- #define SUCCESS (byte) 0x01
118- #define ERROR (byte) 0xFF
119- #define ZERO (byte) 0x00
120- #define WELCOME (char ) ' !'
121- #define UNKNOWN (char ) ' ?'
111+ // Device pin names (SpdReaderWriterDll.Pin.Name class)
112+ #define OFFLINE_MODE_SWITCH (uint8_t ) 0 // Pin to toggle SPD5 offline mode
113+ #define SA1_SWITCH (uint8_t ) 1 // Pin to toggle SA1 state
114+ #define HIGH_VOLTAGE_SWITCH (uint8_t ) 9 // Pin to toggle VHV on SA0 pin
122115
123116// Pin states
124117#define ON HIGH
129122#define RESET (byte) 0x00
130123#define GET (char ) ' ?' // Suffix added to commands to return current state
131124
125+ // Device responses
126+ #define SUCCESS (byte) 0x01
127+ #define ERROR (byte) 0xFF
128+ #define ZERO (byte) 0x00
129+ #define WELCOME (char ) ' !'
130+ #define UNKNOWN (char ) ' ?'
131+
132132// Device name settings
133133#define NAMELENGTH 16
134134char deviceName[NAMELENGTH];
@@ -378,7 +378,7 @@ void cmdRetestRswp() {
378378}
379379
380380void cmdDdr4Detect () {
381- // Data buffer for address
381+ // Data buffer for i2c address
382382 byte buffer[1 ];
383383 PORT.readBytes (buffer, sizeof (buffer));
384384
@@ -387,7 +387,7 @@ void cmdDdr4Detect() {
387387}
388388
389389void cmdDdr5Detect () {
390- // Data buffer for address
390+ // Data buffer for i2c address
391391 byte buffer[1 ];
392392 PORT.readBytes (buffer, sizeof (buffer));
393393
@@ -567,7 +567,7 @@ void cmdPinControl() {
567567 // VHV 9V controls
568568 else if (pin == HIGH_VOLTAGE_SWITCH) {
569569 // Toggle HV state
570- if (state == 0 || state == 1 ) {
570+ if (state == ENABLE || state == DISABLE ) {
571571 PORT.write (setHighVoltage (state) ? SUCCESS : ERROR);
572572 }
573573 // Get HV state
@@ -658,12 +658,15 @@ bool setRswp(uint8_t block) {
658658 byte commands[] = { SWP0, SWP1, SWP2, SWP3 };
659659 byte cmd = (block > 0 || block <= 3 ) ? commands[block] : commands[0 ];
660660
661- setHighVoltage (ON);
662- setConfigPin (SA1_EN, OFF); // Required for pre-DDR4
663- bool result = probeDeviceTypeId (cmd);
664- resetPins ();
661+ if ( setHighVoltage (ON)) {
662+ setConfigPin (SA1_EN, OFF); // Required for pre-DDR4
663+ bool result = probeDeviceTypeId (cmd);
664+ resetPins ();
665665
666- return result;
666+ return result;
667+ }
668+
669+ return false ;
667670}
668671
669672// Reads reversible write protection status
@@ -680,12 +683,15 @@ bool getRswp(uint8_t block) {
680683// Clears reversible software write protection
681684bool clearRswp () {
682685
683- setHighVoltage (ON);
684- setConfigPin (SA1_EN, ON); // Required for pre-DDR4
685- bool result = probeDeviceTypeId (CWP);
686- resetPins ();
686+ if ( setHighVoltage (ON)) {
687+ setConfigPin (SA1_EN, ON); // Required for pre-DDR4
688+ bool result = probeDeviceTypeId (CWP);
689+ resetPins ();
687690
688- return result;
691+ return result;
692+ }
693+
694+ return false ;
689695}
690696
691697// Test RSWP support capabilities
@@ -807,7 +813,7 @@ uint8_t getPageAddress(bool lowLevel = false) {
807813
808814#ifdef __AVR__
809815
810- uint8_t status = 0 ;
816+ uint8_t status = ERROR ;
811817
812818 // Send start condition
813819 TWCR = _BV (TWEN) | _BV (TWINT) | _BV (TWEA) | _BV (TWSTA);
@@ -830,16 +836,14 @@ uint8_t getPageAddress(bool lowLevel = false) {
830836 // Check status (0x40 = ACK = page 0; 0x48 = NACK = page 1)
831837 status = (TWSR & 0xF8 );
832838
833- // Write 2xDNC after ACK. If status is NACK (0x48), stop and return 1
834- /*
839+ // Write 2xDNC after control byte
835840 if (status == 0x40 ) {
836841 for (int i = 0 ; i < 2 ; i++) {
837842 TWDR = DNC;
838843 TWCR = _BV (TWEN) | _BV (TWEA) | _BV (TWINT);
839844 while (!(TWCR & (_BV (TWINT)))) {}
840845 }
841846 }
842- */
843847
844848 // Send stop condition
845849 TWCR = _BV (TWEN) | _BV (TWINT) | _BV (TWEA) | _BV (TWSTO);
@@ -848,7 +852,7 @@ uint8_t getPageAddress(bool lowLevel = false) {
848852 switch (status) {
849853 case 0x40 : return 0 ;
850854 case 0x48 : return 1 ;
851- default : return ERROR ;
855+ default : return status ;
852856 }
853857
854858#endif
@@ -858,12 +862,14 @@ uint8_t getPageAddress(bool lowLevel = false) {
858862}
859863
860864// Sets page address to access lower or upper 256 bytes of DDR4 SPD
861- void setPageAddress (uint8_t pageNumber) {
865+ bool setPageAddress (uint8_t pageNumber) {
862866
863867 if (pageNumber < 2 ) {
864868 probeDeviceTypeId ((pageNumber == 0 ) ? SPA0 : SPA1);
865869 eepromPageAddress = pageNumber;
870+ return true ;
866871 }
872+ return false ;
867873}
868874
869875// Adjusts page address according to byte offset specified
@@ -948,7 +954,7 @@ bool setI2cClockMode(bool mode) {
948954 i2cClock = mode ? 400000 : 100000 ;
949955 Wire.setClock (i2cClock);
950956
951- return getI2cClockMode ();
957+ return getI2cClockMode () == mode ;
952958}
953959
954960// Gets saved I2C clock mode (true=fast mode, false=std mode)
@@ -1038,61 +1044,8 @@ bool ddr4Detect(uint8_t address) {
10381044 return false ;
10391045 }
10401046
1041- bool result = true ;
1042- bool avrCpu = true ;
1043- byte eePage = 128 ;
1044-
1045- for (uint8_t i = 0 ; i <= 1 ; i++) {
1046- setPageAddress (i);
1047- eePage = getPageAddress (true );
1048- if (eePage == ERROR) { // unsupported hardware, switch to alternative methods
1049- avrCpu = false ;
1050- break ;
1051- }
1052- if (eePage != i && eePage != ERROR ) {
1053- result = false ;
1054- break ;
1055- }
1056- }
1057-
1058- if (avrCpu) {
1059- return result;
1060- }
1061-
1062- // Alternative methods for non-AVR controllers
1063-
1064- result = false ; // presume DDR4 is not present
1065-
1066- // Read protection status of blocks 1-3, if at least one is unprotected, return true.
1067- for (uint8_t i = 1 ; i <= 3 ; i++) {
1068- if (getRswp (i)) {
1069- return true ;
1070- }
1071- }
1072-
1073- // Check for TS registers, if present, return true.
1074- if (probeBusAddress (TSRB << 3 | address & 0b111 )) {
1075- return true ;
1076- }
1077-
1078- // Read data from 2 pages, if contents don't match, return true.
1079- uint8_t pageSize = 16 ;
1080- byte page0[pageSize];
1081- byte page1[pageSize];
1082-
1083- for (uint16_t i = 0 ; i <= 256 ; i += pageSize) {
1084-
1085- readByte (address, i, pageSize, page0); // Read page 0
1086- readByte (address, i + 256 , pageSize, page1); // Read page 1
1087-
1088- for (uint8_t j = 0 ; j < pageSize; j++) {
1089- if (page0[j] != page1[j]) {
1090- return true ;
1091- }
1092- }
1093- }
1094-
1095- return result;
1047+ return ((setPageAddress (0 ) ^ getPageAddress (true )) !=
1048+ (setPageAddress (1 ) ^ getPageAddress (true )));
10961049}
10971050
10981051// DDR5 detetion
@@ -1111,10 +1064,10 @@ bool ddr5Detect(uint8_t address) {
11111064
11121065// Restores device's default settings
11131066bool factoryReset () {
1114- for (uint8_t i = 0 ; i < 32 ; i++) {
1067+ for (uint8_t i = 0 ; i <= 32 ; i++) {
11151068 EEPROM.update (i, ZERO);
11161069 }
1117- for (uint8_t i = 0 ; i < 32 ; i++) {
1070+ for (uint8_t i = 0 ; i <= 32 ; i++) {
11181071 if (EEPROM.read (i) != ZERO) {
11191072 return false ;
11201073 }
0 commit comments