summaryrefslogtreecommitdiff
path: root/software/hhd70dongle.old
diff options
context:
space:
mode:
Diffstat (limited to 'software/hhd70dongle.old')
-rw-r--r--software/hhd70dongle.old/Makefile54
-rw-r--r--software/hhd70dongle.old/c1101lib.c771
-rw-r--r--software/hhd70dongle.old/c1101lib.h71
-rw-r--r--software/hhd70dongle.old/hhd70.c184
-rw-r--r--software/hhd70dongle.old/hhd70.h76
-rw-r--r--software/hhd70dongle.old/hhd70dongle.c438
-rw-r--r--software/hhd70dongle.old/readme.txt31
-rwxr-xr-xsoftware/hhd70dongle.old/reset.sh3
-rw-r--r--software/hhd70dongle.old/util.c87
-rw-r--r--software/hhd70dongle.old/util.h45
10 files changed, 1760 insertions, 0 deletions
diff --git a/software/hhd70dongle.old/Makefile b/software/hhd70dongle.old/Makefile
new file mode 100644
index 0000000..fe926c2
--- /dev/null
+++ b/software/hhd70dongle.old/Makefile
@@ -0,0 +1,54 @@
+##
+## spreadspace teensy utils
+##
+##
+## Copyright (C) 2011 Christian Pointner <equinox@spreadspace.org>
+##
+## This file is part of spreadspace teensy utils.
+##
+## spreadspace teensy utils 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
+## any later version.
+##
+## spreadspace teensy utils 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 spreadspace teensy utils. If not, see <http://www.gnu.org/licenses/>.
+##
+
+NAME := hhd70dongle
+BOARD_TYPE := hhd70dongle
+OBJ := $(NAME).o hhd70.o c1101lib.o util.o
+LIBS := led lufa-descriptor-usbserial usbio
+RESET_FUNC := ./reset.sh
+
+EXTERNAL_LIBS := lufa
+
+LUFA_PATH := ../../contrib/LUFA-120219
+LUFA_OPTS = -D USB_DEVICE_ONLY
+LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
+LUFA_OPTS += -D ORDERED_EP_CONFIG
+LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
+LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
+LUFA_OPTS += -D USE_FLASH_DESCRIPTORS
+LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
+LUFA_OPTS += -D INTERRUPT_CONTROL_ENDPOINT
+
+LUFA_OPTS += -D USB_MANUFACTURER="L\"mur.sat\"" -D USB_MANUFACTURER_LEN=7
+LUFA_OPTS += -D USB_PRODUCT="L\"HHD70 usb dongle\"" -D USB_PRODUCT_LEN=16
+
+LUFA_COMPONENTS := USB USBCLASS
+
+include ../avr.include.mk
+
+CFLAGS += -D CC1101_QUARTZ_26M
+
+program0: RESET_PARAM:=/dev/ttyACM0
+program0: program
+
+program1: RESET_PARAM:=/dev/ttyACM1
+program1: program
diff --git a/software/hhd70dongle.old/c1101lib.c b/software/hhd70dongle.old/c1101lib.c
new file mode 100644
index 0000000..209ccee
--- /dev/null
+++ b/software/hhd70dongle.old/c1101lib.c
@@ -0,0 +1,771 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ * 2015 Christian Pointner <equinox@mur.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "c1101lib.h"
+#include "cc1101_defines.h"
+#include "hhd70.h"
+#include "util.h"
+
+// internal functions
+
+#define CC1101_MAX_WAIT_RDY 21
+
+static int16_t c1101_spi_write_byte_ok_get_status(uint8_t data)
+{
+ uint8_t sb;
+ unsigned int attempts = 0;
+ do
+ {
+ sb = hhd70_spi_exchange_byte(data);
+ //Note: content of returned StatusByte is actually context depenedant on sent command
+ // i.e. we won't get Fifo Byte count or overflow status on normal command and so on
+ // e.g. we only get TX Fifo Free Byte count while writing to TX Fifo
+ // thus it makes sense to only check for CHIP_RDY here
+ if (attempts++ > CC1101_MAX_WAIT_RDY)
+ return -1;
+ } while (CC1101_STATUS_CHIP_NOT_RDY(sb));
+ return sb;
+}
+
+int16_t c1101_spi_strobe_command(uint8_t cmd)
+{
+ if(cmd < CC1101_CMD_MIN || cmd > CC1101_CMD_MAX)
+ return -1;
+
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ uint8_t rbyte = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_COMMAND | cmd);
+ if(rbyte < 0)
+ return -1;
+ hhd70_spi_cs_disable();
+ return rbyte;
+}
+
+int16_t c1101_spi_read_register(uint8_t addr)
+{
+ if(addr > CC1101_ADDR_MAX)
+ return -1;
+
+ if(addr > CC1101_REG_RW_MAX)
+ addr |= CC1101_HEADER_READONLY;
+ else
+ addr |= CC1101_HEADER_READ;
+
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ if(c1101_spi_write_byte_ok_get_status(addr) < 0)
+ return -1;
+ uint8_t rbyte = hhd70_spi_read_byte();
+ hhd70_spi_cs_disable();
+ return rbyte;
+}
+
+int16_t c1101_spi_write_register(uint8_t addr, uint8_t byte)
+{
+ if(addr > CC1101_REG_RW_MAX)
+ return -1;
+
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ if(c1101_spi_write_byte_ok_get_status(CC1101_HEADER_WRITE | addr) < 0)
+ return -1;
+ _delay_ms(2); // TODO: why wait here???
+ if(c1101_spi_write_byte_ok_get_status(byte) < 0)
+ return -1;
+ hhd70_spi_cs_disable();
+ return 1;
+}
+
+void c1101_spi_dump_registers(void)
+{
+ int c = 0;
+ char debug_sb[6];
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | 0x00) < 0)
+ return;
+ printf("dump all 46 registers:\r\n");
+ for (c = 0; c < CC1101_REG_RW_MAX; c++) {
+ debug_sprint_int16hex(debug_sb, hhd70_spi_read_byte());
+ printf("%s", debug_sb);
+ printf("\r\n");
+ }
+ hhd70_spi_cs_disable();
+}
+
+int c1101_spi_read_rxfifo(int leave_num_bytes, uint8_t *buffer, int maxlen)
+{
+ int num_read = 0;
+ uint8_t num_available = 0;
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READONLY | CC1101_REG_RO_RXBYTES) < 0)
+ return -1;
+
+ num_available = hhd70_spi_read_byte();
+ if (num_available == 0)
+ return 0;
+ if (c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO) < 0)
+ return -1;
+ while (maxlen-- > 0 && num_available - num_read > leave_num_bytes)
+ buffer[num_read++] = hhd70_spi_read_byte();
+
+ hhd70_spi_cs_disable();
+ return num_read;
+}
+
+//note: currently this function reads at most 15 bytes
+int c1101_spi_read_rxfifo_max15(int leave_num_bytes, uint8_t *buffer, int maxlen)
+{
+ int16_t sb;
+ int num_read = 0;
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO);
+ if (sb < 0)
+ return -1;
+ //note if CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) == 15 then 15 or more bytes are available
+ while (maxlen-- > 0 && CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) - num_read > leave_num_bytes) {
+ //hope this works !!
+ buffer[num_read++] = hhd70_spi_read_byte();
+ }
+ hhd70_spi_cs_disable();
+ return num_read;
+}
+
+//note: always check if num_written returned == len given
+int c1101_spi_write_txfifo(uint8_t *buffer, int len)
+{
+ uint8_t sb;
+ int num_written = 0;
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_READ | CC1101_HEADER_BURST | CC1101_REG_FIFO);
+ if (sb < 0)
+ return -1;
+ while (len-- > 0 && CC1101_STATUS_FIFO_BYTES_AVAILABLE(sb) > 2) {
+ sb = c1101_spi_write_byte_ok_get_status(buffer[num_written++]);
+ }
+ hhd70_spi_cs_disable();
+ return num_written;
+}
+
+//patable muste be uint8_t array of length 8
+int c1101_spi_write_patable(uint8_t const patable[])
+{
+ int16_t sb;
+ int8_t len = 8;
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_WRITE | CC1101_HEADER_BURST | CC1101_REG_PATABLE);
+ if (sb < 0)
+ return -1;
+ while (len-- > 0) {
+ sb = c1101_spi_write_byte_ok_get_status(*patable);
+ patable++;
+ }
+ hhd70_spi_cs_disable();
+ return sb;
+}
+
+static uint8_t const pa_table_values_[] = { 0x00, 0x30, 0x20, 0x10, 0x01, 0x02, 0x11, 0x03,
+ 0x12, 0x04, 0x05, 0x13, 0x06, 0x07, 0x21, 0x14, 0x08, 0x09, 0x0A, 0x15,
+ 0x0B, 0x31, 0x16, 0x0C, 0x0D, 0x0E, 0x17, 0x0F, 0x22, 0x18, 0x19, 0x1A,
+ 0x1B, 0x32, 0x23, 0x1C, 0x6F, 0x1D, 0x1E, 0x1F, 0x24, 0x33, 0x25, 0x34,
+ 0x26, 0x6E, 0x27, 0x35, 0x28, 0x6D, 0x6C, 0x29, 0x36, 0x6B, 0x2A, 0x6A,
+ 0x37, 0x69, 0x2B, 0x68, 0x38, 0x2C, 0x8F, 0x67, 0x2D, 0x57, 0x39, 0x66,
+ 0x2E, 0x56, 0x3A, 0x2F, 0x65, 0x55, 0x3B, 0x64, 0x54, 0x3C, 0x63, 0x3D,
+ 0x53, 0x3E, 0x62, 0x3F, 0x52, 0x40, 0x61, 0x51, 0x60, 0x50, 0x8E, 0x8D,
+ 0x8C, 0xCF, 0x8B, 0x8A, 0x89, 0x88, 0x87, 0x86, 0x85, 0xCE, 0x84, 0x83,
+ 0xCD, 0x82, 0xCC, 0x81, 0xCB, 0x80, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5,
+ 0xC4, 0xC3, 0xC2, 0xC1, 0xC0 };
+
+#define PA_TABLE_VALUES_MAX ((sizeof(pa_table_values_)/sizeof(uint8_t))-1)
+static uint8_t ook_power_ = 83; // ==> 3F
+
+
+/**** External Functions ****/
+
+uint16_t c1101_setFSKDeviationFromCarrier(int8_t m, int8_t e)
+{
+ c1101_spi_write_register(CC1101_REG_RW_DEVIATN, (m & 0x7) | ((e & 0x7) << 4));
+ return (1983u * (8u+((uint32_t)m)) * (1u << ((uint32_t)e))) / 100; //return +- deviation in 10Hz Steps
+}
+
+void c1101_init(void)
+{
+ //reset C1101
+ c1101_spi_strobe_command(CC1101_CMD_SRES);
+ _delay_ms(100);
+ //flush FIFOs
+ c1101_spi_strobe_command(CC1101_CMD_SFRX);
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+ //dump pre-init default values to stdout
+ c1101_spi_dump_registers();
+ //enable analog temperature sensor on GDO0
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x80);
+ //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47
+ // FIFOTHR RX FIFO and TX FIFO Thresholds
+ // pull GPO high (interrupt) if more than 12 bytes in rx buffer (or less than 53 in tx)
+ //c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 2); //assert at 12 bytes in RX Fifo and 53 in TX Fifo
+ c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 0); //assert at 4 bytes in RX Fifo and 61 in TX Fifo
+ // PKTCTRL0 Packet Automation Control
+ //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000010); //crc disabled; use FIFOs; infinite packet length mode
+ c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
+ //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000101); //crc enabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
+ c1101_spi_write_register(CC1101_REG_RW_PKTCTRL1, 0x00); //no address check, no append rssi and crc_ok to packet
+ // FSCTRL1 Frequency Synthesizer Control
+ c1101_spi_write_register(CC1101_REG_RW_FSCTRL1, 0x06);
+ // FREQn Frequency Control Words
+ c1101_spi_write_register(CC1101_REG_RW_FREQ2, 0x10); //should be 435.125 mhz
+ c1101_spi_write_register(CC1101_REG_RW_FREQ1, 0xBF);
+ c1101_spi_write_register(CC1101_REG_RW_FREQ0, 0xEF);
+ c1101_spi_write_register(CC1101_REG_RW_FSCTRL0, 0); //frequency offset
+ // MDMCFGn Modem Configuration
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG4, 0xF8);
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG3, 0x83);
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG2, 0x12); //gfsk, 15/16 sync word
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG1, 0x00);
+ //Sync Word
+ c1101_spi_write_register(CC1101_REG_RW_SYNC1, 0x21);
+ c1101_spi_write_register(CC1101_REG_RW_SYNC0, 0x42);
+ // DEVIATN Modem Deviation Setting
+ c1101_spi_write_register(CC1101_REG_RW_DEVIATN, 0x11); //0x11 equals deviation of 3.5kHz; 0x27 equals deviation of 11.9kHz
+ // MCSM0 Main Radio Control State Machine Configuration
+ c1101_spi_write_register(CC1101_REG_RW_MCSM0, 0x18);
+ c1101_spi_write_register(CC1101_REG_RW_MCSM1, 0b00111100); // State RX after recieving packet-> stay in RX; State TX after sending packet -> IDLE
+ // FOCCFG Frequency Offset Compensation Configuration
+ c1101_spi_write_register(CC1101_REG_RW_FOCCFG, 0x16);
+ // WORCTRL Wake On Radio Control
+ c1101_spi_write_register(CC1101_REG_RW_WORCTRL, 0xFB);
+ // FSCALn Frequency Synthesizer Calibration
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL3, 0xE9);
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL2, 0x2A);
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL1, 0x00);
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL0, 0x1F);
+ //FREN0 TX Power:
+ c1101_spi_write_register(CC1101_REG_RW_FREND0, 0x10); //should be set using RF-Studio !!, for now, only use PA-Table Entry[0] no power ramping !! (FIXME: but should maybe be used)
+ c1101_spi_write_register(CC1101_REG_PATABLE, 0xC0); //write PATABLE[0] only, rest needs to be written in Burst-Mode ! set to max power 10dBm
+
+ // note: for now: assume f_xosc to be 26 Mhz
+ // for ~433.125 Mhz -> freq = 1091741, freq_offset = 0
+ //c1101_setFrequency(1091741,0,15);
+
+ //AFU Satellite Band: 435.000 - 438.000 kHz
+ //AFU Salellite Band Max Bandwith: 20 kHz
+
+ hhd70_config_GDO0_OOK_output(false);
+}
+
+//Note for comparision:
+void c1101_init_w_rfstudiosettings1(void)
+{
+ // Sync word qualifier mode = 30/32 sync word bits detected
+ // CRC autoflush = false
+ // Channel spacing = 199.951172
+ // Data format = Normal mode
+ // Data rate = 9.59587
+ // RX filter BW = 58.035714
+ // PA ramping = true
+ // Preamble count = 4
+ // Address config = No address check
+ // Whitening = false
+ // Carrier frequency = 435.124695
+ // Device address = 0
+ // TX power = 10
+ // Manchester enable = false
+ // CRC enable = true
+ // Deviation = 11.901855
+ // Modulation format = GFSK
+ // Base frequency = 435.124695
+ // Modulated = true
+ // Channel number = 0
+ // PA table
+ uint8_t const pa_table[8] = {0x00,0x12,0x0e,0x34,0x60,0xc5,0xc1,0xc0};
+ //
+ // Rf settings for CC1101
+ //
+ //reset C1101
+ c1101_spi_strobe_command(CC1101_CMD_SRES);
+ _delay_ms(100);
+ //flush FIFOs
+ c1101_spi_strobe_command(CC1101_CMD_SFRX);
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+ //enable analog temperature sensor on GDO0
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x80);
+ //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47
+
+ //Values from SmartRFStudio:
+ c1101_spi_write_patable(pa_table);
+
+ hhd70_config_GDO0_OOK_output(false);
+}
+
+
+void c1101_init_ook_beacon(void)
+{
+ // Sync word qualifier mode = No preamble/sync
+ // CRC autoflush = false
+ // Channel spacing = 49.987793
+ // Data format = Synchronous serial mode
+ // Data rate = 1.00112
+ // RX filter BW = 58.035714
+ // PA ramping = true
+ // Preamble count = 2
+ // Address config = No address check
+ // Whitening = false
+ // Carrier frequency = 437.524902 MHz
+ // Device address = 0
+ // TX power = 10
+ // Manchester enable = false
+ // CRC enable = false
+ // Deviation = 2.975464
+ // Modulation format = ASK/OOK
+ // Base frequency = 437.524902 MHz
+ // Channel number = 0
+ // PA table by TI
+
+ //reset C1101
+ c1101_spi_strobe_command(CC1101_CMD_SRES);
+ _delay_ms(100);
+ //flush FIFOs
+ c1101_spi_strobe_command(CC1101_CMD_SFRX);
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+
+ //
+ // Rf settings for CC1101
+ //
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG0, 0x00);
+ //enable RX FIFO interrupt (i.e. GPO2 pulls high if >= FIFOTHR bytes are in RX FIFO)
+ c1101_spi_write_register(CC1101_REG_RW_IOCFG2, 0x41 ); //0x40, 0x42, 0x44, 0x47
+ // pull GPO high (interrupt) if more than 12 bytes in rx buffer (or less than 53 in tx)
+ //c1101_spi_write_register(CC1101_REG_RW_FIFOTHR,0x47); //RX FIFO and TX FIFO Thresholds
+ c1101_spi_write_register(CC1101_REG_RW_FIFOTHR, 0); //assert at 4 bytes in RX Fifo and 61 in TX Fifo
+ //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0,0x12);//Packet Automation Control
+ //c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
+ c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000110001); //crc disabled; asynchronous serial input on GDO0
+ c1101_spi_write_register(CC1101_REG_RW_FSCTRL1,0x06); //Frequency Synthesizer Control
+ c1101_spi_write_register(CC1101_REG_RW_FREQ2,0x10); //Frequency Control Word, High Byte
+ c1101_spi_write_register(CC1101_REG_RW_FREQ1,0xD3); //Frequency Control Word, Middle Byte
+ c1101_spi_write_register(CC1101_REG_RW_FREQ0,0xF0); //Frequency Control Word, Low Byte
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG4,0xF5); //Modem Configuration
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG3,0x43); //Modem Configuration
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG2,0x30); //Modem Configuration
+ c1101_spi_write_register(CC1101_REG_RW_MDMCFG1,0x00); //Modem Configuration
+ c1101_spi_write_register(CC1101_REG_RW_DEVIATN,0x07); //Modem Deviation Setting
+ c1101_spi_write_register(CC1101_REG_RW_MCSM0,0x18); //Main Radio Control State Machine Configuration
+ c1101_spi_write_register(CC1101_REG_RW_FOCCFG,0x16); //Frequency Offset Compensation Configuration
+ c1101_spi_write_register(CC1101_REG_RW_WORCTRL,0xFB); //Wake On Radio Control
+ c1101_spi_write_register(CC1101_REG_RW_FREND0,0x11); //Front End TX Configuration // PA_POWER[2:0] = 1
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL3,0xE9); //Frequency Synthesizer Calibration
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL2,0x2A); //Frequency Synthesizer Calibration
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL1,0x00); //Frequency Synthesizer Calibration
+ c1101_spi_write_register(CC1101_REG_RW_FSCAL0,0x1F); //Frequency Synthesizer Calibration
+
+ c1101_ook_power_set(ook_power_);
+ hhd70_config_GDO0_OOK_output(true);
+}
+
+uint8_t c1101_ook_power_get()
+{
+ return ook_power_;
+}
+
+uint8_t c1101_ook_power_get_raw()
+{
+ return pa_table_values_[ook_power_];
+}
+
+void c1101_ook_power_set(uint8_t power)
+{
+ uint8_t val = pa_table_values_[(power <= PA_TABLE_VALUES_MAX) ? power : PA_TABLE_VALUES_MAX];
+ uint8_t const pa_table[8] = {0x00, val ,0x00,0x00,0x00,0x00,0x00,0x00};
+ c1101_spi_write_patable(pa_table);
+}
+
+void c1101_ook_power_inc()
+{
+ ook_power_ = (ook_power_ < PA_TABLE_VALUES_MAX) ? ook_power_ + 1 : PA_TABLE_VALUES_MAX;
+ uint8_t const pa_table[8] = {0x00, pa_table_values_[ook_power_] ,0x00,0x00,0x00,0x00,0x00,0x00};
+ c1101_spi_write_patable(pa_table);
+}
+
+void c1101_ook_power_dec()
+{
+ ook_power_ = (ook_power_ > 0) ? ook_power_ - 1 : 0;
+ uint8_t const pa_table[8] = {0x00, pa_table_values_[ook_power_] ,0x00,0x00,0x00,0x00,0x00,0x00};
+ c1101_spi_write_patable(pa_table);
+}
+
+// see Datasheet Chapter 14.1 Frequency Offset Compensation
+// freq_offset: desired frequency offset [Hz] *2^14 / f_XTAL
+//f_XTAL = 26Mhz
+void c1101_permanently_save_current_rx_tx_freqoffset_auto_compensation()
+{
+ int16_t freq_offset;
+ freq_offset = c1101_spi_read_register(CC1101_REG_RO_FREQUEST);
+ if (freq_offset >= 0)
+ {
+ c1101_spi_write_register(CC1101_REG_RW_FSCTRL0, (uint8_t) freq_offset);
+ }
+}
+
+// WARNING: All content of the PATABLE except for the first byte (index 0) is lost when entering the SLEEP state.
+uint8_t c1101_putToSleep(void)
+{
+ return c1101_spi_strobe_command(CC1101_CMD_SPWD);
+}
+
+uint16_t c1101_measureTemp(void)
+{
+ uint16_t temp;
+ uint8_t ptest_value=0x7F;
+ ptest_value = c1101_spi_read_register(CC1101_REG_RW_PTEST);
+ c1101_spi_write_register(CC1101_REG_RW_PTEST, 0xBF);
+ _delay_ms(5);
+ temp = adc_read(ADCMUX_INTERNALTEMP);
+ c1101_spi_write_register(CC1101_REG_RW_PTEST, ptest_value);
+ return temp;
+}
+
+void c1101_handleMARCStatusByte(uint8_t sb)
+{
+ //on RXFifo Overflow, Flush RX Fifo
+ if (sb == 0x11)
+ {
+ c1101_spi_strobe_command(CC1101_CMD_SFRX);
+ printf("RX fifo flushed\r\n");
+ }
+ //on TXFifo Overflow, Flush TX Fifo
+ else if (sb == 0x16)
+ {
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+ printf("TX fifo flushed\r\n");
+ }
+}
+
+void c1101_handleStatusByte(uint8_t sb)
+{
+ //on RXFifo Overflow, Flush RX Fifo
+ if (CC1101_STATUS_RXFIFO_OVERFLOW(sb))
+ {
+ c1101_spi_strobe_command(CC1101_CMD_SFRX);
+ printf("RX fifo flushed\r\n");
+ }
+ //on TXFifo Overflow, Flush TX Fifo
+ if (CC1101_STATUS_TXFIFO_OVERFLOW(sb))
+ {
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+ printf("TX fifo flushed\r\n");
+ }
+}
+
+uint8_t c1101_getStatus(void)
+{
+ uint8_t sb=0;
+ hhd70_spi_cs_enable();
+ hhd70_c1101_wait_chip_rdy();
+ sb = c1101_spi_write_byte_ok_get_status(CC1101_HEADER_COMMAND | CC1101_CMD_SNOP);
+ hhd70_spi_cs_disable();
+ c1101_handleStatusByte(sb);
+ return sb;
+}
+
+uint8_t c1101_getMARCState(void)
+{
+ uint8_t sb=0;
+ sb = c1101_spi_read_register(CC1101_REG_RO_MARCSTATE);
+ sb &= 0x1F;
+ //debug start
+ /* uint8_t debug_sb[6]; */
+ /* printf("c1101 MARCState:\r\n"); */
+ /* debug_sprint_int16hex(debug_sb, sb); */
+ /* printf("%s", debug_sb); */
+ /* printf("\r\n"); */
+ //debug end
+ return sb;
+}
+
+uint8_t c1101_getNumBytesInTXFifo(void)
+{
+ return c1101_spi_read_register(CC1101_REG_RO_TXBYTES);
+}
+
+
+//true if IDLE state reached before timeout [ms]
+bool c1101_waitUntilIDLEState(uint16_t timeout_ms)
+{
+ uint8_t sb;
+ for (uint16_t c = 0; c < timeout_ms; c++)
+ {
+ sb = c1101_getStatus();
+ if (CC1101_STATUS_IDLE(sb))
+ return true;
+ _delay_ms(1);
+ }
+ return false;
+}
+
+//wait until C1101 left TX State
+bool c1101_waitUntilTXFinished(uint16_t timeout_ms)
+{
+ uint8_t c1101_state;
+ for (uint16_t c = 0; c < timeout_ms; c++)
+ {
+ c1101_state = c1101_getMARCState();
+ c1101_handleMARCStatusByte(c1101_state);
+ _delay_ms(1);
+ if (! (c1101_state == 19 || c1101_state == 20))
+ return true;
+ }
+ return false;
+}
+
+//wait until in IDLE or RX State:
+bool c1101_waitUntilIDLEorRXState(uint16_t timeout_ms)
+{
+ uint8_t c1101_state;
+ for (uint16_t c = 0; c < timeout_ms; c++)
+ {
+ c1101_state = c1101_getMARCState();
+ c1101_handleMARCStatusByte(c1101_state);
+ _delay_ms(1);
+ if (c1101_state == 1 || (c1101_state >= 13 && c1101_state <= 15))
+ return true;
+ }
+ return false;
+}
+
+bool c1101_writeFrequencyRegisters(uint32_t freq)
+{
+ if (! c1101_waitUntilIDLEState(2000)) //wait 2sec max
+ return false;
+ //programm frequency
+ c1101_spi_write_register(CC1101_REG_RW_FREQ0, freq & 0xFF);
+ c1101_spi_write_register(CC1101_REG_RW_FREQ1, (freq >> 8) & 0xFF);
+ c1101_spi_write_register(CC1101_REG_RW_FREQ2, (freq >> 16) & 0x3F);
+
+ //set channel 0
+ c1101_spi_write_register(CC1101_REG_RW_CHANNR, 0);
+ return true;
+}
+
+uint32_t c1101_readFrequencyRegisters(void)
+{
+ uint32_t freq = 0;
+ freq = ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_FREQ2)) & 0x3F;
+ freq = freq << 8;
+ freq |= ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_FREQ1));
+ freq = freq << 8;
+ freq |= ((uint8_t) c1101_spi_read_register(CC1101_REG_RW_FREQ0));
+ return freq;
+}
+
+//f_XOSC = 26Mhz
+// freq: desired_carrier_freq [Hz] *2^16 / f_XOSC
+bool c1101_setFrequency(uint32_t freq_hz)
+{
+ uint32_t freq = (uint32_t)((float)freq_hz / CC1101_FREQ_CORR);
+ if ( freq <= 0x3FFFFF)
+ return c1101_writeFrequencyRegisters(freq);
+ else
+ return false;
+}
+
+//f_XOSC = 26Mhz
+// freq: desired_carrier_freq [Hz] *2^16 / f_XOSC
+bool c1101_changeFrequencyByRelativeValue(int32_t freq_change_hz)
+{
+ int32_t freq_change = (int32_t)((float)freq_change_hz / CC1101_FREQ_CORR);
+ int32_t freq = (int32_t) c1101_readFrequencyRegisters();
+
+ freq += freq_change;
+
+ if ( freq >= 0 && freq <= 0x3FFFFF )
+ return c1101_writeFrequencyRegisters((uint32_t) freq);
+ else
+ return false;
+}
+
+uint32_t c1101_getCurrentCarrierFrequencyHz(void)
+{
+ return (uint32_t)((float)c1101_readFrequencyRegisters() * CC1101_FREQ_CORR);
+}
+
+// if_freq: desired intermidiate rx frequency [Hz] *2^10 / f_XOSC
+bool c1101_setIFFrequency(uint32_t freq_hz)
+{
+ uint8_t if_freq = freq_hz / 25391;
+ //make sure we are in idle mode
+ if (! c1101_waitUntilIDLEState(2000)) //wait 2sec max
+ return false;
+
+ c1101_spi_write_register(CC1101_REG_RW_FSCTRL1, if_freq & 0x1F);
+ return true;
+}
+
+bool c1101_transmitData(uint8_t *buffer, uint8_t len)
+{
+ //~ uint8_t debug_sb[6];
+ uint8_t num_written = 0;
+ bool success = true;
+ //~ uint8_t mcsm1 = c1101_spi_read_register(CC1101_REG_RW_MCSM1);
+ //~ //configure state machine to automatically go to IDLE, once packet was transmitted
+ //~ mcsm1 = (mcsm1 & 0b11111100) | 0b00;
+ //~ c1101_spi_write_register(CC1101_REG_RW_MCSM1, 0x18);
+ //~ c1101_spi_write_register(CC1101_REG_RW_PKTCTRL0, 0b0000000001); //crc disabled; use FIFOs; variable packet length mode (first TX FIFO byte must be length)
+ // flush TX FIFO
+ c1101_spi_strobe_command(CC1101_CMD_SFTX);
+
+ //~ //fill buffer
+ //~ num_written = c1101_spi_write_txfifo(buffer, len);
+ //~ buffer += num_written;
+ //~ len -= num_written;
+
+ //~ ((uint8_t*)"TX num written",255);
+ //~ debug_sprint_int16hex(debug_sb, num_written);
+ //~ (debug_sb,255);
+ //~ ((uint8_t*)"TX len",255);
+ //~ debug_sprint_int16hex(debug_sb, len);
+ //~ (debug_sb,255);
+
+ //~ c1101_getStatus();
+ //~ ((uint8_t*)"TX bytes",255);
+ //~ debug_sprint_int16hex(debug_sb, c1101_getNumBytesInTXFifo());
+ //~ (debug_sb,255);
+
+ //start transmitting
+ //num_written = c1101_spi_strobe_command(CC1101_CMD_STX);
+ //~ num_written = hhd70_spi_exchange_byte(CC1101_CMD_STX);
+ //~ ((uint8_t*)"Strobe STX",255);
+ //~ debug_sprint_int16hex(debug_sb, num_written);
+ //~ (debug_sb,255);
+
+ //enable Power Amplifier
+ hhd70_palna_txmode(); //should actually be done by c1101 itself, by connecting PTT function of GPO0 pin to LNA/PA toggle
+
+ //keep buffer filled
+ do
+ {
+ c1101_getStatus();
+ num_written = c1101_spi_write_txfifo(buffer, len );
+ buffer += num_written;
+ len -= num_written;
+
+ //wait until in IDLE or RX State:
+ if (! c1101_waitUntilIDLEorRXState(10000)) //wait for max 10s
+ {
+ success = false;
+ goto c1101_transmitData_cleanup;
+ }
+ //from state IDLE or RX go to TX
+ num_written = c1101_spi_strobe_command(CC1101_CMD_STX);
+
+ //~ ((uint8_t*)"TX2 num written",255);
+ //~ debug_sprint_int16hex(debug_sb, num_written);
+ //~ (debug_sb,255);
+ //~ ((uint8_t*)"TX2 len",255);
+ //~ debug_sprint_int16hex(debug_sb, len);
+ //~ (debug_sb,255);
+ //~ ((uint8_t*)"TX2 bytes",255);
+ //~ debug_sprint_int16hex(debug_sb, c1101_getNumBytesInTXFifo());
+ //~ (debug_sb,255);
+ } while (len > 0);
+
+ //wait until TX finished
+ if (!c1101_waitUntilTXFinished(10000)) //wait 10s max, then just shut down PA
+ {
+ success = false;
+ goto c1101_transmitData_cleanup;
+ }
+
+ c1101_transmitData_cleanup:
+ //disable Power Amplifier
+ //FIXME, instead use PTT function of GPO0 -> interrupt handler -> toggle rx/tx
+ hhd70_palna_rxmode();
+ return success;
+}
+
+void c1101_transmitData_infPktMode(uint8_t *buffer, uint8_t len)
+{
+ //in infinite Packet Mode, prepend length to buffer:
+ uint8_t *new_buffer = malloc(len+1);
+ new_buffer[0] = len;
+ memcpy(new_buffer+1, buffer, len);
+ //variable packet length: write length of packet to TX FIFO:
+ c1101_transmitData(new_buffer, len+1);
+ free(new_buffer);
+}
+
+void c1101_recieveData(void)
+{
+ uint8_t const max_len=255;
+ uint8_t recv_data[256];
+ uint8_t num_recv = 0;
+ uint8_t num_recv_total = 0;
+ uint8_t num_leave_in_fifo = 1;
+ do
+ {
+ num_recv = c1101_spi_read_rxfifo( num_leave_in_fifo, recv_data+num_recv_total, max_len - num_recv_total);
+ num_recv_total += num_recv;
+
+ //variable packet length:
+ //don't read last byte in fifo unless packet has finished receiving
+ num_leave_in_fifo = (recv_data[0] - num_recv_total < 64)? 0 : 1;
+ } while (num_recv > 0);
+ recv_data[num_recv_total]=0;
+ printf("RX: Data Recieved: ");
+ printf("%s", recv_data);
+ printf("\r\n");
+ c1101_getStatus(); // get status and handle possiblble RX Fifo Overflow
+}
+
+//max returned: 64 bytes
+int c1101_readRXFifo(uint8_t *buffer)
+{
+ //check RXBYTES.NUM_RXBYTES
+ // never read more bytes than avaiblabe or we will read garbage
+
+ //note: if RX transmission fills fifo buffer at exact same time as last RX Fifo Bit is read via SPI, Fifo Pointer will not be properly updated
+ // and last read byte will be duplicated.
+ // thus: don't last avialable FIFO Bytes unless we can be sure that it will be the last byte of a packet and we can be sure that a following duplicated byte is actually an Fifo duplication and not an actually recieved byte !
+
+ return 0;
+}
diff --git a/software/hhd70dongle.old/c1101lib.h b/software/hhd70dongle.old/c1101lib.h
new file mode 100644
index 0000000..f24126b
--- /dev/null
+++ b/software/hhd70dongle.old/c1101lib.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ * 2015 Christian Pointner <equinox@mur.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef MURSAT_c1101lib_h_INCLUDED
+#define MURSAT_c1101lib_h_INCLUDED
+
+#include <stdbool.h>
+
+// TODO: should be internal only...
+int16_t c1101_spi_read_register(uint8_t address);
+int16_t c1101_spi_write_register(uint8_t address, uint8_t byte);
+int16_t c1101_spi_strobe_command(uint8_t cmd);
+
+void c1101_init(void);
+void c1101_init_ook_beacon(void);
+
+uint8_t c1101_ook_power_get(void);
+uint8_t c1101_ook_power_get_raw(void);
+void c1101_ook_power_set(uint8_t power);
+void c1101_ook_power_inc(void);
+void c1101_ook_power_dec(void);
+
+void c1101_handleStatusByte(uint8_t sb);
+uint8_t c1101_getStatus(void);
+
+uint16_t c1101_measureTemp(void);
+void c1101_spi_dump_registers(void);
+void c1101_permanently_save_current_rx_tx_freqoffset_auto_compensation(void);
+bool c1101_setFrequency(uint32_t freq_hz);
+bool c1101_changeFrequencyByRelativeValue(int32_t freq_change_hz);
+uint32_t c1101_getCurrentCarrierFrequencyHz(void);
+bool c1101_setIFFrequency(uint32_t freq_hz);
+uint16_t c1101_setFSKDeviationFromCarrier(int8_t m, int8_t e);
+
+bool c1101_transmitData(uint8_t *buffer, uint8_t len);
+void c1101_transmitData_infPktMode(uint8_t *buffer, uint8_t len);
+void c1101_recieveData(void);
+
+//max returned: 64 bytes
+int c1101_readRXFifo(uint8_t *buffer);
+
+#endif
diff --git a/software/hhd70dongle.old/hhd70.c b/software/hhd70dongle.old/hhd70.c
new file mode 100644
index 0000000..1e3b5c7
--- /dev/null
+++ b/software/hhd70dongle.old/hhd70.c
@@ -0,0 +1,184 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ * 2015 Christian Pointner <equinox@mur.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "avr/io.h"
+
+#include "hhd70.h"
+
+#define BIAS_VAL OCR1BL
+
+static void hhd70_bias_init(void)
+{
+ DDRB |= (1<<PB6);
+ TCCR1B = 0;
+ TCNT1 = 0;
+ OCR1B = 0;
+ TCCR1A = (1<<COM1B1) | (1<<WGM10);
+ TCCR1B = (1<<WGM12);
+}
+
+static inline void hhd70_bias_on(void)
+{
+ TCCR1B = (TCCR1B & 0xF8) | (1<<CS10);
+}
+
+static inline void hhd70_bias_off(void)
+{
+ TCCR1B = (TCCR1B & 0xF8);
+ TCNT1 = 0;
+}
+
+void hhd70_init(void)
+{
+ //configure Direction of SS / PB0 , MOSI and SCLK as Output to drive CS of CC1101
+ SPI_DDR = (1<<MOSI)|(1<<SCK)|(1<<CS)|(1<<TE)|(1<<BIAS_PWM);
+ SPI_PORT = (1<<CS) | (1<<GDO2) | (1<<BIAS_PWM);
+ SPCR = (1<<SPE)|(1<<MSTR); // | (0<<DORD) //select MSB first: DORD == 0
+ // SPSR = (0<<SPI2X) // f_osc/4
+ // SPSR = (1<<SPI2X) // f_osc/2
+ // SPSR = (1<<SPI2X); (4MHz vs. 8MHz)
+ hhd70_bias_init();
+}
+
+void hhd70_config_GDO0_OOK_output(bool output_mode)
+{
+ hhd70_set_OOK_GDO0_low();
+ if (output_mode)
+ SPI_DDR |= (1 << GDO0);
+ else
+ SPI_DDR &= ~(1 << GDO0);
+}
+
+void hhd70_set_OOK_GDO0_high(void)
+{
+ SPI_PORT |= (1 << GDO0);
+}
+
+void hhd70_set_OOK_GDO0_low(void)
+{
+ //pull low
+ SPI_PORT &= ~(1<<GDO0);
+}
+
+void hhd70_set_OOK_GDO0_toggle(void)
+{
+ SPI_PORT ^= (1 << GDO0);
+}
+
+void hhd70_spi_cs_enable(void)
+{
+ //pull low
+ SPI_PORT &= ~(1<<CS);
+}
+
+void hhd70_spi_cs_disable(void)
+{
+ //pull high
+ SPI_PORT |= (1<<CS);
+}
+
+#include "util.h"
+
+void hhd70_c1101_wait_chip_rdy(void)
+{
+ //c1101 will set MISO to low if ready
+ while (SPI_PINB_REG & (1<<MISO));
+ //~ unsigned int c;
+ //~ for (c=0; c < 0xFFFFFFFF && (SPI_PINB_REG & (1<<MISO)); c++);
+ //~ uint8_t debug_buff[6];
+ //~ usb_rawhid_send((uint8_t*)"spi waited for:",255);
+ //~ debug_sprint_int16hex(debug_buff, c);
+ //~ usb_rawhid_send(debug_buff,255);
+}
+
+void hhd70_spi_write_byte(char byte)
+{
+ SPDR = byte; //Load byte to Data register
+ while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
+}
+
+char hhd70_spi_exchange_byte(char byte)
+{
+ hhd70_spi_write_byte(byte);
+ return SPDR;
+}
+
+char hhd70_spi_read_byte(void)
+{
+ //transmit something so SCLK runs for 8 bits, so that slave can transfer 1 byte
+ return hhd70_spi_exchange_byte(0);
+}
+
+void hhd70_palna_txmode(void)
+{
+ SPI_PORT |= (1<<TE);
+ hhd70_bias_on();
+}
+
+void hhd70_palna_rxmode(void)
+{
+ SPI_PORT &= ~(1<<TE);
+ hhd70_bias_off();
+}
+
+void hhd70_palna_off(void)
+{
+ SPI_PORT |= (1<<TE);
+ hhd70_bias_off();
+}
+
+int8_t hhd70_rx_data_available(void)
+{
+ //check if GDO2 pin has been pulled low by c1101
+ return (SPI_PINB_REG & (1 << GDO2)) == 0;
+}
+
+void hhd70_bias_set(uint8_t val)
+{
+ BIAS_VAL = val;
+}
+
+uint8_t hhd70_bias_get(void)
+{
+ return BIAS_VAL;
+}
+
+void hhd70_bias_inc(void)
+{
+ BIAS_VAL = (BIAS_VAL < 253) ? BIAS_VAL + 2 : 255;
+}
+
+void hhd70_bias_dec(void)
+{
+ BIAS_VAL = (BIAS_VAL > 2) ? BIAS_VAL - 2 : 0;
+}
+
diff --git a/software/hhd70dongle.old/hhd70.h b/software/hhd70dongle.old/hhd70.h
new file mode 100644
index 0000000..a1faea6
--- /dev/null
+++ b/software/hhd70dongle.old/hhd70.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ * 2015 Christian Pointner <equinox@mur.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MURSAT_hhd70_h_INCLUDED
+#define MURSAT_hhd70_h_INCLUDED
+
+#include <stdbool.h>
+
+#define SPI_DDR DDRB
+#define SPI_PORT PORTB
+#define SPI_PINB_REG PINB
+#define CS DDB0
+#define SCK DDB1
+#define MOSI DDB2
+// MISO DDB3 is also GDO1 (can be used when CS == 0)
+#define MISO DDB3
+//GDO2 currently used for RX Buffer Filled Interrupt
+#define GDO2 DDB4
+//GDO0 currently only used for c1101 internal temperature sensor
+//GDO0 future use: connect directly to RX/TX Switch (set GDO0_CFG to 0x2F)
+#define GDO0 DDB5
+#define BIAS_PWM DDB6
+#define TE DDB7
+
+
+void hhd70_init(void);
+void hhd70_spi_cs_enable(void);
+void hhd70_spi_cs_disable(void);
+void hhd70_c1101_wait_chip_rdy(void);
+void hhd70_spi_write_byte(char byte);
+char hhd70_spi_read_byte(void);
+char hhd70_spi_exchange_byte(char byte);
+void hhd70_palna_txmode(void);
+void hhd70_palna_rxmode(void);
+void hhd70_palna_off(void);
+int8_t hhd70_rx_data_available(void);
+void hhd70_config_GDO0_OOK_output(bool output_mode);
+void hhd70_set_OOK_GDO0_high(void);
+void hhd70_set_OOK_GDO0_low(void);
+void hhd70_set_OOK_GDO0_toggle(void);
+void hhd70_bias_set(uint8_t val);
+uint8_t hhd70_bias_get(void);
+void hhd70_bias_inc(void);
+void hhd70_bias_dec(void);
+
+#endif
diff --git a/software/hhd70dongle.old/hhd70dongle.c b/software/hhd70dongle.old/hhd70dongle.c
new file mode 100644
index 0000000..f28886d
--- /dev/null
+++ b/software/hhd70dongle.old/hhd70dongle.c
@@ -0,0 +1,438 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ * 2015 Christian Pointner <equinox@mur.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <avr/io.h>
+#include <avr/wdt.h>
+#include <util/delay.h>
+#include <stdio.h>
+#include <avr/interrupt.h>
+//#include <avr/power.h>
+
+#include "led.h"
+#include "util.h"
+#include "usbio.h"
+
+#include "hhd70.h"
+#include "c1101lib.h"
+#include "cc1101_defines.h"
+
+//todo: move to separte File:
+
+// If TTX_EN goes high, ~ <=500ms before TTX CW Sender forcefully disables our RX/TX Signal Path
+//IF TTX_EN goes low, we have ~ 1min (Beacon Interval) until the next CW Beacon is sent and our RX/TX Signal Path is forcefully disabled
+// Beacon Interval Time can be measured by counting with an interrupt triggered by RTC_SECONDS Input
+//#define TTX_EN <port>
+//#define RTC_SECONDS <port>
+
+
+#define CPU_PRESCALE(n) do { CLKPR = 0x80; CLKPR = (n); } while(0)
+char read_buffer[64]; // buffer for reading usb signals
+char write_buffer[64]; // buffer for writing usb signals
+
+//TODOs:
+//* make adc work ?
+// * remove code duplications
+// * speed up and simplify code
+// * make as much use of sleep modes as possible
+// * use adc noise canceler (i.e. automatic sampling during cpu sleep)
+// * read atmega temp
+// * safely save state in eeprom (2 memory regions, only use the one with the "written successfully bit" which is written last)
+// * what if c1101 resets spuriously and clears it's settings ? -> check peridically ?
+
+bool enable_tx_part=false;
+bool enable_rx_part=false;
+bool enable_beacon_part=false;
+
+void print_part_status(void)
+{
+ printf("OOK Beacon: ");
+ printf(((enable_beacon_part)? "Enabled": "Disabled") );
+ printf("\r\n");
+ printf("RX-Part: ");
+ printf(((enable_rx_part)? "Enabled": "Disabled") );
+ printf("\r\n");
+ printf("TX-Part: ");
+ printf(((enable_tx_part)? "Enabled": "Disabled") );
+ printf("\r\n");
+}
+
+//void generate_morse_code_sequence(char *msg, *cw_buffer, uint16_t buffer_len)
+//{
+ //char cw_short[2] = {1,1};
+ //char cw_long[2] = {1,3};
+ //char cw_space[2] = {0, 1};
+ //char cw_letterspace[2] = {0,3};
+ //char cw_wordspace[2] = {0, 7};
+//}
+
+void beacon_enable(void)
+{
+ c1101_spi_strobe_command(CC1101_CMD_STX);
+ hhd70_palna_txmode();
+}
+
+void beacon_on(void)
+{
+ hhd70_set_OOK_GDO0_high();
+ led_on();
+}
+
+void beacon_off(void)
+{
+ led_off();
+ hhd70_set_OOK_GDO0_low();
+}
+
+void beacon_disable(void)
+{
+ hhd70_palna_rxmode();
+ c1101_spi_strobe_command(CC1101_CMD_SIDLE);
+}
+
+int main(void)
+{
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable(); // FIXME: disable WatchDog for now, but use it later...
+ CPU_PRESCALE(0); //cpu_init
+
+ led_init();
+ usbio_init();
+
+ hhd70_init();
+ DDRB &= ~(1<<DDB5); // set PB5/ADC12 to INPUT (c1101 temp sensor)
+ sei(); //set enable global interrupt
+
+ printf("hhd70dongle ready\r\n");
+
+ _delay_ms(500);
+ c1101_spi_strobe_command(CC1101_CMD_SRES); // reset c1101
+ //c1101 init now happens after pressing B, S or E
+
+ hhd70_palna_rxmode();
+ hhd70_bias_set(255);
+
+ enable_tx_part=false;
+ enable_rx_part=false;
+ enable_beacon_part=false;
+ int8_t fdev_m = 1;
+ int8_t fdev_e = 1;
+ uint32_t prev_ook_freq = c1101_getCurrentCarrierFrequencyHz();
+
+ //char mursat_beacon[256];
+ //for(int i=0;i<sizeof(mursat_beacon);++i) {
+ // mursat_beacon[i] = 0xFF;
+ //}
+
+ for(;;)
+ {
+ int16_t num_bytes_received = usbio_bytes_received();
+ while(num_bytes_received > 0)
+ {
+ int16_t recv_byte = fgetc(stdin);
+ num_bytes_received--;
+ if (recv_byte == EOF)
+ continue;
+ if ((char) recv_byte == '!')
+ {
+ printf("resetting\r\n");
+ wdt_enable(WDTO_500MS);
+ reset();
+ }
+ else if ((char) recv_byte == 'N') {
+ enable_tx_part=false;
+ enable_rx_part=false;
+ enable_beacon_part=false;
+ c1101_spi_strobe_command(CC1101_CMD_SRES); // reset c1101
+ hhd70_palna_rxmode();
+ print_part_status();
+ led_off();
+ }
+ else if ((char) recv_byte == 'B')
+ {
+ enable_beacon_part = !enable_beacon_part;
+ if (enable_beacon_part)
+ {
+ enable_rx_part=false;
+ enable_tx_part=false;
+ c1101_init_ook_beacon();
+
+ printf("CC1101 enabling Beacon with Power: %3d (0x%02X)\r\n", (int)c1101_ook_power_get(), (int)c1101_ook_power_get_raw());
+
+ beacon_enable();
+ beacon_on();
+ }
+ print_part_status();
+ }
+ else if ((char) recv_byte == 'E')
+ {
+ enable_rx_part = !enable_rx_part;
+ if (enable_rx_part)
+ {
+ enable_beacon_part=false;
+ c1101_init();
+ }
+ print_part_status();
+ }
+ else if ((char) recv_byte == 'S')
+ {
+ enable_tx_part = !enable_tx_part;
+ if (enable_tx_part)
+ {
+ enable_beacon_part=false;
+ c1101_init();
+ }
+ print_part_status();
+ }
+ else if ((char) recv_byte == 'R')
+ {
+ c1101_spi_dump_registers();
+ print_part_status();
+ }
+ else if ((char) recv_byte == 'D' || (char) recv_byte == 'd')
+ {
+ printf("FSK Freq Deviation Now: %u0 Hz\r\n", c1101_setFSKDeviationFromCarrier(fdev_m, fdev_e));
+ if ((char) recv_byte == 'd')
+ {
+ fdev_m--;
+ if (fdev_m < 0)
+ {
+ fdev_e = (fdev_e - 1) % 8;
+ if (fdev_e < 0)
+ fdev_e = 7;
+ fdev_m = 7;
+ }
+ fdev_m %= 8;
+ }
+ else
+ {
+ fdev_m++;
+ if (fdev_m > 7)
+ fdev_e = (fdev_e + 1) % 8;
+ fdev_m %= 8;
+ }
+ }
+ else if ((char) recv_byte == '+' || (char) recv_byte == '-' || (char) recv_byte == '#' || (char) recv_byte == '_' || (char) recv_byte == ':' || (char) recv_byte == '.' || (char) recv_byte == 'f'|| (char) recv_byte == '?')
+ {
+ int32_t change_freq = 0;
+ switch (recv_byte)
+ {
+ case '+':
+ change_freq = 1000000;
+ break;
+ case '-':
+ change_freq = -1000000;
+ break;
+ case '#':
+ change_freq = 10000000;
+ break;
+ case '_':
+ change_freq = -10000000;
+ break;
+ case ':':
+ change_freq = 100000;
+ break;
+ case '.':
+ change_freq = -100000;
+ break;
+ case 'f':
+ printf("Setting Frequency to previously adjusted value.\r\n");
+ c1101_setFrequency(prev_ook_freq);
+ break;
+ case '?':
+ //just show current frequency
+ break;
+ }
+ if (change_freq != 0)
+ {
+ if (enable_beacon_part) beacon_off();
+ beacon_disable();
+
+ printf("Frequency %s by %lu KHz - ", (change_freq > 0 ? "up" : "down"), (change_freq > 0 ? 1 : -1) * change_freq / 1000);
+ c1101_changeFrequencyByRelativeValue(change_freq);
+ prev_ook_freq = c1101_getCurrentCarrierFrequencyHz();
+
+ if (enable_beacon_part) {
+ beacon_enable();
+ beacon_on();
+ }
+ }
+ uint32_t hz = c1101_getCurrentCarrierFrequencyHz();
+ uint16_t mhz = hz / 1000000;
+ uint16_t khz = (hz % 1000000)/1000;
+ hz %= 1000;
+ printf("Frequency is now: %d.%03d%03d MHz\r\n", mhz, khz, (uint16_t)hz);
+ }
+ else if ((char) recv_byte == 'p')
+ {
+ hhd70_bias_dec();
+ printf("Bias Power is now: %d\r\n", hhd70_bias_get());
+ }
+ else if ((char) recv_byte == 'P')
+ {
+ hhd70_bias_inc();
+ printf("Bias Power is now: %d\r\n", hhd70_bias_get());
+ }
+ else if ((char) recv_byte == 'o')
+ {
+ if (enable_beacon_part) beacon_off();
+ beacon_disable();
+
+ c1101_ook_power_dec();
+ printf("CC1101 Power is now: %3d (0x%02X)\r\n", (int)c1101_ook_power_get(), (int)c1101_ook_power_get_raw());
+
+ if (enable_beacon_part) {
+ beacon_enable();
+ beacon_on();
+ }
+ }
+ else if ((char) recv_byte == 'O')
+ {
+ if (enable_beacon_part) beacon_off();
+ beacon_disable();
+
+ c1101_ook_power_inc();
+ printf("CC1101 Power is now: %3d (0x%02X)\r\n", (int)c1101_ook_power_get(), (int)c1101_ook_power_get_raw());
+
+ if (enable_beacon_part) {
+ beacon_enable();
+ beacon_on();
+ }
+ }
+ else if ((char) recv_byte == ' ')
+ {
+ if (enable_beacon_part) {
+ hhd70_set_OOK_GDO0_toggle();
+ }
+ }
+ }
+
+
+ usbio_task();
+
+ if (enable_rx_part)
+ {
+
+ c1101_spi_strobe_command(CC1101_CMD_SRX); // enter RX - Mode
+ _delay_ms(1000);
+
+ if (hhd70_rx_data_available())
+ {
+ led_on();
+ printf("RX: GDO2 pin HIGH\r\n");
+ printf("c1101 rx bytes:");
+ debug_sprint_int16hex(write_buffer, c1101_spi_read_register(CC1101_REG_RO_RXBYTES));
+ printf("%s", write_buffer);
+ printf("\r\n");
+ c1101_recieveData();
+ led_off();
+ }
+
+ printf("c1101 rssi: ");
+ debug_sprint_int16hex(write_buffer, c1101_spi_read_register(CC1101_REG_RO_RSSI));
+ printf("%s", write_buffer);
+ printf("\r\n");
+ printf("c1101 tx bytes: ");
+ debug_sprint_int16hex(write_buffer, c1101_spi_read_register(CC1101_REG_RO_TXBYTES));
+ printf("%s", write_buffer);
+ printf("\r\n");
+ printf("c1101 rx bytes: ");
+ int16_t num_rx_bytes = c1101_spi_read_register(CC1101_REG_RO_RXBYTES);
+ debug_sprint_int16hex(write_buffer, num_rx_bytes);
+ printf("%s", write_buffer);
+ printf("\r\n");
+
+
+ //~ if (num_rx_bytes > 0)
+ //~ {
+ //~ led_on();
+ //~ printf("RX Buffer Non-Empty\r\n");
+ //~ c1101_recieveData();
+ //~ led_off();
+ //~ }
+
+// printf("c1101 status byte: ");
+// debug_sprint_int16hex(write_buffer, c1101_getStatus());
+// printf("%s", write_buffer);
+// printf("\r\n");
+
+ }
+
+ if (enable_tx_part)
+ {
+ /* write_buffer[0]='T'; */
+ /* write_buffer[1]='e'; */
+ /* write_buffer[2]='m'; */
+ /* write_buffer[3]='p'; */
+ /* write_buffer[4]='s'; */
+ /* write_buffer[5]=':'; */
+ /* adc_on(); */
+ /* _delay_ms(250); */
+ /* printf("temp c1101: "); */
+ /* debug_sprint_int16hex(write_buffer+6, c1101_measureTemp()); */
+ /* printf("%s", write_buffer+6); */
+ /* printf("\r\n"); */
+ /* _delay_ms(250); */
+ /* printf("temp atmega: "); */
+ /* debug_sprint_int16hex(write_buffer+10, adc_read(ADCMUX_ADC12)); */
+ /* printf("%s", write_buffer+10); */
+ /* printf("\r\n"); */
+ /* adc_off(); */
+ /* _delay_ms(250); */
+ /* led_on(); */
+ /* printf("TX Data: String\r\n"); */
+ /* c1101_transmitData_infPktMode("OE6EOF test mur.sat GFSK r:9k6 fdev:11kHz 1234567890123456789012345678901234567890 End of Test",93); */
+ /* led_off(); */
+ /* _delay_ms(100); */
+ /* led_on(); */
+ /* printf("TX Data: Temps\r\n"); */
+ /* c1101_transmitData_infPktMode((char*) write_buffer,14); */
+ /* led_off(); */
+ }
+
+/* if (enable_beacon_part)
+ {
+ //char mursat_beacon[8] = {0b11101110, 0b11100010, 0b00111010, 0b10101000, 0b10001110, 0b11101110, 0b00101011, 0b10100000}; //OE6EOF
+ printf("OOK Sending Beacon\r\n");
+ led_on();
+ //c1101_transmitData_infPktMode(mursat_beacon,sizeof(mursat_beacon));
+ hhd70_palna_txmode();
+ c1101_spi_strobe_command(CC1101_CMD_STX);
+ hhd70_set_OOK_GDO0_high();
+ _delay_ms(1000);
+ led_off();
+ hhd70_set_OOK_GDO0_low();
+ c1101_spi_strobe_command(CC1101_CMD_SIDLE);
+ hhd70_palna_rxmode();
+ _delay_ms(200);
+ }*/
+ }
+}
diff --git a/software/hhd70dongle.old/readme.txt b/software/hhd70dongle.old/readme.txt
new file mode 100644
index 0000000..58e24b9
--- /dev/null
+++ b/software/hhd70dongle.old/readme.txt
@@ -0,0 +1,31 @@
+Commands:
+
+'S' ... enables GFSK test sending mode
+'E' ... enables GFSK test recieving mode
+'B' ... enables Beacon-Mode, i.e. device enters OOK (OnOffKeying) mode and periodically enables the carrier for 1000ms and then pauses for 200ms
+
+S and E can be actived at the same time
+B deactivates S and E
+S or E deactivate B
+
+Each use of S,E or B reinitialize C1101 and thus reset all adjustments.
+
+'R' ... dumps the value of C1101 registers
+
+
+Changing GFSK frequency deviation:
+'D' ... increases GFSK frequency deviation
+'d' ... decreases GFSK frequency deviation
+obviously not much use in Beacon-Mode
+
+
+Using the Beacon Test Mode:
+'B' ... reinitializes C1101 and resets frequency to 435.199677, then starts OOK transmission
+'?' ... shows current frequency
+'#' ... increases frequency by 10 MHz
+'_' ... decreases frequency by 10 MHz
+'+' ... increases frequency by 1 MHz
+'-' ... decreases frequency by 1 MHz
+':' ... increases frequency by 100 KHz
+'.' ... decreases frequency by 100 KHz
+'f' ... sets frequency to previously adjusted valued. e.g. restore frequency after disabling, then reenabling Beacon-Mode 'B'
diff --git a/software/hhd70dongle.old/reset.sh b/software/hhd70dongle.old/reset.sh
new file mode 100755
index 0000000..9339f9f
--- /dev/null
+++ b/software/hhd70dongle.old/reset.sh
@@ -0,0 +1,3 @@
+#!/bin/zsh
+echo \! > ${1-/dev/ttyACM*}
+sleep 4
diff --git a/software/hhd70dongle.old/util.c b/software/hhd70dongle.old/util.c
new file mode 100644
index 0000000..dce23b9
--- /dev/null
+++ b/software/hhd70dongle.old/util.c
@@ -0,0 +1,87 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "util.h"
+
+typedef void (*f_ptr_type)(void);
+f_ptr_type start_bootloader = (f_ptr_type)0x3800;
+
+void reset(void)
+{
+ cli();
+ // disable watchdog, if enabled
+ // disable all peripherals
+ UDCON = 1;
+ USBCON = (1<<FRZCLK); // disable USB
+ UCSR1B = 0;
+ _delay_ms(5);
+ EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+ TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
+ DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
+ PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+ start_bootloader();
+}
+
+//not switchin off adc produces slightly besser results
+void adc_on(void)
+{
+ ADCSRA = (1<<ADEN) | 0b00000111; // enable ADC, Prescaler 1:128
+}
+
+void adc_off(void)
+{
+ ADCSRA &= ~(1<<ADEN); // disable ADC -> save power
+}
+
+uint8_t adc_read(uint8_t mux)
+{
+ ADCSRB = (mux & 0x20); // select input
+ ADMUX = 0b11100000 | (mux & 0x1F); // select input cont'd
+ // select internal 2.56V reference,
+ // result is left justified
+ ADCSRA |= (1<<ADSC); // start the conversion
+ while (ADCSRA & (1<<ADSC)) ; // wait for result
+ return ADCH;
+}
+
+void debug_sprint_int16hex(char *buffer, int16_t num)
+{
+ int c,n;
+ for (c=0; c<4; c++)
+ {
+ n = (num >> (3-c)*4 ) & 15;
+ buffer[c] = n + ((n < 10) ? '0' : 'A' - 10);
+ }
+ buffer[4]=0;
+}
diff --git a/software/hhd70dongle.old/util.h b/software/hhd70dongle.old/util.h
new file mode 100644
index 0000000..e93f96f
--- /dev/null
+++ b/software/hhd70dongle.old/util.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * mur.sat
+ *
+ * Somewhen in the year 20xx, mur.at will have a nano satellite launched
+ * into a low earth orbit (310 km above the surface of our planet). The
+ * satellite itself is a TubeSat personal satellite kit, developed and
+ * launched by interorbital systems. mur.sat is a joint venture of mur.at,
+ * ESC im Labor and realraum.
+ *
+ * Please visit the project hompage at sat.mur.at for further information.
+ *
+ *
+ * Copyright (C) 2012 Bernhard Tittelbach <xro@realraum.at>
+ *
+ * This file is part of mur.sat.
+ *
+ * mur.sat 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
+ * any later version.
+ *
+ * mur.sat 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 mur.sat. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MURSAT_util_h_INCLUDED
+#define MURSAT_util_h_INCLUDED
+
+#define ADCMUX_INTERNALTEMP 0b00100111
+#define ADCMUX_ADC12 0b00100100
+
+void reset(void);
+void adc_on(void);
+void adc_off(void);
+uint8_t adc_read(uint8_t mux);
+void debug_sprint_int16hex(char *buffer, int16_t num);
+
+#endif