@@ -94,6 +94,10 @@ static int read_calib_freq_range(void *device, char *buf, uint32_t len,
9494 const struct iio_ch_info * channel , intptr_t priv );
9595static int write_calib_freq_range (void * device , char * buf , uint32_t len ,
9696 const struct iio_ch_info * channel , intptr_t priv );
97+ static int read_calib_freq_range_reverse (void * device , char * buf , uint32_t len ,
98+ const struct iio_ch_info * channel , intptr_t priv );
99+ static int write_calib_freq_range_reverse (void * device , char * buf , uint32_t len ,
100+ const struct iio_ch_info * channel , intptr_t priv );
97101static int read_temp_freq_range (void * device , char * buf , uint32_t len ,
98102 const struct iio_ch_info * channel , intptr_t priv );
99103static int write_temp_freq_range (void * device , char * buf , uint32_t len ,
@@ -201,6 +205,55 @@ struct iio_attribute powrms_precision_attributes[] = {
201205 .store = write_calib_freq_range ,
202206 .priv = MAX_FREQ_RANGE_INDEX , // frequency index 7
203207 },
208+ // New per-frequency range attributes for reverse correction values
209+ {
210+ .name = "calib_10MHz_values_reverse" ,
211+ .show = read_calib_freq_range_reverse ,
212+ .store = write_calib_freq_range_reverse ,
213+ .priv = MIN_FREQ_RANGE_INDEX , // frequency index 0
214+ },
215+ {
216+ .name = "calib_100MHz_values_reverse" ,
217+ .show = read_calib_freq_range_reverse ,
218+ .store = write_calib_freq_range_reverse ,
219+ .priv = MIN_FREQ_RANGE_INDEX + 1 , // frequency index 1
220+ },
221+ {
222+ .name = "calib_1000MHz_values_reverse" ,
223+ .show = read_calib_freq_range_reverse ,
224+ .store = write_calib_freq_range_reverse ,
225+ .priv = MIN_FREQ_RANGE_INDEX + 2 , // frequency index 2
226+ },
227+ {
228+ .name = "calib_2000MHz_values_reverse" ,
229+ .show = read_calib_freq_range_reverse ,
230+ .store = write_calib_freq_range_reverse ,
231+ .priv = MIN_FREQ_RANGE_INDEX + 3 , // frequency index 3
232+ },
233+ {
234+ .name = "calib_3000MHz_values_reverse" ,
235+ .show = read_calib_freq_range_reverse ,
236+ .store = write_calib_freq_range_reverse ,
237+ .priv = MIN_FREQ_RANGE_INDEX + 4 , // frequency index 4
238+ },
239+ {
240+ .name = "calib_4000MHz_values_reverse" ,
241+ .show = read_calib_freq_range_reverse ,
242+ .store = write_calib_freq_range_reverse ,
243+ .priv = MIN_FREQ_RANGE_INDEX + 5 , // frequency index 5
244+ },
245+ {
246+ .name = "calib_5000MHz_values_reverse" ,
247+ .show = read_calib_freq_range_reverse ,
248+ .store = write_calib_freq_range_reverse ,
249+ .priv = MIN_FREQ_RANGE_INDEX + 6 , // frequency index 6
250+ },
251+ {
252+ .name = "calib_6000MHz_values_reverse" ,
253+ .show = read_calib_freq_range_reverse ,
254+ .store = write_calib_freq_range_reverse ,
255+ .priv = MAX_FREQ_RANGE_INDEX , // frequency index 7
256+ },
204257 // New per-frequency range attributes for temperature calibration values
205258 {
206259 .name = "calib_temp_10MHz_values" ,
@@ -600,6 +653,86 @@ static int write_calib_freq_range(void *device, char *buf, uint32_t len,
600653 return len ;
601654}
602655
656+ static int read_calib_freq_range_reverse (void * device , char * buf , uint32_t len ,
657+ const struct iio_ch_info * channel , intptr_t priv )
658+ {
659+ int freq_index = (int )priv ; // frequency range index (0-7)
660+ int written = 0 ;
661+ int remaining = len ;
662+ int start_idx = freq_index *
663+ FREQ_RANGE_VALUES_PER_RANGE ; // Starting index for this frequency range
664+
665+ // Write 14 values for this frequency range as comma-separated list
666+ for (int i = 0 ; i < FREQ_RANGE_VALUES_PER_RANGE
667+ && remaining > MIN_REMAINING_BUFFER_SIZE ; i ++ ) {
668+ float float_value = (float )precision_values_reverse [start_idx + i ] *
669+ PRECISION_RESOLUTION ;
670+ int bytes = snprintf (buf + written , remaining , "%.7f" , float_value );
671+
672+ if (bytes < 0 || bytes >= remaining )
673+ break ;
674+
675+ written += bytes ;
676+ remaining -= bytes ;
677+
678+ // Add comma separator except for last element
679+ if (i < FREQ_RANGE_VALUES_PER_RANGE - 1 && remaining > MIN_COMMA_BUFFER_SIZE ) {
680+ buf [written ++ ] = ',' ;
681+ remaining -- ;
682+ }
683+ }
684+
685+ return written ;
686+ }
687+
688+ static int write_calib_freq_range_reverse (void * device , char * buf , uint32_t len ,
689+ const struct iio_ch_info * channel , intptr_t priv )
690+ {
691+ int freq_index = (int )priv ; // frequency range index (0-7)
692+ char * token ;
693+ char * saveptr ;
694+ char buf_copy [CALIB_VALUES_BUFFER_SIZE ]; // Buffer for 14 values
695+ int index = 0 ;
696+ int start_idx = freq_index * FREQ_RANGE_VALUES_PER_RANGE ;
697+ int ret ;
698+
699+ if (len >= CALIB_VALUES_BUFFER_SIZE ) {
700+ return - EINVAL ;
701+ }
702+
703+ // Create a copy of the buffer for tokenization
704+ strncpy (buf_copy , buf , len );
705+ buf_copy [len ] = '\0' ;
706+
707+ // Parse comma-separated values
708+ token = strtok_r (buf_copy , "," , & saveptr );
709+ while (token != NULL && index < FREQ_RANGE_VALUES_PER_RANGE ) {
710+ float float_value ;
711+ if (sscanf (token , "%f" , & float_value ) == 1 ) {
712+ // Convert float to integer and store
713+ precision_values_reverse [start_idx + index ] = (int32_t )(float_value *
714+ PRECISION_SCALE_FACTOR );
715+ index ++ ;
716+ } else {
717+ return - EINVAL ;
718+ }
719+ token = strtok_r (NULL , "," , & saveptr );
720+ }
721+
722+ if (index != FREQ_RANGE_VALUES_PER_RANGE ) {
723+ return - EINVAL ; // Expected exactly 14 values
724+ }
725+
726+ // Save to EEPROM (write the entire array since EEPROM functions work with full array)
727+ ret = powrms_eeprom_write_precision_array_reverse (precision_values_reverse );
728+ if (ret != IIO_SUCCESS ) {
729+ // EEPROM write failed - values are still updated in RAM, so continue
730+ // This allows the system to function even without EEPROM persistence
731+ }
732+
733+ return len ;
734+ }
735+
603736static int read_temp_freq_range (void * device , char * buf , uint32_t len ,
604737 const struct iio_ch_info * channel , intptr_t priv )
605738{
@@ -864,6 +997,90 @@ int powrms_get_precision_array_raw(int32_t *raw_values, int max_count)
864997 return count ;
865998}
866999
1000+ // Reverse precision array utility functions for external access
1001+ int powrms_set_precision_value_reverse (int index , float value )
1002+ {
1003+ if (index < 0 || index >= PRECISION_ARRAY_SIZE )
1004+ return - EINVAL ;
1005+ // Convert float to integer for internal storage
1006+ precision_values_reverse [index ] = (int32_t )(value * PRECISION_SCALE_FACTOR );
1007+ return 0 ;
1008+ }
1009+
1010+ float powrms_get_precision_value_reverse (int index )
1011+ {
1012+ if (index < 0 || index >= PRECISION_ARRAY_SIZE )
1013+ return 0.0f ;
1014+ // Convert integer to float for external use
1015+ return (float )precision_values_reverse [index ] * PRECISION_RESOLUTION ;
1016+ }
1017+
1018+ int powrms_set_precision_array_reverse (const float * values , int count )
1019+ {
1020+ if (!values || count > PRECISION_ARRAY_SIZE )
1021+ return - EINVAL ;
1022+
1023+ for (int i = 0 ; i < count ; i ++ ) {
1024+ // Convert float to integer for internal storage
1025+ precision_values_reverse [i ] = (int32_t )(values [i ] * PRECISION_SCALE_FACTOR );
1026+ }
1027+ return 0 ;
1028+ }
1029+
1030+ int powrms_get_precision_array_reverse (float * values , int max_count )
1031+ {
1032+ if (!values )
1033+ return - EINVAL ;
1034+
1035+ int count = (max_count < PRECISION_ARRAY_SIZE ) ? max_count :
1036+ PRECISION_ARRAY_SIZE ;
1037+ for (int i = 0 ; i < count ; i ++ ) {
1038+ // Convert integer to float for external use
1039+ values [i ] = (float )precision_values_reverse [i ] * PRECISION_RESOLUTION ;
1040+ }
1041+ return count ;
1042+ }
1043+
1044+ // Direct integer access functions for MCU internal use (no conversion overhead) - reverse
1045+ int powrms_set_precision_value_raw_reverse (int index , int32_t raw_value )
1046+ {
1047+ if (index < 0 || index >= PRECISION_ARRAY_SIZE )
1048+ return - EINVAL ;
1049+ precision_values_reverse [index ] = raw_value ;
1050+ return 0 ;
1051+ }
1052+
1053+ int32_t powrms_get_precision_value_raw_reverse (int index )
1054+ {
1055+ if (index < 0 || index >= PRECISION_ARRAY_SIZE )
1056+ return 0 ;
1057+ return precision_values_reverse [index ];
1058+ }
1059+
1060+ int powrms_set_precision_array_raw_reverse (const int32_t * raw_values , int count )
1061+ {
1062+ if (!raw_values || count > PRECISION_ARRAY_SIZE )
1063+ return - EINVAL ;
1064+
1065+ for (int i = 0 ; i < count ; i ++ ) {
1066+ precision_values_reverse [i ] = raw_values [i ];
1067+ }
1068+ return 0 ;
1069+ }
1070+
1071+ int powrms_get_precision_array_raw_reverse (int32_t * raw_values , int max_count )
1072+ {
1073+ if (!raw_values )
1074+ return - EINVAL ;
1075+
1076+ int count = (max_count < PRECISION_ARRAY_SIZE ) ? max_count :
1077+ PRECISION_ARRAY_SIZE ;
1078+ for (int i = 0 ; i < count ; i ++ ) {
1079+ raw_values [i ] = precision_values_reverse [i ];
1080+ }
1081+ return count ;
1082+ }
1083+
8671084// Frequency ranges utility functions for external access
8681085int powrms_set_frequency_range (int index , uint32_t frequency_MHz )
8691086{
@@ -1040,6 +1257,10 @@ static int write_dev_mode_overwrite_def_calib_values(void *device, char *buf,
10401257 if (ret != IIO_SUCCESS ) {
10411258 return len ;
10421259 }
1260+ ret = powrms_eeprom_write_def_precision_array_reverse (precision_values_reverse );
1261+ if (ret != IIO_SUCCESS ) {
1262+ return len ;
1263+ }
10431264 ret = powrms_eeprom_write_def_temp_corr_array (temperature_precision_values );
10441265 if (ret != IIO_SUCCESS ) {
10451266 return len ;
0 commit comments