Hast du schon aufgeräumt?
Ich würds auch unaufgeräumt nutzen...und aufräumen.
Ich würds auch unaufgeräumt nutzen...und aufräumen.
Wie gesagt, is viel debugging drin was es unübersichtlich macht. Zudem wurden alle statischen arrays und strings ins Flash gelegt um RAM zu sparen, der Framebuffer vom TV-Out frisst 1,5 der verfügbaren 2k RAM....
Code:
/*
* Based on fs_skyrf_58g-main.c
* Written by Simon Chambers
The MIT License (MIT)
Copyright (c) 2014 Simon Chambers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <TVout.h>
#include <fontALL.h>
#include <avr/pgmspace.h>
#define spiDataPin 10
#define slaveSelectPin 11
#define spiClockPin 12
#define rssiPin A6
#define buttonSeek 2
#define buttonScan 3
#define RSSIMAX 40
#define STATE_TV 0
#define STATE_SEEK 1
#define STATE_SCAN 2
#define rows 96
#define cols 128
//#define DEBUG
// Channels to sent to the SPI registers
const uint16_t channelTable[] PROGMEM = {
// Channel 1 - 8
0x2A05, 0x299B, 0x2991, 0x2987, 0x291D, 0x2913, 0x2909, 0x289F, // Band A
0x2903, 0x290C, 0x2916, 0x291F, 0x2989, 0x2992, 0x299C, 0x2A05, // Band B
0x2895, 0x288B, 0x2881, 0x2817, 0x2A0F, 0x2A19, 0x2A83, 0x2A8D, // Band E
0x2906, 0x2910, 0x291A, 0x2984, 0x298E, 0x2998, 0x2A02, 0x2A0C // Airwave
};
// Channels with their Mhz Values
const uint16_t channelFreqTable[] PROGMEM = {
// Channel 1 - 8
5865, 5845, 5825, 5805, 5785, 5765, 5745, 5725, // Band A
5733, 5752, 5771, 5790, 5809, 5828, 5847, 5866, // Band B
5705, 5685, 5665, 5645, 5885, 5905, 5925, 5945, // Band E
5740, 5760, 5780, 5800, 5820, 5840, 5860, 5880 // Airwave
};
//const char* channelNames[] PROGMEM = {
//"A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8",
//"B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8",
//"E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8",
//"W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8"
//};
const uint8_t channelNames[] PROGMEM = {
0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8
};
// All Channels of the above List ordered by Mhz
const uint8_t channelList[] PROGMEM = {
19, 18, 17, 16, 7, 8, 24, 6, 9, 25, 5, 10, 26, 4, 11, 27, 3, 12, 28, 2, 13, 29, 1, 14, 30, 0, 15, 31, 20, 21, 22, 23
};
const uint8_t offset = 7;
uint8_t channel = 0;
uint8_t channelIndex = 0;
uint8_t rssi = 0;
uint8_t hight = 0;
uint8_t state = STATE_SCAN;
uint8_t bState = HIGH;
uint8_t writePos = 0;
TVout TV;
// SETUP ----------------------------------------------------------------------------
void setup() {
// initialize digital pin 13 LED as an output.
pinMode(13, OUTPUT);
pinMode(buttonSeek, INPUT);
digitalWrite(buttonSeek, INPUT_PULLUP);
pinMode(buttonScan, INPUT);
digitalWrite(buttonScan, INPUT_PULLUP);
#ifdef DEBUG
Serial.begin(115200);
Serial.println(F("START:"));
#endif
pinMode (slaveSelectPin, OUTPUT);
pinMode (spiDataPin, OUTPUT);
pinMode (spiClockPin, OUTPUT);
#ifdef DEBUG
Serial.print(F("FREEMEM: ")); Serial.println(freeRam ());
#endif
char retVal = TV.begin(PAL, cols, rows);
// 0 if no error.
// 1 if x is not divisable by 8.
// 2 if y is to large (NTSC only cannot fill PAL vertical resolution by 8bit limit)
// 4 if there is not enough memory for the frame buffer.
if (retVal > 0) {
// on Error flicker LED
while (true) {
digitalWrite(13, !digitalRead(13));
delay(100);
}
}
TV.select_font(font4x6);
#ifdef DEBUG
Serial.print(F("FREEMEM: ")); Serial.println(freeRam ());
#endif
TV.print("5.8GHz Spectrum Analyser");
TV.print(2, (rows - offset + 2), "5645");
TV.print(57, (rows - offset + 2), "5800");
TV.print(111, (rows - offset + 2), "5945");
// Setup Done - LED ON
digitalWrite(13, HIGH);
}
// LOOP ----------------------------------------------------------------------------
void loop() {
if (digitalRead(buttonScan) == LOW) {
state = STATE_SCAN;
} else {
if (state == STATE_SCAN) {
state = STATE_SEEK;
}
}
// get Channel by Freq. Ascending
channelIndex = pgm_read_byte_near(channelList + channel);
//channelIndex = channel;
#ifdef DEBUG
Serial.print(channel); Serial.print(F(" \t"));
Serial.print(F("STATE: ")); Serial.print(state); Serial.print(F(" \t"));
Serial.print(F("CHANNELINDEX: ")); Serial.print(channelIndex); Serial.print(F(" \t"));
#endif
// if not in TV Mode, tune Module
if (state != STATE_TV) {
setChannelModule(channelIndex);
}
#ifdef DEBUG
Serial.print(F("FREQ: ")); Serial.print(pgm_read_word_near(channelFreqTable + channelIndex)); Serial.print(F("\t"));
#endif
// wait for tuning
delay(100);
// get rssi and map it to 0-70
rssi = readRSSI();
#ifdef DEBUG
Serial.print("RSSIraw: ");Serial.print(rssi); Serial.print(F("\t"));
#endif
rssi = constrain(rssi, 50, 170);
rssi = map(rssi, 170, 50, 3, 70);
#ifdef DEBUG
Serial.print("RSSI: ");Serial.print(rssi); Serial.print(F("\t"));
#endif
// if SCAN Mode, print Spectrum
if (state == STATE_SCAN) {
// print bar
hight = (rows - offset - rssi);
TV.draw_rect((channel * 4), (rows - offset - 74), 3, 70 , BLACK, BLACK);
TV.draw_rect((channel * 4), hight, 3, rssi , WHITE, WHITE);
// print channelname
if (rssi > RSSIMAX) {
TV.draw_rect(writePos, 7, 20, 6, BLACK, BLACK);
TV.print(writePos, 7, pgm_read_byte_near(channelNames + channelIndex), HEX);
TV.print(writePos+10, 7, pgm_read_word_near(channelFreqTable + channelIndex));
writePos += 30;
TV.print((channel * 4) - 3, hight - 5, pgm_read_byte_near(channelNames + channelIndex), HEX);
#ifdef DEBUG
Serial.print("NAME: ");Serial.print(pgm_read_byte_near(channelNames + channelIndex), HEX); Serial.print(F("\t"));
#endif
}
// if SEEK Mode, check RSSI and skip Channel
} else if (state == STATE_SEEK) {
if (rssi > RSSIMAX) {
state = STATE_TV;
} else {
delay(200);
}
}
if (state == STATE_TV && digitalRead(buttonSeek) == LOW) {
state = STATE_SEEK;
}
// if not in TV Mode, next Channel
if (state != STATE_TV) {
// reset Channel channeler
if (channel < 31) {
channel++;
} else {
#ifdef DEBUG
Serial.println();
#endif
TV.draw_rect(writePos, 7, cols-writePos-1, 6, BLACK, BLACK);
channel = 0;
writePos = 0;
}
}
#ifdef DEBUG
Serial.println(F(""));
#endif
}
uint16_t readRSSI() {
uint16_t rssi = 0;
for (uint8_t i = 0; i <= 10; i++) {
rssi += analogRead(rssiPin);
}
return (rssi / 10);
}
// Private function: from http://arduino.cc/playground/Code/AvailableMemory
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void setChannelModule(uint8_t channel)
{
uint8_t i;
uint16_t channelData;
//channelData = pgm_read_word(&channelTable[channel]);
//channelData = channelTable[channel];
channelData = pgm_read_word_near(channelTable + channel);
#ifdef DEBUG
Serial.print(F("TUNE: ")); Serial.print(channelData, HEX); Serial.print(F("\t"));
#endif
// bit bash out 25 bits of data
// Order: A0-3, !R/W, D0-D19
// A0=0, A1=0, A2=0, A3=1, RW=0, D0-19=0
SERIAL_ENABLE_HIGH();
delay(2);
SERIAL_ENABLE_LOW();
SERIAL_SENDBIT0();
SERIAL_SENDBIT0();
SERIAL_SENDBIT0();
SERIAL_SENDBIT1();
SERIAL_SENDBIT0();
// remaining zeros
for (i = 20; i > 0; i--)
SERIAL_SENDBIT0();
// Clock the data in
SERIAL_ENABLE_HIGH();
delay(2);
SERIAL_ENABLE_LOW();
// Second is the channel data from the lookup table
// 20 bytes of register data are sent, but the MSB 4 bits are zeros
// register address = 0x1, write, data0-15=channelData data15-19=0x0
SERIAL_ENABLE_HIGH();
SERIAL_ENABLE_LOW();
// Register 0x1
SERIAL_SENDBIT1();
SERIAL_SENDBIT0();
SERIAL_SENDBIT0();
SERIAL_SENDBIT0();
// Write to register
SERIAL_SENDBIT1();
// D0-D15
// note: loop runs backwards as more efficent on AVR
for (i = 16; i > 0; i--)
{
// Is bit high or low?
if (channelData & 0x1)
{
SERIAL_SENDBIT1();
}
else
{
SERIAL_SENDBIT0();
}
// Shift bits along to check the next one
channelData >>= 1;
}
// Remaining D16-D19
for (i = 4; i > 0; i--)
SERIAL_SENDBIT0();
// Finished clocking data in
SERIAL_ENABLE_HIGH();
delay(2);
digitalWrite(slaveSelectPin, LOW);
digitalWrite(spiClockPin, LOW);
digitalWrite(spiDataPin, LOW);
}
void SERIAL_SENDBIT1()
{
digitalWrite(spiClockPin, LOW);
delayMicroseconds(300);
digitalWrite(spiDataPin, HIGH);
delayMicroseconds(300);
digitalWrite(spiClockPin, HIGH);
delayMicroseconds(300);
digitalWrite(spiClockPin, LOW);
delayMicroseconds(300);
}
void SERIAL_SENDBIT0()
{
digitalWrite(spiClockPin, LOW);
delayMicroseconds(300);
digitalWrite(spiDataPin, LOW);
delayMicroseconds(300);
digitalWrite(spiClockPin, HIGH);
delayMicroseconds(300);
digitalWrite(spiClockPin, LOW);
delayMicroseconds(300);
}
void SERIAL_ENABLE_LOW()
{
delayMicroseconds(100);
digitalWrite(slaveSelectPin, LOW);
delayMicroseconds(100);
}
void SERIAL_ENABLE_HIGH()
{
delayMicroseconds(100);
digitalWrite(slaveSelectPin, HIGH);
delayMicroseconds(100);
}