Allow any arbitrary frequency to be specified for ANU devices and try to find the nearest frequency when initialising it, reporting if the frequency is not exactly as requested.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
diff --git a/ASIC-README b/ASIC-README
index b86182b..0f97e2d 100644
--- a/ASIC-README
+++ b/ASIC-README
@@ -205,12 +205,13 @@ ANTMINER U1 DEVICES
--anu-freq <arg> Set AntminerU1 frequency in MHz, range 150-500 (default: 200)
By default, Antminer U1 devices run at a clockspeed of 200. This command allows
-you to specify a chosen frequency to attempt to run all ANU devices at and the
-value must be in increments of 25. Note that cgminer reports hashrate ONLY
-FROM VALID HASHES so if you increase the frequency but your hashrate does not
-increase or it decreases and hardware errors start showing up, you have
-overclocked it too much. In the worst case scenario it will fail to start at
-too high a speed.
+you to specify a chosen frequency to attempt to run all ANU devices at. Cgminer
+will try to find the nearest frequency the device supports and will report if
+the frequency is not exactly as requested. Note that cgminer reports hashrate
+ONLY FROM VALID HASHES so if you increase the frequency but your hashrate does
+not increase or it decreases and hardware errors start showing up, you have
+overclocked it too much. In the worst case scenario it will fail to start at too
+high a speed. Most will run happily up to 250.
AVALON AND BITBURNER DEVICES
diff --git a/cgminer.c b/cgminer.c
index a16cc1f..69a5acb 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -192,7 +192,7 @@ static bool no_work;
#ifdef USE_ICARUS
char *opt_icarus_options = NULL;
char *opt_icarus_timing = NULL;
-int opt_anu_freq = 200;
+float opt_anu_freq = 200;
#endif
bool opt_worktime;
#ifdef USE_AVALON
@@ -1078,17 +1078,13 @@ static char *set_icarus_timing(const char *arg)
return NULL;
}
-static char *set_int_150_to_500(const char *arg, int *i)
+static char *set_float_125_to_500(const char *arg, float *i)
{
- char *err = set_int_range(arg, i, 150, 500);
- int mult;
+ char *err = opt_set_floatval(arg, i);
+
+ if (*i < 125 || *i > 500)
+ return "Value out of range";
- if (err)
- return err;
- mult = *i / 25;
- mult *= 25;
- if (mult != *i)
- return "Frequency must be a multiple of 25";
return NULL;
}
#endif
@@ -1161,8 +1157,8 @@ static char *set_null(const char __maybe_unused *arg)
static struct opt_table opt_config_table[] = {
#ifdef USE_ICARUS
OPT_WITH_ARG("--anu-freq",
- set_int_150_to_500, &opt_show_intval, &opt_anu_freq,
- "Set AntminerU1 frequency in MHz, range 150-500"),
+ set_float_125_to_500, &opt_show_intval, &opt_anu_freq,
+ "Set AntminerU1 frequency in MHz, range 125-500"),
#endif
OPT_WITH_ARG("--api-allow",
set_api_allow, NULL, NULL,
diff --git a/driver-icarus.c b/driver-icarus.c
index 6e25452..a757cf4 100644
--- a/driver-icarus.c
+++ b/driver-icarus.c
@@ -38,6 +38,7 @@
#include <strings.h>
#include <sys/time.h>
#include <unistd.h>
+#include <math.h>
#include "config.h"
@@ -842,25 +843,45 @@ unsigned char crc5(unsigned char *ptr, unsigned char len)
return crc;
}
-static unsigned char anu_freq_table[] = {
- 0x05, // 150
- 0x06,
- 0x07, // 200 == default
- 0x08,
- 0x09,
- 0x0a,
- 0x0b, // 300
- 0x4c,
- 0x4d,
- 0x4e,
- 0x4f, // 400
- 0x50,
- 0x51,
- 0x52,
- 0x53 // 500
-};
+static bool anu_freqfound = false;
+static uint16_t anu_freq_hex;
-#define ANU_FREQTODATA(freq) (anu_freq_table[(freq - 150) / 25])
+static void anu_find_freqhex(void)
+{
+ float fout, best_fout = opt_anu_freq;
+ int od, nf, nr, no, n, m, bs;
+ float best_diff = 1000;
+
+ anu_freqfound = true;
+
+ for (od = 0; od < 4; od++) {
+ no = 1 << od;
+ for (n = 0; n < 16; n++) {
+ nr = n + 1;
+ for (m = 0; m < 64; m++) {
+ nf = m + 1;
+ fout = 25 * (float)nf /((float)(nr) * (float)(no));
+ if (fabsf(fout - opt_anu_freq) > best_diff)
+ continue;
+ if (500 <= (fout * no) && (fout * no) <= 1000)
+ bs = 1;
+ else
+ bs = 0;
+ best_diff = fabsf(fout - opt_anu_freq);
+ best_fout = fout;
+ anu_freq_hex = (bs << 14) | (m << 7) | (n << 2) | od;
+ if (fout == opt_anu_freq) {
+ applog(LOG_DEBUG, "ANU found exact frequency %.1f with hex %04x",
+ opt_anu_freq, anu_freq_hex);
+ return;
+ }
+ }
+ }
+ }
+ opt_anu_freq = best_fout;
+ applog(LOG_NOTICE, "ANU found nearest frequency %.1f with hex %04x", opt_anu_freq,
+ anu_freq_hex);
+}
static bool set_anu_freq(struct cgpu_info *icarus, struct ICARUS_INFO *info)
{
@@ -868,11 +889,13 @@ static bool set_anu_freq(struct cgpu_info *icarus, struct ICARUS_INFO *info)
int amount, err;
char buf[512];
+ if (!anu_freqfound)
+ anu_find_freqhex();
memset(cmd_buf, 0, 4);
memset(rdreg_buf, 0, 4);
cmd_buf[0] = 2 | 0x80;
- cmd_buf[1] = ANU_FREQTODATA(opt_anu_freq); //16-23
- cmd_buf[2] = 0x81; //8-15
+ cmd_buf[1] = (anu_freq_hex & 0xff00u) >> 8;
+ cmd_buf[2] = (anu_freq_hex & 0x00ffu);
cmd_buf[3] = crc5(cmd_buf, 27);
rdreg_buf[0] = 4 | 0x80;
diff --git a/miner.h b/miner.h
index cfcf754..88833ff 100644
--- a/miner.h
+++ b/miner.h
@@ -968,7 +968,7 @@ extern bool opt_restart;
#ifdef USE_ICARUS
extern char *opt_icarus_options;
extern char *opt_icarus_timing;
-extern int opt_anu_freq;
+extern float opt_anu_freq;
#endif
extern bool opt_worktime;
#ifdef USE_AVALON