forked from myorangedragon/longmynd
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnim.c
207 lines (172 loc) · 10.8 KB
/
nim.c
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/* -------------------------------------------------------------------------------------------------- */
/* The LongMynd receiver: nim.c */
/* - an implementation of the Serit NIM controlling software for the MiniTiouner Hardware */
/* - handlers for the nim module itself */
/* Copyright 2019 Heather Lomond */
/* -------------------------------------------------------------------------------------------------- */
/*
This file is part of longmynd.
Longmynd is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Longmynd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with longmynd. If not, see <https://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------------------------------- */
/* ----------------- INCLUDES ----------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "nim.h"
#include "ftdi.h"
#include "errors.h"
/* -------------------------------------------------------------------------------------------------- */
/* ----------------- GLOBALS ------------------------------------------------------------------------ */
/* -------------------------------------------------------------------------------------------------- */
/* The tuner and LNAs are accessed by turning on the I2C bus repeater in the demodulator
this reduces the noise on the tuner I2C lines as they are inactive when the repeater
is turned off. We need to keep track of this when we access the NIM */
bool repeater_on;
/* -------------------------------------------------------------------------------------------------- */
/* ----------------- ROUTINES ----------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_read_demod(uint16_t reg, uint8_t *val) {
/* -------------------------------------------------------------------------------------------------- */
/* reads a demodulator register and takes care of the i2c bus repeater */
/* reg: which demod register to read */
/* val: where to put the result */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
/* if we are not using the tuner or lna any more then we can turn off
the repeater to reduce noise
this is bit 7 of the Px_I2CRPT register. Other bits define I2C speed etc. */
if (repeater_on) {
repeater_on=false;
err=nim_write_demod(0xf12a,0x38);
}
if (err==ERROR_NONE) err=ftdi_i2c_read_reg16(NIM_DEMOD_ADDR,reg,val);
if (err!=ERROR_NONE) printf("ERROR: demod read 0x%.4x\n",reg);
/* note we don't turn the repeater off as there might be other r/w to tuner/LNAs */
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_write_demod(uint16_t reg, uint8_t val) {
/* -------------------------------------------------------------------------------------------------- */
/* writes to a demodulator register and takes care of the i2c bus repeater */
/* reg: which demod register to write to */
/* val: what to write to it */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
if (repeater_on) {
repeater_on=false;
err=nim_write_demod(0xf12a,0x38);
}
if (err==ERROR_NONE) err=ftdi_i2c_write_reg16(NIM_DEMOD_ADDR,reg,val);
if (err!=ERROR_NONE) printf("ERROR: demod write 0x%.4x, 0x%.2x\n",reg,val);
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_read_lna(uint8_t lna_addr, uint8_t reg, uint8_t *val) {
/* -------------------------------------------------------------------------------------------------- */
/* reads from the specified lna taking care of the i2c bus repeater */
/* lna_addr: i2c address of the lna to access */
/* reg: which lna register to read */
/* val: where to put the result */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
if (!repeater_on) {
err=nim_write_demod(0xf12a,0xb8);
repeater_on=true;
}
if (err==ERROR_NONE) err=ftdi_i2c_read_reg8(lna_addr,reg,val);
if (err!=ERROR_NONE) printf("ERROR: lna read 0x%.2x, 0x%.2x\n",lna_addr,reg);
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_write_lna(uint8_t lna_addr, uint8_t reg, uint8_t val) {
/* -------------------------------------------------------------------------------------------------- */
/* writes to the specified lna taking care of the i2c bus repeater */
/* lna_addr: i2c address of the lna to access */
/* reg: which lna register to write to */
/* val: what to write to it */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
if (!repeater_on) {
err=nim_write_demod(0xf12a,0xb8);
repeater_on=true;
}
if (err==ERROR_NONE) err=ftdi_i2c_write_reg8(lna_addr,reg,val);
if (err!=ERROR_NONE) printf("ERROR: lna write 0x%.2x, 0x%.2x,0x%.2x\n",lna_addr,reg,val);
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_read_tuner(uint8_t reg, uint8_t *val) {
/* -------------------------------------------------------------------------------------------------- */
/* reads from the stv0910 (tuner) taking care of the i2c bus repeater */
/* reg: which tuner register to read from */
/* val: where to put the result */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
if (!repeater_on) {
err=nim_write_demod(0xf12a,0xb8);
repeater_on=true;
}
if (err==ERROR_NONE) err=ftdi_i2c_read_reg8(NIM_TUNER_ADDR,reg,val);
if (err!=ERROR_NONE) printf("ERROR: tuner read 0x%.2x\n",reg);
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_write_tuner(uint8_t reg, uint8_t val) {
/* -------------------------------------------------------------------------------------------------- */
/* writes to the stv0910 (tuner) taking care of the i2c bus repeater */
/* reg: which tuner register to write to */
/* val: what to write to it */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
if (!repeater_on) {
err=nim_write_demod(0xf12a,0xb8);
repeater_on=true;
}
if (err==ERROR_NONE) err=ftdi_i2c_write_reg8(NIM_TUNER_ADDR,reg,val);
if (err!=ERROR_NONE) printf("ERROR: tuner write %i,%i\n",reg,val);
return err;
}
/* -------------------------------------------------------------------------------------------------- */
uint8_t nim_init() {
/* -------------------------------------------------------------------------------------------------- */
/* initialises the nim (at the highest level) */
/* return: error code */
/* -------------------------------------------------------------------------------------------------- */
uint8_t err=ERROR_NONE;
uint8_t val;
printf("Flow: NIM init\n");
repeater_on = false;
/* check we can read and write a register */
/* check to see if we can write and readback to a demod register */
if (err==ERROR_NONE) err=nim_write_demod(0xf536,0xaa); /* random reg with alternating bits */
if (err==ERROR_NONE) err=nim_read_demod(0xf536,&val);
if (err==ERROR_NONE) {
if (val!=0xaa) { /* check alternating bits ok */
printf("ERROR: nim_init didn't r/w to the modulator\n");
err=ERROR_NIM_INIT;
}
}
/* we always want to start with the i2c repeater turned off */
if (err!=ERROR_NONE) err=nim_write_demod(0xf12a,0x38);
if (err!=ERROR_NONE) printf("ERROR: nim_init\n");
return err;
}