Skip to content

Commit

Permalink
Add shinyshez's A7105 arduino interface sketch, including phracturedb…
Browse files Browse the repository at this point in the history
…lue's hubsan protocol.
  • Loading branch information
Andy May committed Feb 4, 2014
0 parents commit 88986ff
Show file tree
Hide file tree
Showing 6 changed files with 644 additions and 0 deletions.
86 changes: 86 additions & 0 deletions a7105.h
@@ -0,0 +1,86 @@
#ifndef _IFACE_A7105_H_
#define _IFACE_A7105_H_

enum A7105_State {
A7105_SLEEP = 0x80,
A7105_IDLE = 0x90,
A7105_STANDBY = 0xA0,
A7105_PLL = 0xB0,
A7105_RX = 0xC0,
A7105_TX = 0xD0,
A7105_RST_WRPTR = 0xE0,
A7105_RST_RDPTR = 0xF0,
};

enum {
A7105_00_MODE = 0x00,
A7105_01_MODE_CONTROL = 0x01,
A7105_02_CALC = 0x02,
A7105_03_FIFOI = 0x03,
A7105_04_FIFOII = 0x04,
A7105_05_FIFO_DATA = 0x05,
A7105_06_ID_DATA = 0x06,
A7105_07_RC_OSC_I = 0x07,
A7105_08_RC_OSC_II = 0x08,
A7105_09_RC_OSC_III = 0x09,
A7105_0A_CK0_PIN = 0x0A,
A7105_0B_GPIO1_PIN1 = 0x0B,
A7105_0C_GPIO2_PIN_II = 0x0C,
A7105_0D_CLOCK = 0x0D,
A7105_0E_DATA_RATE = 0x0E,
A7105_0F_PLL_I = 0x0F,
A7105_10_PLL_II = 0x10,
A7105_11_PLL_III = 0x11,
A7105_12_PLL_IV = 0x12,
A7105_13_PLL_V = 0x13,
A7105_14_TX_I = 0x14,
A7105_15_TX_II = 0x15,
A7105_16_DELAY_I = 0x16,
A7105_17_DELAY_II = 0x17,
A7105_18_RX = 0x18,
A7105_19_RX_GAIN_I = 0x19,
A7105_1A_RX_GAIN_II = 0x1A,
A7105_1B_RX_GAIN_III = 0x1B,
A7105_1C_RX_GAIN_IV = 0x1C,
A7105_1D_RSSI_THOLD = 0x1D,
A7105_1E_ADC = 0x1E,
A7105_1F_CODE_I = 0x1F,
A7105_20_CODE_II = 0x20,
A7105_21_CODE_III = 0x21,
A7105_22_IF_CALIB_I = 0x22,
A7105_23_IF_CALIB_II = 0x23,
A7105_24_VCO_CURCAL = 0x24,
A7105_25_VCO_SBCAL_I = 0x25,
A7105_26_VCO_SBCAL_II = 0x26,
A7105_27_BATTERY_DET = 0x27,
A7105_28_TX_TEST = 0x28,
A7105_29_RX_DEM_TEST_I = 0x29,
A7105_2A_RX_DEM_TEST_II = 0x2A,
A7105_2B_CPC = 0x2B,
A7105_2C_XTAL_TEST = 0x2C,
A7105_2D_PLL_TEST = 0x2D,
A7105_2E_VCO_TEST_I = 0x2E,
A7105_2F_VCO_TEST_II = 0x2F,
A7105_30_IFAT = 0x30,
A7105_31_RSCALE = 0x31,
A7105_32_FILTER_TEST = 0x32,
};
#define A7105_0F_CHANNEL A7105_0F_PLL_I

enum A7105_MASK {
A7105_MASK_FBCF = 1 << 4,
A7105_MASK_VBCF = 1 << 3,
};

void A7105_Initialize();
void A7105_WriteReg(u8 addr, u8 value);
void A7105_WriteData(u8 *dpbuffer, u8 len, u8 channel);
void A7105_ReadData(u8 *dpbuffer, u8 len);
u8 A7105_ReadReg(u8 addr);
void A7105_Reset();
void A7105_WriteID(u32 id);
void A7105_Strobe(enum A7105_State);
void A7105_SetPower(int power);


#endif
164 changes: 164 additions & 0 deletions a7105.ino
@@ -0,0 +1,164 @@
/*
This project 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.
Deviation 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 Deviation. If not, see <http://www.gnu.org/licenses/>.
*/

#include <Arduino.h>
#include <SPI.h>
#include "config.h"
#include "a7105.h"

#define CS_PIN 10

#define CS_HI() digitalWrite(CS_PIN, HIGH);
#define CS_LO() digitalWrite(CS_PIN, LOW);

void A7105_WriteReg(u8 address, u8 data)
{
CS_LO();
SPI.transfer(address); // spi_xfer(SPI2, address);
SPI.transfer(data); // spi_xfer(SPI2, data);
CS_HI();
}


void A7105_Setup() {
pinMode(CS_PIN, OUTPUT);
SPI.begin();
SPI.setDataMode(SPI_MODE0);
// SPI.setClockDivider(10);
SPI.setBitOrder(MSBFIRST);
// set gpio1 to SDO (MISO) by writing to reg GIO1S
// A7105_WriteReg(0x0b,0x06); // 0b0110
}

u8 A7105_ReadReg(u8 address)
{
u8 data;
int i;
CS_LO();
// Bits A7-A0 make up the first u8.
// Bit A7 = 1 == Strobe. A7 = 0 == access register.
// Bit a6 = 1 == read. a6 = 0 == write.
// bits 0-5 = address. Assuming address < 64 the below says we want to read an address.
SPI.transfer(0x40 | address); //spi_xfer(SPI2, 0x40 | address);
data = SPI.transfer(0);
CS_HI();
// Serial.print(address); Serial.print(" "); Serial.println(data);
return data;
// Not necessary because we expect SPI class to handle this?
// /* Wait for tx completion before spi shutdown */
// while(!(SPI_SR(SPI2) & SPI_SR_TXE))
// ;
// while((SPI_SR(SPI2) & SPI_SR_BSY))
// ;

// spi_disable(SPI2);
// spi_set_bidirectional_receive_only_mode(SPI2);
// */
// /* Force read from SPI_DR to ensure RXNE is clear (probably not needed) */
// volatile u8 x = SPI_DR(SPI2);
// (void)x;
// spi_enable(SPI2); //This starts the data read
// for(i = 0; i < 20; i++) //Wait > 1 SPI clock (but less than 8). clock is 4.5MHz
// asm volatile ("nop");
// ;
// spi_disable(SPI2); //This ends the read window
// data = spi_read(SPI2);
// CS_HI();
// spi_set_unidirectional_mode(SPI2);
// spi_enable(SPI2);
// return data;
}

void A7105_WriteData(u8 *dpbuffer, u8 len, u8 channel)
{
int i;
CS_LO();
SPI.transfer(A7105_RST_WRPTR); //reset write FIFO PTR
SPI.transfer(0x05); // FIFO DATA register - about to send data to put into FIFO
for (i = 0; i < len; i++)
SPI.transfer(dpbuffer[i]); // send some data
CS_HI();

// set the channel
A7105_WriteReg(0x0F, channel);

CS_LO();
SPI.transfer(A7105_TX); // strobe command to actually transmit the daat
CS_HI();
}

void A7105_ReadData(u8 *dpbuffer, u8 len)
{
A7105_Strobe(A7105_RST_RDPTR); //A7105_RST_RDPTR
for(int i = 0; i < len; i++) {
dpbuffer[i] = A7105_ReadReg(0x05);
}

return;
}

void A7105_Reset()
{
A7105_WriteReg(0x00, 0x00);
delayMicroseconds(1000);
// Serial.println(A7105_ReadReg(0x2));
}

void A7105_WriteID(unsigned long id)
{
CS_LO();
SPI.transfer(0x06);
SPI.transfer((id >> 24) & 0xFF);
SPI.transfer((id >> 16) & 0xFF);
SPI.transfer((id >> 8) & 0xFF);
SPI.transfer((id >> 0) & 0xFF);
CS_HI();
}

void A7105_SetPower(int power)
{
/*
Power amp is ~+16dBm so:
TXPOWER_100uW = -23dBm == PAC=0 TBG=0
TXPOWER_300uW = -20dBm == PAC=0 TBG=1
TXPOWER_1mW = -16dBm == PAC=0 TBG=2
TXPOWER_3mW = -11dBm == PAC=0 TBG=4
TXPOWER_10mW = -6dBm == PAC=1 TBG=5
TXPOWER_30mW = 0dBm == PAC=2 TBG=7
TXPOWER_100mW = 1dBm == PAC=3 TBG=7
TXPOWER_150mW = 1dBm == PAC=3 TBG=7
*/
u8 pac, tbg;
switch(power) {
case 0: pac = 0; tbg = 0; break;
case 1: pac = 0; tbg = 1; break;
case 2: pac = 0; tbg = 2; break;
case 3: pac = 0; tbg = 4; break;
case 4: pac = 1; tbg = 5; break;
case 5: pac = 2; tbg = 7; break;
case 6: pac = 3; tbg = 7; break;
case 7: pac = 3; tbg = 7; break;
default: pac = 0; tbg = 0; break;
};
A7105_WriteReg(0x28, (pac << 3) | tbg);
}

void A7105_Strobe(enum A7105_State state)
{
CS_LO();
SPI.transfer(state);
CS_HI();
}

42 changes: 42 additions & 0 deletions config.h
@@ -0,0 +1,42 @@
#include <stdint.h>

#define NUM_OUT_CHANNELS 12
#define CHAN_MULTIPLIER 100
#define CHAN_MAX_VALUE (100 * CHAN_MULTIPLIER)

#define s16 int16_t
#define u16 uint16_t
#define s32 int32_t
#define u32 uint32_t
#define u8 uint8_t

extern volatile s16 Channels[NUM_OUT_CHANNELS];

enum TxPower {
TXPOWER_100uW,
TXPOWER_300uW,
TXPOWER_1mW,
TXPOWER_3mW,
TXPOWER_10mW,
TXPOWER_30mW,
TXPOWER_100mW,
TXPOWER_150mW,
TXPOWER_LAST,
};

enum ProtoCmds {
PROTOCMD_INIT,
PROTOCMD_DEINIT,
PROTOCMD_BIND,
PROTOCMD_CHECK_AUTOBIND,
PROTOCMD_NUMCHAN,
PROTOCMD_DEFAULT_NUMCHAN,
PROTOCMD_CURRENT_ID,
PROTOCMD_SET_TXPOWER,
PROTOCMD_GETOPTIONS,
PROTOCMD_SETOPTIONS,
PROTOCMD_TELEMETRYSTATE,
};


void PROTOCOL_SetBindState(u32 msec);

0 comments on commit 88986ff

Please sign in to comment.