Compare commits
6 Commits
a20dddb9d0
...
5649eb59b8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5649eb59b8 | ||
![]() |
86d30c02ec | ||
![]() |
58ba467538 | ||
![]() |
625502a04e | ||
![]() |
e6e9efd73e | ||
![]() |
21e95b8d3a |
106
README.md
106
README.md
@ -1,3 +1,109 @@
|
|||||||
# cat-tracker
|
# cat-tracker
|
||||||
|
|
||||||
A multi-function application designed to run on a pi node. When used in a mesh network, this app will help track your cat with a CC2500 based radio collar, using complementary CC2500 based radio modules interfaced with your Pi.
|
A multi-function application designed to run on a pi node. When used in a mesh network, this app will help track your cat with a CC2500 based radio collar, using complementary CC2500 based radio modules interfaced with your Pi.
|
||||||
|
|
||||||
|
The implementation here uses CC2500 register values which intend to mimic my [Girafus M07A](https://www.girafus.com/en-en/collections/peilsender/products/ersatzteil-basismodul-fur-girafus%C2%AE-pro-track-tor-katzen-hunde-haustier-kleintier-sucher) unit. This unit is paired with my associated [tracker](https://www.girafus.com/en-en/collections/peilsender/products/extra-sender-tag-fur-den-girafus%C2%AE-pro-track-tor-haustier-hund-katze-kleintier-finder-sucher-ortung)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
* [Arduion Forum Port](https://forum.arduino.cc/t/replicating-a-signal-from-a-locating-device-2-4ghz-to-locate-tag/321993/2)
|
||||||
|
* [cc2500 data sheet](./cc2500.pdf)
|
||||||
|
* [C Code transciever example](https://github.com/alexbirkett/cc2500-raspberry-pi)
|
||||||
|
|
||||||
|
## CC2500 to Raspberry Pi GPIO Pin Mapping
|
||||||
|
|
||||||
|
| CC2500 Pin | Function Description | Raspberry Pi GPIO Pin | GPIO Number |
|
||||||
|
|------------|------------------------------------------------------|-------------------------------|-------------|
|
||||||
|
| GND | Ground | Pin 6 | - |
|
||||||
|
| VCC | 3.3V Power (⚠️ **Do not use 5V**) | Pin 1 or Pin 17 | - |
|
||||||
|
|
||||||
|
### SPI Connections
|
||||||
|
|
||||||
|
| CC2500 Pin | Function | Raspberry Pi GPIO Pin | GPIO Number |
|
||||||
|
|------------|----------|-------------------------------|-------------|
|
||||||
|
| SI | MOSI | Pin 19 | GPIO 10 |
|
||||||
|
| SCK | SCLK | Pin 23 | GPIO 11 |
|
||||||
|
| CSN | CE0 (Chip Select) | Pin 24 | GPIO 8 |
|
||||||
|
| SO | MISO | Pin 21 | GPIO 9 |
|
||||||
|
|
||||||
|
### Optional Pins
|
||||||
|
|
||||||
|
| CC2500 Pin | Function | Raspberry Pi GPIO Pin | GPIO Number |
|
||||||
|
|------------|-------------------------------------------|-------------------------------|-------------|
|
||||||
|
| GDO0 | Interrupt/Data Ready | Pin 12 | GPIO 18 |
|
||||||
|
| GDO2 | Additional Interrupt/Data Line | Pin 22 | GPIO 25 |
|
||||||
|
|
||||||
|
### Power Amplifier Pins (If Applicable)
|
||||||
|
|
||||||
|
| CC2500 Pin | Function | Raspberry Pi GPIO Pin | Notes |
|
||||||
|
|------------|-------------------------------------------|-------------------------------|----------------------------------------|
|
||||||
|
| PA_EN | Control Power Amplifier (Optional) | Any GPIO Pin | Connect if amplifier control is needed |
|
||||||
|
| PA_EX | Reserved | Not Connected | Only connect if required |
|
||||||
|
|
||||||
|
## Reverse Engineering the Registers
|
||||||
|
|
||||||
|
### SmartRF Studio
|
||||||
|
|
||||||
|
#### Install
|
||||||
|
[SmartRF Studio](https://www.ti.com/tool/SMARTRFTM-STUDIO#downloads) will automatically generate a configuration for the CC2500 Radio based on some RF parameters
|
||||||
|
* A free registration and login is required to download this app from Texas Instruments
|
||||||
|
* The app seems to run well via `wine` on linux. I chose to install it on an actual Windows OS, then copy the binaries.
|
||||||
|
|
||||||
|
#### Copy Register JSON template
|
||||||
|
When this is installed, copy the code export json file to help export the initial register configuration in a JSON format
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp srfexp_json.xml "~/Documents/Texas Instruments/SmartRF Studio v7/codeexport/."
|
||||||
|
# Example copy command for linux+wine
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Understanding necessary RF Parameters
|
||||||
|
In SmartRF Studio, open the CC2500 Device Controller under the 2.4 GHZ list.
|
||||||
|
|
||||||
|
At the time of writing, it is believed this device uses 250 kBaud MSK encoding. We will choose this option.
|
||||||
|
|
||||||
|
Next we need to figure out the Base Frequency, Channel numbers, and Channel Spacing
|
||||||
|

|
||||||
|
|
||||||
|
### Singal Capture
|
||||||
|
I have captured the initial signal emitted by the handheld unit when it is first powered on. To do this, I have used a HackRF SDR + gqrx application on linux.
|
||||||
|
|
||||||
|
The known frequency range is 2400 – 2483.5 MHz, and my SDR has a 20 MHZ bandwidth. I choose sweep for signals by tuning the following frequencies
|
||||||
|
| Sweep # | Center Frequency | Center Frequency (kHz) | Approx. Coverage (MHz) | Approx. Coverage (kHz) |
|
||||||
|
|---------|------------------|-------------------------|-------------------------|-----------------------------|
|
||||||
|
| 1 | 2410 MHz | 2,410,000 kHz | 2400 – 2420 MHz | 2,400,000 – 2,420,000 kHz |
|
||||||
|
| 2 | 2430 MHz | 2,430,000 kHz | 2420 – 2440 MHz | 2,420,000 – 2,440,000 kHz |
|
||||||
|
| 3 | 2450 MHz | 2,450,000 kHz | 2440 – 2460 MHz | 2,440,000 – 2,460,000 kHz |
|
||||||
|
| 4 | 2470 MHz | 2,470,000 kHz | 2460 – 2480 MHz | 2,460,000 – 2,480,000 kHz |
|
||||||
|
| 5 | 2483.5 MHz | 2,483,500 kHz | 2473.5 – 2483.5 MHz | 2,473,500 – 2,483,500 kHz |
|
||||||
|
|
||||||
|
#### Signal 00
|
||||||
|
2.423257000 GHz | 2423.257000 MHz | 2423257.000 kHz |
|
||||||
|

|
||||||
|
#### Signal 0
|
||||||
|
2.431258000 GHz | 2431.258000 MHz| 2431258.000 kHz
|
||||||
|

|
||||||
|
#### Signal 1
|
||||||
|
2.447257000 GHz | 2447.257000 MHz | 2447257.000 kHz
|
||||||
|

|
||||||
|
#### Signal 2
|
||||||
|
2.450225000 GHz | 2450.225000 MHz | 2450225.000 kHz
|
||||||
|

|
||||||
|
#### Signal 3
|
||||||
|
2.471275000 GHz | 2471.275000 MHz | 2471275.000 kHz
|
||||||
|

|
||||||
|
|
||||||
|
#### Signal Summary
|
||||||
|
|
||||||
|
Base frequency: ? MHz
|
||||||
|
Date Rate ? Baud
|
||||||
|
Channel spacing: ? kHz
|
||||||
|
Signal channels:
|
||||||
|
Signal 00 → Channel ?
|
||||||
|
Signal 0 → Channel ?
|
||||||
|
Signal 1 → Channel ?
|
||||||
|
Signal 2 → Channel ?
|
||||||
|
Signal 3 → Channel ?
|
||||||
|
|
||||||
|
|
||||||
|
## Run
|
||||||
|
`python3 read.py`
|
BIN
cc2500.pdf
Normal file
BIN
cc2500.pdf
Normal file
Binary file not shown.
21
cc2500_init.json
Normal file
21
cc2500_init.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"IOCFG0" : { "hex":"0x06", "dec":6},
|
||||||
|
"PKTCTRL0": { "hex":"0x05", "dec":5},
|
||||||
|
"FSCTRL1" : { "hex":"0x0A", "dec":10},
|
||||||
|
"FREQ1" : { "hex":"0x20", "dec":32},
|
||||||
|
"FREQ0" : { "hex":"0x11", "dec":17},
|
||||||
|
"MDMCFG4" : { "hex":"0x2D", "dec":45},
|
||||||
|
"MDMCFG3" : { "hex":"0x3B", "dec":59},
|
||||||
|
"MDMCFG2" : { "hex":"0x73", "dec":115},
|
||||||
|
"DEVIATN" : { "hex":"0x00", "dec":0},
|
||||||
|
"MCSM0" : { "hex":"0x18", "dec":24},
|
||||||
|
"FOCCFG" : { "hex":"0x1D", "dec":29},
|
||||||
|
"BSCFG" : { "hex":"0x1C", "dec":28},
|
||||||
|
"AGCCTRL2": { "hex":"0xC7", "dec":199},
|
||||||
|
"AGCCTRL1": { "hex":"0x00", "dec":0},
|
||||||
|
"AGCCTRL0": { "hex":"0xB0", "dec":176},
|
||||||
|
"FREND1" : { "hex":"0xB6", "dec":182},
|
||||||
|
"FSCAL3" : { "hex":"0xEA", "dec":234},
|
||||||
|
"FSCAL1" : { "hex":"0x00", "dec":0},
|
||||||
|
"FSCAL0" : { "hex":"0x11", "dec":17}
|
||||||
|
}
|
97
cc2500_regs.json
Normal file
97
cc2500_regs.json
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
{
|
||||||
|
"CONFIG_REGS": {
|
||||||
|
"IOCFG2": {"hex": "0x00", "dec": 0},
|
||||||
|
"IOCFG1": {"hex": "0x01", "dec": 1},
|
||||||
|
"IOCFG0": {"hex": "0x02", "dec": 2},
|
||||||
|
"FIFOTHR": {"hex": "0x03", "dec": 3},
|
||||||
|
"SYNC1": {"hex": "0x04", "dec": 4},
|
||||||
|
"SYNC0": {"hex": "0x05", "dec": 5},
|
||||||
|
"PKTLEN": {"hex": "0x06", "dec": 6},
|
||||||
|
"PKTCTRL1": {"hex": "0x07", "dec": 7},
|
||||||
|
"PKTCTRL0": {"hex": "0x08", "dec": 8},
|
||||||
|
"ADDR": {"hex": "0x09", "dec": 9},
|
||||||
|
"CHANNR": {"hex": "0x0A", "dec": 10},
|
||||||
|
"FSCTRL1": {"hex": "0x0B", "dec": 11},
|
||||||
|
"FSCTRL0": {"hex": "0x0C", "dec": 12},
|
||||||
|
"FREQ2": {"hex": "0x0D", "dec": 13},
|
||||||
|
"FREQ1": {"hex": "0x0E", "dec": 14},
|
||||||
|
"FREQ0": {"hex": "0x0F", "dec": 15},
|
||||||
|
"MDMCFG4": {"hex": "0x10", "dec": 16},
|
||||||
|
"MDMCFG3": {"hex": "0x11", "dec": 17},
|
||||||
|
"MDMCFG2": {"hex": "0x12", "dec": 18},
|
||||||
|
"MDMCFG1": {"hex": "0x13", "dec": 19},
|
||||||
|
"MDMCFG0": {"hex": "0x14", "dec": 20},
|
||||||
|
"DEVIATN": {"hex": "0x15", "dec": 21},
|
||||||
|
"MCSM2": {"hex": "0x16", "dec": 22},
|
||||||
|
"MCSM1": {"hex": "0x17", "dec": 23},
|
||||||
|
"MCSM0": {"hex": "0x18", "dec": 24},
|
||||||
|
"FOCCFG": {"hex": "0x19", "dec": 25},
|
||||||
|
"BSCFG": {"hex": "0x1A", "dec": 26},
|
||||||
|
"AGCCTRL2": {"hex": "0x1B", "dec": 27},
|
||||||
|
"AGCCTRL1": {"hex": "0x1C", "dec": 28},
|
||||||
|
"AGCCTRL0": {"hex": "0x1D", "dec": 29},
|
||||||
|
"WOREVT1": {"hex": "0x1E", "dec": 30},
|
||||||
|
"WOREVT0": {"hex": "0x1F", "dec": 31},
|
||||||
|
"WORCTRL": {"hex": "0x20", "dec": 32},
|
||||||
|
"FREND1": {"hex": "0x21", "dec": 33},
|
||||||
|
"FREND0": {"hex": "0x22", "dec": 34},
|
||||||
|
"FSCAL3": {"hex": "0x23", "dec": 35},
|
||||||
|
"FSCAL2": {"hex": "0x24", "dec": 36},
|
||||||
|
"FSCAL1": {"hex": "0x25", "dec": 37},
|
||||||
|
"FSCAL0": {"hex": "0x26", "dec": 38},
|
||||||
|
"RCCTRL1": {"hex": "0x27", "dec": 39},
|
||||||
|
"RCCTRL0": {"hex": "0x28", "dec": 40},
|
||||||
|
"FSTEST": {"hex": "0x29", "dec": 41},
|
||||||
|
"PTEST": {"hex": "0x2A", "dec": 42},
|
||||||
|
"AGCTEST": {"hex": "0x2B", "dec": 43},
|
||||||
|
"TEST2": {"hex": "0x2C", "dec": 44},
|
||||||
|
"TEST1": {"hex": "0x2D", "dec": 45},
|
||||||
|
"TEST0": {"hex": "0x2E", "dec": 46}
|
||||||
|
},
|
||||||
|
"STROBES": {
|
||||||
|
"SRES": {"hex": "0x30", "dec": 48},
|
||||||
|
"SFSTXON": {"hex": "0x31", "dec": 49},
|
||||||
|
"SXOFF": {"hex": "0x32", "dec": 50},
|
||||||
|
"SCAL": {"hex": "0x33", "dec": 51},
|
||||||
|
"SRX": {"hex": "0x34", "dec": 52},
|
||||||
|
"STX": {"hex": "0x35", "dec": 53},
|
||||||
|
"SIDLE": {"hex": "0x36", "dec": 54},
|
||||||
|
"SAFC": {"hex": "0x37", "dec": 55},
|
||||||
|
"SWOR": {"hex": "0x38", "dec": 56},
|
||||||
|
"SPWD": {"hex": "0x39", "dec": 57},
|
||||||
|
"SFRX": {"hex": "0x3A", "dec": 58},
|
||||||
|
"SFTX": {"hex": "0x3B", "dec": 59},
|
||||||
|
"SWORRST": {"hex": "0x3C", "dec": 60},
|
||||||
|
"SNOP": {"hex": "0x3D", "dec": 61}
|
||||||
|
},
|
||||||
|
"STATUS": {
|
||||||
|
"PARTNUM": {"hex": "0x30", "dec": 48},
|
||||||
|
"VERSION": {"hex": "0x31", "dec": 49},
|
||||||
|
"FREQEST": {"hex": "0x32", "dec": 50},
|
||||||
|
"LQI": {"hex": "0x33", "dec": 51},
|
||||||
|
"RSSI": {"hex": "0x34", "dec": 52},
|
||||||
|
"MARCSTATE": {"hex": "0x35", "dec": 53},
|
||||||
|
"WORTIME1": {"hex": "0x36", "dec": 54},
|
||||||
|
"WORTIME0": {"hex": "0x37", "dec": 55},
|
||||||
|
"PKTSTATUS": {"hex": "0x38", "dec": 56},
|
||||||
|
"VCO_VC_DAC": {"hex": "0x39", "dec": 57},
|
||||||
|
"TXBYTES": {"hex": "0x3A", "dec": 58},
|
||||||
|
"RXBYTES": {"hex": "0x3B", "dec": 59},
|
||||||
|
"NUM_RXBYTES": {"hex": "0x7F", "dec": 127}
|
||||||
|
},
|
||||||
|
"MEMORY": {
|
||||||
|
"PATABLE": {"hex": "0x3E", "dec": 62},
|
||||||
|
"TXFIFO": {"hex": "0x3F", "dec": 63},
|
||||||
|
"RXFIFO": {"hex": "0x3F", "dec": 63}
|
||||||
|
},
|
||||||
|
"MASKS": {
|
||||||
|
"LQI_RX": {"hex": "0x01", "dec": 1},
|
||||||
|
"CRC_OK": {"hex": "0x80", "dec": 128}
|
||||||
|
},
|
||||||
|
"ACCESS": {
|
||||||
|
"WRITE_BURST": {"hex": "0x40", "dec": 64},
|
||||||
|
"READ_SINGLE": {"hex": "0x80", "dec": 128},
|
||||||
|
"READ_BURST": {"hex": "0xC0", "dec": 192}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
freq.txt
Normal file
12
freq.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Handheld Init
|
||||||
|
2.4312 GHZ (mid)
|
||||||
|
2.439256 (strong)
|
||||||
|
2.447 GHZ (strong)
|
||||||
|
2.4632 GHZ (strong)
|
||||||
|
2.471 GHZ (weak)
|
||||||
|
|
||||||
|
Test Pts
|
||||||
|
2410000.000
|
||||||
|
2430000.000
|
||||||
|
2450000.000
|
||||||
|
2470000.000
|
BIN
images/signals/signal0.png
Normal file
BIN
images/signals/signal0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 401 KiB |
BIN
images/signals/signal00.png
Normal file
BIN
images/signals/signal00.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 410 KiB |
BIN
images/signals/signal1.png
Normal file
BIN
images/signals/signal1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 930 KiB |
BIN
images/signals/signal2.png
Normal file
BIN
images/signals/signal2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 560 KiB |
BIN
images/signals/signal3.png
Normal file
BIN
images/signals/signal3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 385 KiB |
BIN
images/smart_rf.png
Normal file
BIN
images/smart_rf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
167
read.py
Normal file
167
read.py
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import spidev
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Initialize SPI
|
||||||
|
global spi
|
||||||
|
global init_data
|
||||||
|
# global regs_data
|
||||||
|
global CONFIG_REGS
|
||||||
|
global STROBES
|
||||||
|
global STATUS
|
||||||
|
global MEMORY
|
||||||
|
global MASKS
|
||||||
|
global ACCESS
|
||||||
|
|
||||||
|
def asb (a):
|
||||||
|
return int(a,16)
|
||||||
|
|
||||||
|
def strobe(command):
|
||||||
|
"""Send a command strobe to CC2500"""
|
||||||
|
spi.xfer2([command])
|
||||||
|
|
||||||
|
def write_reg(addr, value):
|
||||||
|
"""Write single byte to a register"""
|
||||||
|
spi.xfer2([addr, value])
|
||||||
|
|
||||||
|
def burst_write(addr, data):
|
||||||
|
"""Write multiple bytes to FIFO or registers"""
|
||||||
|
BURST = 0x40
|
||||||
|
spi.xfer2([addr | BURST] + data)
|
||||||
|
|
||||||
|
def burst_read(addr, length):
|
||||||
|
"""Read multiple bytes"""
|
||||||
|
READ_SINGLE = ACCESS["READ_SINGLE"]["dec"]
|
||||||
|
READ_BURST = ACCESS["READ_BURST"]["dec"]
|
||||||
|
return spi.xfer2([addr | READ_SINGLE | READ_BURST] + [0x00] * length)
|
||||||
|
|
||||||
|
def read_fifo():
|
||||||
|
# Burst read RX FIFO
|
||||||
|
READ_BURST = ACCESS["READ_BURST"]["dec"]
|
||||||
|
RXFIFO = MEMORY["RXFIFI"]["dec"]
|
||||||
|
fifo = spi.xfer2([RXFIFO | READ_BURST] + [0x00]*64) # Max 64 bytes
|
||||||
|
return fifo[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def read_register(addr):
|
||||||
|
READ_SINGLE = ACCESS["READ_SINGLE"]["dec"]
|
||||||
|
# Send address | 0x80 (read), then 0x00 dummy to clock in response
|
||||||
|
response = spi.xfer2([READ_SINGLE | addr, 0x00])
|
||||||
|
return response[1]
|
||||||
|
|
||||||
|
def send_packet(data):
|
||||||
|
# Flush TX FIFO
|
||||||
|
strobe(0x3B) # SFTX
|
||||||
|
|
||||||
|
# Load data to TX FIFO (fixed length)
|
||||||
|
burst_write(0x3F, data) # 0x3F = TX FIFO
|
||||||
|
|
||||||
|
# Strobe STX to transmit
|
||||||
|
strobe(0x35) # STX
|
||||||
|
|
||||||
|
print(f"Sent: {data}")
|
||||||
|
|
||||||
|
|
||||||
|
def receive_packet():
|
||||||
|
# Flush RX FIFO
|
||||||
|
SFRX = STROBES["SFRX"]["dec"]
|
||||||
|
strobe(SFRX) # SFRX
|
||||||
|
|
||||||
|
SRX = STROBES["SRX"]["dec"]
|
||||||
|
# Go into RX mode
|
||||||
|
strobe(SRX) # SRX
|
||||||
|
|
||||||
|
# Wait for data (use GDO0 in real app)
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# Check RXBYTES
|
||||||
|
RXBYTES = STATUS["RXBYTES"]["dec"]
|
||||||
|
rx_bytes = read_register(RXBYTES) & 0x7F
|
||||||
|
if rx_bytes == 0:
|
||||||
|
print("No data received.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Read data
|
||||||
|
RXFIFO = MEMORY["RXFIFO"]["dec"]
|
||||||
|
data = read_fifo() # 0x3F = RX FIFO
|
||||||
|
print(f"Received: {data}")
|
||||||
|
return data
|
||||||
|
|
||||||
|
def test_read_write_reg():
|
||||||
|
FIFOTHR = CONFIG_REGS["FIFOTHR"]["dec"]
|
||||||
|
print("reg ", hex(FIFOTHR))
|
||||||
|
initial_val = read_register(FIFOTHR)
|
||||||
|
test_value = initial_val + 1
|
||||||
|
write_reg(FIFOTHR, test_value)
|
||||||
|
check = read_register(FIFOTHR)
|
||||||
|
write_reg(FIFOTHR, initial_val)
|
||||||
|
print("initial value ", initial_val)
|
||||||
|
print("test value ", test_value)
|
||||||
|
print("check ",check)
|
||||||
|
return check == test_value
|
||||||
|
|
||||||
|
def disable_crc():
|
||||||
|
spi.xfer2([CONFIG_REGS["PKTCTRL0"]["dec"], 0x01])
|
||||||
|
|
||||||
|
def dump_reg():
|
||||||
|
for reg_name_group, regs in regs_data.items():
|
||||||
|
for reg_name, reg_loc in regs.items():
|
||||||
|
addr = reg_loc['dec']
|
||||||
|
reg_value = read_register(addr)
|
||||||
|
print(reg_name + ":"+str(reg_value))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
spi = spidev.SpiDev()
|
||||||
|
spi.open(0, 0) # Bus 0, CE0 (Pin 24)
|
||||||
|
spi.max_speed_hz = 2000000 # Safe start speed
|
||||||
|
spi.mode = 0b00 # SPI mode 0
|
||||||
|
|
||||||
|
|
||||||
|
with open("cc2500_init.json", "r") as f:
|
||||||
|
init_data = json.load(f)
|
||||||
|
with open("cc2500_regs.json", "r") as f:
|
||||||
|
regs_data = json.load(f)
|
||||||
|
CONFIG_REGS = regs_data["CONFIG_REGS"]
|
||||||
|
STROBES = regs_data["STROBES"]
|
||||||
|
STATUS = regs_data["STATUS"]
|
||||||
|
MEMORY = regs_data["MEMORY"]
|
||||||
|
MASKS = regs_data["MASKS"]
|
||||||
|
ACCESS = regs_data["ACCESS"]
|
||||||
|
|
||||||
|
SRES = STROBES["SRES"]["dec"]
|
||||||
|
SNOP = STROBES["SNOP"]["dec"]
|
||||||
|
VERSION = STATUS["VERSION"]["dec"]
|
||||||
|
|
||||||
|
print("Sending SRES (reset)...")
|
||||||
|
spi.xfer2([SRES])
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
print("Sending SNOP (no-op)...")
|
||||||
|
status = spi.xfer2([SNOP])[0]
|
||||||
|
print(f"Status byte: 0x{status:02X}")
|
||||||
|
|
||||||
|
print("Reading VERSION register...")
|
||||||
|
version = read_register(VERSION)
|
||||||
|
print(f"CC2500 VERSION register: 0x{version:02X}")
|
||||||
|
|
||||||
|
# dump_reg()
|
||||||
|
|
||||||
|
for reg_name, values in init_data.items():
|
||||||
|
addr_dec = regs_data["CONFIG_REGS"][reg_name]["dec"]
|
||||||
|
addr_hex = regs_data["CONFIG_REGS"][reg_name]["hex"]
|
||||||
|
value_hex = values["hex"]
|
||||||
|
value_dec = values["dec"]
|
||||||
|
# print(addr)
|
||||||
|
# print(values["hex"])
|
||||||
|
# print("writing "+str(addr_hex) + " to "+str(addr_dec))
|
||||||
|
write_reg(addr_dec, value_dec)
|
||||||
|
disable_crc()
|
||||||
|
time.sleep(2)
|
||||||
|
# dump_reg()
|
||||||
|
print("Read + Write test ", test_read_write_reg())
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
receive_packet()
|
||||||
|
time.sleep(1)
|
||||||
|
finally:
|
||||||
|
spi.close()
|
14
srfexp_json.xml
Normal file
14
srfexp_json.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<registerexporttemplate>
|
||||||
|
<name><![CDATA[JSON]]></name>
|
||||||
|
<commentStart><![CDATA[//]]></commentStart>
|
||||||
|
<commentEnd><![CDATA[]]></commentEnd>
|
||||||
|
<paramSummary><![CDATA[0]]></paramSummary>
|
||||||
|
<paTable><![CDATA[0]]></paTable>
|
||||||
|
<header><![CDATA[{
|
||||||
|
]]></header>
|
||||||
|
<registers><![CDATA[ "@RN@"@<<@: @<<@{ "hex":"0x@VH@", "dec":@VD@},]]></registers>
|
||||||
|
<footer><![CDATA[}]]></footer>
|
||||||
|
<filename><![CDATA[@CHIPID@_simple_link_reg_config.json]]></filename>
|
||||||
|
<devices><![CDATA[]]></devices>
|
||||||
|
</registerexporttemplate>
|
50
test.py
Executable file
50
test.py
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
import spidev
|
||||||
|
import time
|
||||||
|
|
||||||
|
cc2500_config = {
|
||||||
|
0x00: 0x0B, # IOCFG2
|
||||||
|
0x02: 0x06, # IOCFG0
|
||||||
|
0x03: 0x00, # FIFOTHR
|
||||||
|
0x07: 0x08, # FSCTRL1
|
||||||
|
0x08: 0x00, # FSCTRL0
|
||||||
|
0x0B: 0x06, # IOCFG0 (repeating correct setting)
|
||||||
|
0x0C: 0x00, # FIFOTHR
|
||||||
|
0x0D: 0x5D, # FREQ2
|
||||||
|
0x0E: 0x93, # FREQ1
|
||||||
|
0x0F: 0xB1, # FREQ0
|
||||||
|
0x10: 0x2D, # MDMCFG4
|
||||||
|
0x11: 0x3B, # MDMCFG3
|
||||||
|
0x12: 0x73, # MDMCFG2
|
||||||
|
0x15: 0x00, # DEVIATN
|
||||||
|
0x18: 0x18, # MCSM0
|
||||||
|
0x19: 0x1D, # FOCCFG
|
||||||
|
0x1A: 0x1C, # BSCFG
|
||||||
|
0x1B: 0xC7, # AGCCTRL2
|
||||||
|
0x22: 0x11, # FREND0
|
||||||
|
0x23: 0xE9, # FSCAL3
|
||||||
|
0x24: 0x2A, # FSCAL2
|
||||||
|
0x25: 0x00, # FSCAL1
|
||||||
|
0x26: 0x1F, # FSCAL0
|
||||||
|
0x2C: 0x81, # TEST2
|
||||||
|
0x2D: 0x35, # TEST1
|
||||||
|
0x2E: 0x09, # TEST0
|
||||||
|
0x06: 0x00, # ADDR (only once)
|
||||||
|
0x1E: 0x05, # PKTCTRL0
|
||||||
|
0x07: 0x00, # CHANNR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
spi = spidev.SpiDev()
|
||||||
|
spi.open(0, 0) # Bus 0, CE0
|
||||||
|
spi.max_speed_hz = 500000 # Adjust if needed
|
||||||
|
spi.mode = 0 # CC2500 usually works in SPI mode 0
|
||||||
|
|
||||||
|
def cc2500_strobe(command):
|
||||||
|
resp = spi.xfer2([command])
|
||||||
|
return resp[0]
|
||||||
|
|
||||||
|
SRES = 0x30 # Reset strobe command
|
||||||
|
|
||||||
|
print("Sending reset to CC2500...")
|
||||||
|
status = cc2500_strobe(SRES)
|
||||||
|
print(f"Status byte: 0x{status:02X}")
|
31
wiring.txt
Normal file
31
wiring.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
CC2500 Pins to Raspberry Pi GPIO Pins
|
||||||
|
GND (CC2500) → Ground (Pin 6 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
VCC (CC2500) → 3.3V Power (Pin 1 or Pin 17 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
Ensure the CC2500 module operates at 3.3V. Connecting it to 5V may damage it.
|
||||||
|
|
||||||
|
SPI Pins:
|
||||||
|
SI (CC2500) → MOSI (GPIO 10) (Pin 19 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
SCK (CC2500) → SCLK (GPIO 11) (Pin 23 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
CSN (CC2500) → CE0 (GPIO 8) (Pin 24 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
This is the Chip Select line.
|
||||||
|
|
||||||
|
SO (CC2500) → MISO (GPIO 9) (Pin 21 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
Optional Pins:
|
||||||
|
GDO0 (CC2500) → Any GPIO Pin (e.g., GPIO 18) (Pin 12 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
Use this for interrupt handling or data-ready signals if required.
|
||||||
|
|
||||||
|
GDO2 (CC2500) → Any GPIO Pin (e.g., GPIO 25) (Pin 22 on Raspberry Pi GPIO header)
|
||||||
|
|
||||||
|
Additional interrupt or data pin.
|
||||||
|
|
||||||
|
Power Amplifier Pins (If Applicable):
|
||||||
|
PA_EN (CC2500) → Any GPIO Pin (Optional, depending on whether you control the amplifier externally or not).
|
||||||
|
|
||||||
|
PA_EX (CC2500) → Not Connected (unless needed for a specific configuration)
|
Loading…
Reference in New Issue
Block a user