瀏覽代碼

Merge branch 'developer' into eeprom-controller

# Conflicts:
#	main.c
#	ntp.c
Jordy Sipkema 9 年之前
父節點
當前提交
4e2ea342ac
共有 18 個文件被更改,包括 1328 次插入151 次删除
  1. 131 0
      alarm.c
  2. 28 0
      alarm.h
  3. 64 13
      display.c
  4. 4 3
      display.h
  5. 56 13
      displayHandler.c
  6. 2 0
      displayHandler.h
  7. 285 0
      httpstream.c
  8. 13 0
      httpstream.h
  9. 330 0
      jsmn.c
  10. 86 0
      jsmn.h
  11. 18 18
      keyboard.c
  12. 2 2
      keyboard.h
  13. 150 77
      main.c
  14. 142 3
      network.c
  15. 5 0
      network.h
  16. 10 20
      ntp.c
  17. 1 1
      rtc.c
  18. 1 1
      vs10xx.c

+ 131 - 0
alarm.c

@@ -0,0 +1,131 @@
+#define LOG_MODULE  LOG_MAIN_MODULE
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "log.h"
+#include "rtc.h"
+#include "alarm.h"
+
+#define n 3
+
+
+struct _snooze
+{
+	struct _tm snoozeStart;
+	struct _tm snoozeEnd;
+};
+
+struct _alarm alarm[n];
+struct _snooze snooze[n];
+
+
+int checkAlarms(){
+	int i = 0;
+	int check = 0;
+	for (i = 0; i < n; i++){
+		setState(i);
+		if (alarm[i].state == 1){
+			check = 1;
+		}
+	}
+	if (check == 1){
+		return 1;
+	}
+	
+	return 0;
+}
+
+struct _alarm getAlarm(int idx){
+	return alarm[idx];
+}
+
+int getState(int idx){
+	return alarm[idx].state;
+}
+
+void setState(int idx){
+	struct _tm ct;
+	X12RtcGetClock(&ct);
+	
+	if (compareTime(ct, alarm[idx].time) == 1 && alarm[idx].time.tm_year != 0){
+		alarm[idx].state = 1;
+	} else {
+		alarm[idx].state = 0;
+	}
+	
+	/*if (compareTime(alarm[idx].time,snooze[idx].snoozeStart)){
+		alarm[idx].state = 2;
+	}
+	
+	if (alarm[idx].state == 2){
+		if (compareTime(alarm[idx].time, snooze[idx].snoozeEnd)){
+			snooze[idx].snoozeStart.tm_min += alarm[idx].snooze + 1;
+			snooze[idx].snoozeEnd.tm_min += alarm[idx].snooze + 1;
+		}
+	}*/
+}
+
+/*void getAlarm(struct _alarm *am){
+	int i = 0;
+	for (i = 0; i < n; i++){
+		am[i] = alarm[i]; 
+	}
+}*/
+
+void setAlarm(struct _tm time, char* name, char* ip, u_short port, int snooze, int type, int idx){
+	alarm[idx].time = time;
+	
+	strncpy(alarm[idx].name, name, sizeof(alarm[idx].name));
+	strncpy(alarm[idx].ip, name, sizeof(alarm[idx].ip));
+	alarm[idx].port = port;
+	
+	alarm[idx].snooze = snooze;
+	alarm[idx].type = type;
+	alarm[idx].state = 0;
+
+	//snooze[idx].snoozeStart = time;
+	//snooze[idx].snoozeEnd = time;
+	//snooze[idx].snoozeStart += 1;
+	//snooze[idx].snoozeEnd += (snooze +1);
+}
+
+
+void deleteAlarm(int idx){
+	struct _tm tm;
+	alarm[idx].time = tm;
+	alarm[idx].port = 0;
+	alarm[idx].snooze = 5;
+	alarm[idx].type = -1;
+	alarm[idx].state = -1;
+}
+
+void handleAlarm(int idx){
+	alarm[idx].time.tm_mday = alarm[idx].time.tm_mday + 1;
+	alarm[idx].state = 0;
+}
+
+int compareTime(tm t1,tm t2){
+    if (t1.tm_year > t2.tm_year){
+        return 1;
+	}
+    if (t1.tm_year == t2.tm_year && t1.tm_mon > t2.tm_mon){
+        return 1;
+	}
+    if (t1.tm_year == t2.tm_year && t1.tm_mon == t2.tm_mon && t1.tm_mday > t2.tm_mday){
+        return 1;
+	}
+    if (t1.tm_year == t2.tm_year && t1.tm_mon == t2.tm_mon && t1.tm_mday == t2.tm_mday && t1.tm_hour > t2.tm_hour){
+        return 1;
+	}
+    if (t1.tm_year == t2.tm_year && t1.tm_mon == t2.tm_mon && t1.tm_mday == t2.tm_mday && t1.tm_hour == t2.tm_hour && t1.tm_min > t2.tm_min){
+        return 1;
+	}
+    if (t1.tm_year == t2.tm_year && t1.tm_mon == t2.tm_mon && t1.tm_mday == t2.tm_mday && t1.tm_hour == t2.tm_hour && t1.tm_min == t2.tm_min &&t1.tm_sec > t2.tm_sec){
+        return 1;
+	}
+
+    return 0;
+}
+

+ 28 - 0
alarm.h

@@ -0,0 +1,28 @@
+/* Alarm get/set status values */
+#define ALARM_1 	5
+#define ALARM_2		6
+
+#define AFLGS		0b11111111
+
+#ifndef _ALARM_DEFINED
+struct _alarm
+{
+	struct _tm time;
+	char ip[24];
+	u_short port;
+	char name[16];
+	int snooze;
+	int type;
+	int state;
+};
+#define _ALARM_DEFINED
+#endif
+
+void handleAlarm(int idx);
+int checkAlarms(void);
+void setAlarm(struct _tm time, char* name, char* ip, u_short port, int snooze, int type, int idx);
+void deleteAlarm(int idx);
+int compareTime(tm t1, tm t2);
+void setState(int idx);
+int getState(int idx);
+struct _alarm getAlarm(int idx);

+ 64 - 13
display.c

@@ -26,7 +26,7 @@
 #include "portio.h"
 #include "display.h"
 #include "log.h"
-
+#include <time.h>
 /*-------------------------------------------------------------------------*/
 /* local defines                                                           */
 /*-------------------------------------------------------------------------*/
@@ -42,6 +42,18 @@ static void LcdWriteByte(u_char, u_char);
 static void LcdWriteNibble(u_char, u_char);
 static void LcdWaitBusy(void);
 
+int timerLCD(u_char Mode){
+    time_t Start;
+    if(Mode == startLCD)
+    {
+            time_t diff = time(0) - Start;
+            return diff;
+    }
+    else if(Mode == stopLCD)
+    {
+        Start = time(0);
+    }
+}
 /*!
  * \addtogroup Display
  */
@@ -52,11 +64,11 @@ static void LcdWaitBusy(void);
 /*                         start of code                                   */
 /*-------------------------------------------------------------------------*/
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief control backlight
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 void LcdBackLight(u_char Mode)
 {
     if (Mode==LCD_BACKLIGHT_ON)
@@ -70,7 +82,31 @@ void LcdBackLight(u_char Mode)
     }
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+
+/* ����������������������������������������������������������������������� */
+
+/*
+ * Lcdbacklight knipperen
+ */
+
+void LcdBacklightKnipperen(u_char Mode)
+{
+    time_t Start;
+    time_t Stop;
+    if (Mode==startLCD)
+    {
+        sbi(LCD_BL_PORT, LCD_BL_BIT);   // Turn on backlight
+        timer(Start);
+    }
+    if (Mode==stopLCD)
+    {
+        cbi(LCD_BL_PORT, LCD_BL_BIT);   // Turn off backlight
+        timer(Stop);
+    }
+}
+/*
+
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Write a single character on the LCD
  *
@@ -78,14 +114,14 @@ void LcdBackLight(u_char Mode)
  *
  * \param LcdChar character to write
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 void LcdChar(char MyChar)
 {
     LcdWriteByte(WRITE_DATA, MyChar);
 }
 
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Low-level initialisation function of the LCD-controller
  *
@@ -94,7 +130,7 @@ void LcdChar(char MyChar)
  *           1 line dislay, 10 dots high characters
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
  void LcdLowLevelInit()
 {
     u_char i;
@@ -127,7 +163,7 @@ void LcdChar(char MyChar)
 }
 
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Low-level routine to write a byte to LCD-controller
  *
@@ -139,7 +175,7 @@ void LcdChar(char MyChar)
  * \param LcdByte byte to write
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static void LcdWriteByte(u_char CtrlState, u_char LcdByte)
 {
     LcdWaitBusy();                      // see if the controller is ready to receive next byte
@@ -148,7 +184,7 @@ static void LcdWriteByte(u_char CtrlState, u_char LcdByte)
 
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Low-level routine to write a nibble to LCD-controller
  *
@@ -160,7 +196,7 @@ static void LcdWriteByte(u_char CtrlState, u_char LcdByte)
  * \param LcdNibble nibble to write (upper 4 bits in this byte
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static void LcdWriteNibble(u_char CtrlState, u_char LcdNibble)
 {
     outp((inp(LCD_DATA_DDR) & 0x0F) | 0xF0, LCD_DATA_DDR);  // set data-port to output again
@@ -186,7 +222,7 @@ static void LcdWriteNibble(u_char CtrlState, u_char LcdNibble)
     outp((inp(LCD_DATA_PORT) & 0x0F) | 0xF0, LCD_DATA_PORT);  // enable pull-ups in data-port
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Low-level routine to see if the controller is ready to receive
  *
@@ -194,7 +230,7 @@ static void LcdWriteNibble(u_char CtrlState, u_char LcdNibble)
  * has become '0'. If a '0' is detected on bit 7 the function returns.
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static void LcdWaitBusy()
 {
     u_char Busy = 1;
@@ -242,6 +278,21 @@ void LcdArrayLineTwo(char *data, int size){
 	}
 }
 
+void setXCursorPos(int leftRight,int count)
+{
+    int i;
+    for ( i = 0; i <count ; ++i)
+    {
+        switch(leftRight)
+        {
+            case 0: LcdWriteByte(1,0x18);		// shift rechts
+                break;
+            case 1: LcdWriteByte(1,0x1c);		// shift links
+                break;
+        }
+    }
+}
+
 /* ---------- end of module ------------------------------------------------ */
 	
 /*@}*/

+ 4 - 3
display.h

@@ -30,7 +30,8 @@
 
 #define LCD_BACKLIGHT_ON            1
 #define LCD_BACKLIGHT_OFF           0
-
+#define startLCD        1
+#define stopLCD          0
 #define ALL_ZERO          			0x00      // 0000 0000 B
 #define WRITE_COMMAND     			0x02      // 0000 0010 B
 #define WRITE_DATA        			0x03      // 0000 0011 B
@@ -56,9 +57,9 @@ extern void LcdLowLevelInit(void);
 extern void ClearLcd(void);
 extern void LcdArrayLineOne(char*, int);
 extern void LcdArrayLineTwo(char*, int);
-
+extern void setXCursorPos(int,int);
 #endif /* _Display_H */
-/*  ÍÍÍÍ  End Of File  ÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/*  ����  End Of File  �������� �������������������������������������������� */
 
 
 

+ 56 - 13
displayHandler.c

@@ -1,6 +1,7 @@
 //
 // Created by Jordy Sipkema on 26/02/16.
 //
+#define LOG_MODULE  LOG_MAIN_MODULE
 
 #include <stdlib.h>
 #include <string.h>
@@ -9,7 +10,10 @@
 #include "display.h"
 #include "displayHandler.h"
 #include "ntp.h"
+#include "log.h"
 #include "rtc.h"
+#include "alarm.h"
+#include "network.h"
 
 #define MONTH_OFFSET 1
 #define YEAR_OFFSET 1900
@@ -20,35 +24,74 @@ void displayTime(int line_number){
     tm time;
     X12RtcGetClock(&time);
 
-    char str[12];
+    char str[16];
     if (NtpTimeIsValid()){
-        sprintf(str, "    %02d:%02d:%02d", time.tm_hour, time.tm_min, time.tm_sec);
+        sprintf(str, "    %02d:%02d:%02d    ", time.tm_hour, time.tm_min, time.tm_sec);
     }else {
-        sprintf(str, "    ??:??:??");
+        sprintf(str, "    ??:??:??    ");
     }
 
     if (line_number > -1 && line_number < 2){
-        (*write_display_ptr[line_number])(str, 12);
+        (*write_display_ptr[line_number])(str, 16);
     }
 }
 
-void displayDate(int line_number){
+void displayDate(int line_number) {
     tm *time;
     X12RtcGetClock(time);
 
-    char str[13];
-    if (NtpTimeIsValid()){
-        sprintf(str, "   %02d-%02d-%04d", time->tm_mday, time->tm_mon+MONTH_OFFSET, time->tm_year+YEAR_OFFSET);
-    }else {
-        sprintf(str, "   ??-??-????");
+    char str[16];
+
+    if (NtpTimeIsValid()) {
+        sprintf(str, "   %02d-%02d-%04d      ", time->tm_mday, time->tm_mon + MONTH_OFFSET, time->tm_year + YEAR_OFFSET);
+    } else {
+        sprintf(str, "   ??-??-????      ");
     }
 
-    if(NtpIsSyncing())
-        str[1] = 'S';
+    if (NtpIsSyncing()) {
+       str[1] = 'S';
+    }else if(NetworkIsReceiving()){
+        str[1] = 'N';
+    }
 
     if (line_number > -1 && line_number < 2){
-        (*write_display_ptr[line_number])(str, 13);
+        (*write_display_ptr[line_number])(str, 16);
+    }
+}
+
+void displayAlarm(int line_number, int line_numberTwo, int idx)
+{
+	int i;
+    char str[12];
+	struct _alarm am = getAlarm(idx);
+    sprintf(str, "    %02d:%02d:%02d    ", am.time.tm_hour, am.time.tm_min, am.time.tm_sec);
+    if (line_number > -1 && line_number < 2){
+        (*write_display_ptr[line_number])(str, 12);
+    }
+
+    char str2[16];
+	for(i = 0; i < 17; i++){
+		str2[i] = am.name[i];
+	}
+    if (line_numberTwo > -1 && line_numberTwo < 2){
+        (*write_display_ptr[line_numberTwo])(str2, 16);
+        LcdBackLight(LCD_BACKLIGHT_ON);
+    }
+}
+
+void displayVolume(int pos)
+{
+    ClearLcd();
+    int i;
+    LcdArrayLineOne("     Volume     ", 16);
+
+    char characters[17];
+
+    for(i = 0; i < 17; i++)
+    {
+        characters[i] = 0xFF;
     }
+        LcdArrayLineTwo(characters,pos);
 }
 
 

+ 2 - 0
displayHandler.h

@@ -7,5 +7,7 @@
 
 void displayTime(int);
 void displayDate(int);
+void displayAlarm(int line_number, int line_numberTwo, int idx);
+void displayVolume(int pos);
 
 #endif //MUTLI_OS_BUILD_DISPLAYHANDLER_H

+ 285 - 0
httpstream.c

@@ -0,0 +1,285 @@
+//
+// Created by janco on 10-3-16.
+//
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/thread.h>
+#include <sys/timer.h>
+#include <sys/version.h>
+#include <dev/irqreg.h>
+
+#include "vs10xx.h"
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+
+#include <sys/confnet.h>
+
+#include <arpa/inet.h>
+#include <net/route.h>
+
+#include <dev/board.h>
+#include <pro/httpd.h>
+#include <pro/dhcp.h>
+#include <pro/asp.h>
+#include <pro/discover.h>
+#include <dev/nicrtl.h>
+
+#include "ntp.h"
+#include "httpstream.h"
+
+#define MAX_HEADERLINE 512
+
+bool isStreaming;
+
+TCPSOCKET *sock;
+u_short mss = 1460;
+u_long rx_to = 3000;
+u_short tcpbufsiz = 8760;
+FILE *stream;
+u_long metaint;
+
+THREAD(Stream, args)
+{
+    if(stream) {
+        PlayMp3Stream(stream, metaint);
+    }
+    stopStream();
+    NutThreadExit();
+}
+
+void playStream(char *ipaddr, u_short port, char *radiourl){
+    if(isStreaming != true){
+        isStreaming = true;
+        ConnectStation(sock, inet_addr(ipaddr), port, radiourl, &metaint);
+        NutThreadCreate("Stream", Stream, NULL, 1024);
+    }
+}
+
+void stopStream(){
+    isStreaming = false;
+    fclose(stream);
+    NutTcpCloseSocket(sock);
+}
+
+bool HttpIsStreaming(){
+    return isStreaming;
+}
+
+void ConnectStation(TCPSOCKET *sock, u_long ip, u_short port, char *radiourl, u_long *metaint){
+    int rc;
+    u_char *line;
+    u_char *cp;
+
+    /*
+     * Connect the TCP server.
+     */
+    if ((sock = NutTcpCreateSocket()) == 0)
+        printf("Probleem bij het creereen van tcp socket");
+    if (NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss)))
+        printf("Probleem bij het creereen van tcp socket");
+    if (NutTcpSetSockOpt(sock, SO_RCVTIMEO, &rx_to, sizeof(rx_to)))
+        printf("Probleem bij het creereen van tcp socket");
+    if (NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz, sizeof(tcpbufsiz)))
+        printf("Probleem bij het creereen van tcp socket");
+
+    printf("Connecting %s:%u...", inet_ntoa(ip), port);
+    if ((rc = NutTcpConnect(sock, ip, port))) {
+        printf("Error: Connect failed with %d\n", ip);
+        return 0;
+    }
+    puts("OK");
+
+    if ((stream = _fdopen((int) sock, "r+b")) == 0) {
+        printf("Error: Can't create stream");
+        return 0;
+    }
+
+    /*
+     * Send the HTTP request.
+     */
+    printf("GET %s HTTP/1.0\n\n", radiourl);
+    fprintf(stream, "GET %s HTTP/1.0\r\n", radiourl);
+    fprintf(stream, "Host: %s\r\n", inet_ntoa(ip));
+    fprintf(stream, "User-Agent: Ethernut\r\n");
+    fprintf(stream, "Accept: */*\r\n");
+    fprintf(stream, "Icy-MetaData: 1\r\n");
+    fprintf(stream, "Connection: close\r\n");
+    fputs("\r\n", stream);
+    fflush(stream);
+
+    /*
+     * Receive the HTTP header.
+     */
+    line = malloc(MAX_HEADERLINE);
+    while(fgets(line, MAX_HEADERLINE, stream)) {
+
+        /*
+         * Chop off the carriage return at the end of the line. If none
+         * was found, then this line was probably too large for our buffer.
+         */
+        cp = strchr(line, '\r');
+        if(cp == 0) {
+            printf("Warning: Input buffer overflow");
+            continue;
+        }
+        *cp = 0;
+
+        /*
+         * The header is terminated by an empty line.
+         */
+        if(*line == 0) {
+            break;
+        }
+        if(strncmp(line, "icy-metaint:", 12) == 0) {
+            *metaint = atol(line + 12);
+        }
+        printf("%s\n", line);
+    }
+    putchar('\n');
+
+    free(line);
+}
+
+int ProcessMetaData(FILE *stream)
+{
+    u_char blks = 0;
+    u_short cnt;
+    int got;
+    int rc = 0;
+    u_char *mbuf;
+
+    /*
+     * Wait for the lenght byte.
+     */
+    got = fread(&blks, 1, 1, stream);
+    if(got != 1) {
+        return -1;
+    }
+    if (blks) {
+        if (blks > 32) {
+            printf("Error: Metadata too large, %u blocks\n", blks);
+            return -1;
+        }
+
+        cnt = blks * 16;
+        if ((mbuf = malloc(cnt + 1)) == 0) {
+            return -1;
+        }
+
+        /*
+         * Receive the metadata block.
+         */
+        for (;;) {
+            if ((got = fread(mbuf + rc, 1, cnt, stream)) <= 0) {
+                return -1;
+            }
+            if ((cnt -= got) == 0) {
+                break;
+            }
+            rc += got;
+            mbuf[rc] = 0;
+        }
+
+        printf("\nMeta='%s'\n", mbuf);
+        free(mbuf);
+    }
+    return 0;
+}
+
+
+void PlayMp3Stream(FILE *stream, u_long metaint)
+{
+    size_t rbytes;
+    u_char *mp3buf;
+    u_char ief;
+    int got = 0;
+    u_long last;
+    u_long mp3left = metaint;
+
+    /*
+     * Initialize the MP3 buffer. The NutSegBuf routines provide a global
+     * system buffer, which works with banked and non-banked systems.
+     */
+    if (NutSegBufInit(8192) == 0) {
+        puts("Error: MP3 buffer init failed");
+        return;
+    }
+
+    /*
+     * Initialize the MP3 decoder hardware.
+     */
+    if (VsPlayerReset(0)) {
+        puts("Error: MP3 hardware init failed");
+        return;
+    }
+
+    /*
+     * Reset the MP3 buffer.
+     */
+    ief = VsPlayerInterrupts(0);
+    NutSegBufReset();
+    VsPlayerInterrupts(ief);
+    last = NutGetSeconds();
+
+    while (isStreaming == true) {
+        /*
+         * Query number of byte available in MP3 buffer.
+         */
+        ief = VsPlayerInterrupts(0);
+        mp3buf = NutSegBufWriteRequest(&rbytes);
+        VsPlayerInterrupts(ief);
+
+        /*
+         * If the player is not running, kick it.
+         */
+        if (VsGetStatus() != VS_STATUS_RUNNING) {
+            puts("Not running");
+            if(rbytes < 1024 || NutGetSeconds() - last > 4UL) {
+                last = NutGetSeconds();
+                puts("Kick player");
+                VsPlayerKick();
+            }
+        }
+        /*
+         * Do not read pass metadata.
+         */
+        if (metaint && rbytes > mp3left) {
+            rbytes = mp3left;
+        }
+
+        /*
+         * Read data directly into the MP3 buffer.
+         */
+        while (rbytes && (isStreaming == true)) {
+            if ((got = fread(mp3buf, 1, rbytes, stream)) > 0) {
+                ief = VsPlayerInterrupts(0);
+                mp3buf = NutSegBufWriteCommit(got);
+                VsPlayerInterrupts(ief);
+
+                if (metaint) {
+                    mp3left -= got;
+                    if (mp3left == 0) {
+                        ProcessMetaData(stream);
+                        mp3left = metaint;
+                    }
+                }
+
+                if(got < rbytes && got < 512) {
+                    printf("%lu buffered\n", NutSegBufUsed());
+                    NutSleep(250);
+                }
+                else {
+                    NutThreadYield();
+                }
+            } else {
+                break;
+            }
+            rbytes -= got;
+        }
+
+        if(got <= 0) {
+            break;
+        }
+    }
+}

+ 13 - 0
httpstream.h

@@ -0,0 +1,13 @@
+//
+// Created by janco on 25-2-16.
+//
+
+#ifndef _Httpstream_H
+#define _Httpstream_H
+
+extern bool HttpIsStreaming();
+extern void playStream(char *ipaddr, u_short port, char *radiourl);
+extern void stopStream();
+
+
+#endif /* _Httpstream_H */

+ 330 - 0
jsmn.c

@@ -0,0 +1,330 @@
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+		jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *tok;
+	if (parser->toknext >= num_tokens) {
+		return NULL;
+	}
+	tok = &tokens[parser->toknext++];
+	tok->start = tok->end = -1;
+	tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+	tok->parent = -1;
+#endif
+	return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+                            int start, int end) {
+	token->type = type;
+	token->start = start;
+	token->end = end;
+	token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+		size_t len, jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *token;
+	int start;
+
+	start = parser->pos;
+
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+			/* In strict mode primitive must be followed by "," or "}" or "]" */
+			case ':':
+#endif
+			case '\t' : case '\r' : case '\n' : case ' ' :
+			case ','  : case ']'  : case '}' :
+				goto found;
+		}
+		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+			parser->pos = start;
+			return JSMN_ERROR_INVAL;
+		}
+	}
+#ifdef JSMN_STRICT
+	/* In strict mode primitive must be followed by a comma/object/array */
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+#endif
+
+found:
+	if (tokens == NULL) {
+		parser->pos--;
+		return 0;
+	}
+	token = jsmn_alloc_token(parser, tokens, num_tokens);
+	if (token == NULL) {
+		parser->pos = start;
+		return JSMN_ERROR_NOMEM;
+	}
+	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+	token->parent = parser->toksuper;
+#endif
+	parser->pos--;
+	return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+		size_t len, jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *token;
+
+	int start = parser->pos;
+
+	parser->pos++;
+
+	/* Skip starting quote */
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		char c = js[parser->pos];
+
+		/* Quote: end of string */
+		if (c == '\"') {
+			if (tokens == NULL) {
+				return 0;
+			}
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL) {
+				parser->pos = start;
+				return JSMN_ERROR_NOMEM;
+			}
+			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+			token->parent = parser->toksuper;
+#endif
+			return 0;
+		}
+
+		/* Backslash: Quoted symbol expected */
+		if (c == '\\' && parser->pos + 1 < len) {
+			int i;
+			parser->pos++;
+			switch (js[parser->pos]) {
+				/* Allowed escaped symbols */
+				case '\"': case '/' : case '\\' : case 'b' :
+				case 'f' : case 'r' : case 'n'  : case 't' :
+					break;
+				/* Allows escaped symbol \uXXXX */
+				case 'u':
+					parser->pos++;
+					for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+						/* If it isn't a hex character we have an error */
+						if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+									(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+									(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+							parser->pos = start;
+							return JSMN_ERROR_INVAL;
+						}
+						parser->pos++;
+					}
+					parser->pos--;
+					break;
+				/* Unexpected symbol */
+				default:
+					parser->pos = start;
+					return JSMN_ERROR_INVAL;
+			}
+		}
+	}
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		jsmntok_t *tokens, unsigned int num_tokens) {
+	int r;
+	int i;
+	jsmntok_t *token;
+	int count = parser->toknext;
+
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		char c;
+		jsmntype_t type;
+
+		c = js[parser->pos];
+		switch (c) {
+			case '{': case '[':
+				count++;
+				if (tokens == NULL) {
+					break;
+				}
+				token = jsmn_alloc_token(parser, tokens, num_tokens);
+				if (token == NULL)
+					return JSMN_ERROR_NOMEM;
+				if (parser->toksuper != -1) {
+					tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+					token->parent = parser->toksuper;
+#endif
+				}
+				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+				token->start = parser->pos;
+				parser->toksuper = parser->toknext - 1;
+				break;
+			case '}': case ']':
+				if (tokens == NULL)
+					break;
+				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+				if (parser->toknext < 1) {
+					return JSMN_ERROR_INVAL;
+				}
+				token = &tokens[parser->toknext - 1];
+				for (;;) {
+					if (token->start != -1 && token->end == -1) {
+						if (token->type != type) {
+							return JSMN_ERROR_INVAL;
+						}
+						token->end = parser->pos + 1;
+						parser->toksuper = token->parent;
+						break;
+					}
+					if (token->parent == -1) {
+						break;
+					}
+					token = &tokens[token->parent];
+				}
+#else
+				for (i = parser->toknext - 1; i >= 0; i--) {
+					token = &tokens[i];
+					if (token->start != -1 && token->end == -1) {
+						if (token->type != type) {
+							return JSMN_ERROR_INVAL;
+						}
+						parser->toksuper = -1;
+						token->end = parser->pos + 1;
+						break;
+					}
+				}
+				/* Error if unmatched closing bracket */
+				if (i == -1) return JSMN_ERROR_INVAL;
+				for (; i >= 0; i--) {
+					token = &tokens[i];
+					if (token->start != -1 && token->end == -1) {
+						parser->toksuper = i;
+						break;
+					}
+				}
+#endif
+				break;
+			case '\"':
+				r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+				if (r < 0) return r;
+				count++;
+				if (parser->toksuper != -1 && tokens != NULL)
+					tokens[parser->toksuper].size++;
+				break;
+			case '\t' : case '\r' : case '\n' : case ' ':
+				break;
+			case ':':
+				parser->toksuper = parser->toknext - 1;
+				break;
+			case ',':
+				if (tokens != NULL && parser->toksuper != -1 &&
+						tokens[parser->toksuper].type != JSMN_ARRAY &&
+						tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+					parser->toksuper = tokens[parser->toksuper].parent;
+#else
+					for (i = parser->toknext - 1; i >= 0; i--) {
+						if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+							if (tokens[i].start != -1 && tokens[i].end == -1) {
+								parser->toksuper = i;
+								break;
+							}
+						}
+					}
+#endif
+				}
+				break;
+#ifdef JSMN_STRICT
+			/* In strict mode primitives are: numbers and booleans */
+			case '-': case '0': case '1' : case '2': case '3' : case '4':
+			case '5': case '6': case '7' : case '8': case '9':
+			case 't': case 'f': case 'n' :
+				/* And they must not be keys of the object */
+				if (tokens != NULL && parser->toksuper != -1) {
+					jsmntok_t *t = &tokens[parser->toksuper];
+					if (t->type == JSMN_OBJECT ||
+							(t->type == JSMN_STRING && t->size != 0)) {
+						return JSMN_ERROR_INVAL;
+					}
+				}
+#else
+			/* In non-strict mode every unquoted value is a primitive */
+			default:
+#endif
+				r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+				if (r < 0) return r;
+				count++;
+				if (parser->toksuper != -1 && tokens != NULL)
+					tokens[parser->toksuper].size++;
+				break;
+
+#ifdef JSMN_STRICT
+			/* Unexpected char in strict mode */
+			default:
+				return JSMN_ERROR_INVAL;
+#endif
+		}
+	}
+
+	if (tokens != NULL) {
+		for (i = parser->toknext - 1; i >= 0; i--) {
+			/* Unmatched opened object or array */
+			if (tokens[i].start != -1 && tokens[i].end == -1) {
+				return JSMN_ERROR_PART;
+			}
+		}
+	}
+
+	return count;
+}
+
+/**
+ * Creates a new parser based over a given  buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+	parser->pos = 0;
+	parser->toknext = 0;
+	parser->toksuper = -1;
+}
+
+/**
+ * Compare a token string with a token, returns the token value
+ */
+int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
+	if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+		strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+		return 0;
+	}
+	return -1;
+}
+
+/**
+ * Get the value of the token in a integer format.
+ */
+int getIntegerToken(const char *json, jsmntok_t *tok){
+	char s[ ((tok->end - tok->start) + 1) ];
+	sprintf(s, "%.*s", tok->end - tok->start, json + tok->start);
+	return atoi(s);
+}

+ 86 - 0
jsmn.h

@@ -0,0 +1,86 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * 	o Object
+ * 	o Array
+ * 	o String
+ * 	o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+	JSMN_UNDEFINED = 0,
+	JSMN_OBJECT = 1,
+	JSMN_ARRAY = 2,
+	JSMN_STRING = 3,
+	JSMN_PRIMITIVE = 4
+} jsmntype_t;
+
+enum jsmnerr {
+	/* Not enough tokens were provided */
+	JSMN_ERROR_NOMEM = -1,
+	/* Invalid character inside JSON string */
+	JSMN_ERROR_INVAL = -2,
+	/* The string is not a full JSON packet, more bytes expected */
+	JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * @param		type	type (object, array, string etc.)
+ * @param		start	start position in JSON data string
+ * @param		end		end position in JSON data string
+ */
+typedef struct {
+	jsmntype_t type;
+	int start;
+	int end;
+	int size;
+#ifdef JSMN_PARENT_LINKS
+	int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+	unsigned int pos; /* offset in the JSON string */
+	unsigned int toknext; /* next token to allocate */
+	int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Compare a token string with a token, returns the token value
+ */
+int jsoneq(const char *json, jsmntok_t *tok, const char *s);
+
+/**
+ * Get the value of the token in a integer format.
+ */
+int getIntegerToken(const char *json, jsmntok_t *tok);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
+ * a single JSON object.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		jsmntok_t *tokens, unsigned int num_tokens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __JSMN_H_ */

+ 18 - 18
keyboard.c

@@ -75,7 +75,7 @@ static u_char KbRemapKey(u_short LongKey);
 
 
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Clear the eventbuffer of this module
  *
@@ -83,7 +83,7 @@ static u_char KbRemapKey(u_short LongKey);
  *
  * \param *pEvent pointer to the event queue
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static void KbClearEvent(HANDLE *pEvent)
 {
     NutEnterCritical();
@@ -93,7 +93,7 @@ static void KbClearEvent(HANDLE *pEvent)
     NutExitCritical();
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Low-level keyboard scan
  *
@@ -102,8 +102,8 @@ static void KbClearEvent(HANDLE *pEvent)
  *
  * After each keyboard-scan, check for a valid MMCard
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
-int KbScan()
+/* ����������������������������������������������������������������������� */
+void KbScan()
 {
     u_char KeyNibble0, KeyNibble1, KeyNibble2, KeyNibble3;
 
@@ -156,17 +156,17 @@ int KbScan()
     KeyFound |= (KeyNibble1 & 0x00F0);          // b7..b4 in 'KeyNibble1' to b7...b4  in 'KeyFound' -- do nothing
     KeyFound |= ((KeyNibble2<<4) & 0x0F00);     // b7..b4 in 'KeyNibble2' to b11..b8  in 'KeyFound' << shift 4 left
     KeyFound |= ((KeyNibble3<<8) & 0xF000);     // b7..b4 in 'KeyNibble3' to b15..b12 in 'KeyFound' << shift 8 left
-	return KeyFound;
+    KbInjectKey(KbRemapKey(KeyFound));
 #endif  // USE_JTAG
 
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Remap the 16-bit value for the active key to an 8-bit value
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static u_char KbRemapKey(u_short LongKey)
 {
     switch (LongKey)
@@ -192,25 +192,25 @@ static u_char KbRemapKey(u_short LongKey)
     }
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Return the repeating property for this key
  *
  * \return 'TRUE' in case the key was repeating, 'FALSE' if not
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 static u_char KbKeyIsRepeating(u_short Key)
 {
     return(KeyRepeatArray[KbRemapKey(Key)]==KEY_REPEAT);
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief set the property of this key to repeating or not-repeating
  *
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 void KbSetKeyRepeating(u_char Key, u_char Property)
 {
     // check arguments
@@ -220,7 +220,7 @@ void KbSetKeyRepeating(u_char Key, u_char Property)
     }
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Wait until an event was pushed on the eventqueue for this module
  *
@@ -232,7 +232,7 @@ void KbSetKeyRepeating(u_char Key, u_char Property)
  * \return KB_OK in case an event was found
  * \return KB_ERROR in case no event was found (return due to timeout)
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 int KbWaitForKeyEvent(u_long dwTimeout)
 {
 
@@ -248,7 +248,7 @@ int KbWaitForKeyEvent(u_long dwTimeout)
     return(nError);
 }
 
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Return the databyte that was receeived in the IR-stream
  *
@@ -260,7 +260,7 @@ int KbWaitForKeyEvent(u_long dwTimeout)
  *
  * \todo implement a key-buffer for this routine
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 u_char KbGetKey()
 {
     return(KeyBuffer[0]);
@@ -275,7 +275,7 @@ void KbInjectKey(u_char VirtualKey)
     KeyBuffer[0]=VirtualKey;
     NutEventPostFromIrq(&hKBEvent);   // 'valid key' detected -> generate Event
 }
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 /*!
  * \brief Initialise the Keyboard module
  *
@@ -288,7 +288,7 @@ void KbInjectKey(u_char VirtualKey)
  * when no key is pressed. Use negative logic to detect keys.
  * So default state of the colums is '1'
  */
-/* ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/* ����������������������������������������������������������������������� */
 void KbInit()
 {
     u_char i;

+ 2 - 2
keyboard.h

@@ -90,14 +90,14 @@
 /* export global routines (interface)                                      */
 /*-------------------------------------------------------------------------*/
 void    KbInit(void);
-int    KbScan(void);
+void  KbScan(void);
 int 	CheckKey();
 int     KbWaitForKeyEvent(u_long);
 u_char  KbGetKey(void);
 void    KbSetKeyRepeating(u_char, u_char);
 void    KbInjectKey(u_char VirtualKey);
 
-/*  ÍÍÍÍ  End Of File  ÍÍÍÍÍÍÍÍ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ */
+/*  ����  End Of File  �������� �������������������������������������������� */
 
 
 

+ 150 - 77
main.c

@@ -9,8 +9,8 @@
  */
 
 /*! \file
- *  COPYRIGHT (C) STREAMIT BV 2010
- *  \date 19 december 2003
+ *  COPYRIGHT (C) SaltyRadio 2016
+ *  \date 20-02-2016
  */
 
 #define LOG_MODULE  LOG_MAIN_MODULE
@@ -28,10 +28,12 @@
 #include <dev/irqreg.h>
 
 // Jordy: Please keep this in alphabetical order!
+#include "alarm.h"
 #include "display.h"
 #include "displayHandler.h"
 #include "eeprom.h"
 #include "flash.h"
+#include "httpstream.h"
 #include "keyboard.h"
 #include "led.h"
 #include "log.h"
@@ -47,17 +49,6 @@
 #include "watchdog.h"
 
 
-
-
-/*-------------------------------------------------------------------------*/
-/* global variable definitions                                             */
-/*-------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
-/* local variable definitions                                              */
-/*-------------------------------------------------------------------------*/
-
-
 /*-------------------------------------------------------------------------*/
 /* local routines (prototyping)                                            */
 /*-------------------------------------------------------------------------*/
@@ -80,7 +71,6 @@ static void SysControlMainBeat(u_char);
 /*-------------------------------------------------------------------------*/
 
 
-/* ����������������������������������������������������������������������� */
 /*!
  * \brief ISR MainBeat Timer Interrupt (Timer 2 for Mega128, Timer 0 for Mega256).
  *
@@ -91,7 +81,6 @@ static void SysControlMainBeat(u_char);
  *
  * \param *p not used (might be used to pass parms from the ISR)
  */
-/* ����������������������������������������������������������������������� */
 static void SysMainBeatInterrupt(void *p)
 {
 
@@ -102,8 +91,6 @@ static void SysMainBeatInterrupt(void *p)
     CardCheckCard();
 }
 
-
-/* ����������������������������������������������������������������������� */
 /*!
  * \brief Initialise Digital IO
  *  init inputs to '0', outputs to '1' (DDRxn='0' or '1')
@@ -111,7 +98,6 @@ static void SysMainBeatInterrupt(void *p)
  *  Pull-ups are enabled when the pin is set to input (DDRxn='0') and then a '1'
  *  is written to the pin (PORTxn='1')
  */
-/* ����������������������������������������������������������������������� */
 void SysInitIO(void)
 {
     /*
@@ -168,12 +154,10 @@ void SysInitIO(void)
     outp(0x18, DDRG);
 }
 
-/* ����������������������������������������������������������������������� */
 /*!
  * \brief Starts or stops the 4.44 msec mainbeat of the system
  * \param OnOff indicates if the mainbeat needs to start or to stop
  */
-/* ����������������������������������������������������������������������� */
 static void SysControlMainBeat(u_char OnOff)
 {
     int nError = 0;
@@ -193,58 +177,103 @@ static void SysControlMainBeat(u_char OnOff)
     }
 }
 
-int timer(time_t start){
-	time_t diff = time(0) - start;
-	return diff;
-}
 
-int checkOffPressed(){
-	if (KbScan() < -1){
-		LcdBackLight(LCD_BACKLIGHT_ON);
-		return 1;
-	} else {
-		return 0;
-	}
-}
+/*-------------------------------------------------------------------------*/
+/* global variable definitions                                             */
+/*-------------------------------------------------------------------------*/
+int isAlarmSyncing;
+int initialized;
 
-/* ����������������������������������������������������������������������� */
-/*!
- * \brief Main entry of the SIR firmware
- *
- * All the initialisations before entering the for(;;) loop are done BEFORE
- * the first key is ever pressed. So when entering the Setup (POWER + VOLMIN) some
- * initialisatons need to be done again when leaving the Setup because new values
- * might be current now
- *
- * \return \b never returns
- */
-/* ����������������������������������������������������������������������� */
 
+/*-------------------------------------------------------------------------*/
+/* local variable definitions                                              */
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/* Thread init                                                             */
+/*-------------------------------------------------------------------------*/
 THREAD(StartupInit, arg)
 {
     NetworkInit();
+
     NtpSync();
+
+    initialized = 1;
+    NutThreadExit();
+}
+
+THREAD(NTPSync, arg)
+{
+    for(;;)
+    {
+        if(initialized && (hasNetworkConnection() == true))
+        {
+            while(isAlarmSyncing)
+            {
+                NutSleep(2000);
+            }
+            NtpSync();
+        }
+        NutSleep(86400000);
+    }
+}
+
+THREAD(AlarmSync, arg)
+{
+    for(;;)
+    {
+        if(initialized && (hasNetworkConnection() == true))
+        {
+            isAlarmSyncing = 1;
+            char* content = httpGet("/getAlarmen.php?radioid=DE370");
+            parseAlarmJson(content);
+            free(content);
+            isAlarmSyncing = 0;
+        }
+        NutSleep(30000);
+    }
     NutThreadExit();
 }
 
+/*-------------------------------------------------------------------------*/
+/* Global functions                                                        */
+/*-------------------------------------------------------------------------*/
+
+int timer(time_t start){
+    time_t diff = time(0) - start;
+    return diff;
+}
+
+int checkOffPressed(){
+    if (KbGetKey() == KEY_POWER){
+        LcdBackLight(LCD_BACKLIGHT_ON);
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+
+
 int main(void)
 {
-	time_t start;
-	int running = 0;
+	initialized = 0;
+    int VOL2;
+    time_t start;
+	int idx = 0;
+
+	int running;
 
-    /*
-     *  First disable the watchdog
-     */
     WatchDogDisable();
 
     NutDelay(100);
-	
+
     SysInitIO();
-	
+
 	SPIinit();
-    
+
 	LedInit();
-	
+
 	LcdLowLevelInit();
 
     Uart0DriverInit();
@@ -255,31 +284,21 @@ int main(void)
 
     X12Init();
 
+    VsPlayerInit();
+
     LcdBackLight(LCD_BACKLIGHT_ON);
     NtpInit();
 
-    NutThreadCreate("BackgroundThread", StartupInit, NULL, 512);
-    
+    NutThreadCreate("BackgroundThread", StartupInit, NULL, 1024);
+    NutThreadCreate("BackgroundThread", AlarmSync, NULL, 1024);
+    NutThreadCreate("BackgroundThread", NTPSync, NULL, 1024);
     /** Quick fix for turning off the display after 10 seconds boot */
-    start = time(0);
-    running = 1;
-
-	/*
-	 * Kroeske: sources in rtc.c en rtc.h
-	 */
-
-    if (At45dbInit()==AT45DB041B)
-    {
-        // ......
-    }
-
-
 
     RcInit();
-    
+
 	KbInit();
 
-    SysControlMainBeat(ON);             // enable 4.4 msecs hartbeat interrupt
+    SysControlMainBeat(ON);             // enable 4.4 msecs heartbeat interrupt
 
     /*
      * Increase our priority so we can feed the watchdog.
@@ -288,15 +307,31 @@ int main(void)
 
 	/* Enable global interrupts */
 	sei();
-	
+
+   /* struct _tm tm;
+	tm = GetRTCTime();
+	tm.tm_sec += 10;
+    setAlarm(tm,"    test1234      ", "0.0.0.0", 8001,1,0,0);
+	tm.tm_sec +=20;
+	setAlarm(tm,"    test5678      ", "0.0.0.0", 8001,1,0,1);*/
+
+/*    if(hasNetworkConnection() == true){
+        playStream("145.58.53.152", 80, "/3fm-bb-mp3");
+    }*/
+    start = time(0) - 10;
+    unsigned char VOL = 64;
+
+    running = 1;
+
     for (;;)
-    {		
+    {
 		//Check if a button is pressed
 		if (checkOffPressed() == 1){
 			start = time(0);
 			running = 1;
+            LcdBacklightKnipperen(startLCD);
 		}
-		
+
 		//Check if background LED is on, and compare to timer
 		if (running == 1){
 			if (timer(start) >= 10){
@@ -305,11 +340,49 @@ int main(void)
 			}
 		}
 
-        displayDate(0);
-		displayTime(1);
-		
+        VOL = VOL2;
+        if(KbGetKey() == KEY_DOWN)
+        {
+            NutSleep(150);
+            start = time(0);
+            if(VOL > 8){
+                VOL -= 8;
+                VsSetVolume (128-VOL, 128-VOL);
+                displayVolume(VOL/8);
+            }
+        }
+        else if(KbGetKey() == KEY_UP)
+        {
+            NutSleep(150);
+            start = time(0);
+            if(VOL < 128) {
+                VOL += 8;
+                VsSetVolume(128-VOL, 128-VOL);
+                displayVolume(VOL/8);
+            }
+        }
+        else if(timer(start) >= 5 && checkAlarms() == 1)
+        {
+			for (idx = 0; idx < 3; idx++){
+				if (getState(idx) == 1){
+					displayAlarm(0,1,idx);
+					if (KbGetKey() == KEY_ESC){
+						NutDelay(50);
+						handleAlarm(idx);
+						NutDelay(50);
+						LcdBackLight(LCD_BACKLIGHT_OFF);
+					}
+				}
+			}
+		}
+		else if (timer(start) >= 5){
+            displayTime(0);
+            displayDate(1);
+		}
+
+        VOL2 = VOL;
         WatchDogRestart();
     }
 
-    return(0);      // never reached, but 'main()' returns a non-void, so.....
+    return(0);
 }

+ 142 - 3
network.c

@@ -2,8 +2,16 @@
 // Created by janco on 25-2-16.
 //
 #include <dev/board.h>
+#include <dev/debug.h>
 #include <sys/timer.h>
 #include <sys/confnet.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <net/route.h>
 
 #include <dev/nicrtl.h>
 
@@ -11,16 +19,147 @@
 #include <io.h>
 #include <arpa/inet.h>
 #include <pro/dhcp.h>
+#include <pro/sntp.h>
+
+#include "ntp.h"
 #include "network.h"
+#include "jsmn.h"
+#include "rtc.h"
+#include "alarm.h"
+
+bool isReceiving;
+bool hasNetwork;
 
 void NetworkInit() {
+    hasNetwork = false;
     /* Register de internet controller. */
     if (NutRegisterDevice(&DEV_ETHER, 0, 0)) {
-        printf("Registering  failed.");
+        printf("Registering  failed. \n");
     }/* Netwerk configureren op dhcp */
     else if (NutDhcpIfConfig(DEV_ETHER_NAME, NULL, 0)) {
-        /* Done. */
+        printf("DHCP failed. \n");
     }else {
-        printf("Ik heb een internet connectie. Ip is: %s", inet_ntoa(confnet.cdn_ip_addr));
+        printf("Ik heb een internet connectie. Ip is: %s \n\n", inet_ntoa(confnet.cdn_ip_addr));
     }
+    NutSleep(2000);
+    hasNetwork = true;
+}
+
+char* httpGet(char address[]){
+    isReceiving = true;
+    NutDelay(1000);
+    printf("\n\n #-- HTTP get -- #\n");
+
+    TCPSOCKET* sock = NutTcpCreateSocket();
+
+    char http[strlen(address) + 49]; //49 chars based on get command. Change this number if you change the domain name
+    sprintf(http, "GET %s HTTP/1.1\r\nHost: saltyradio.jancokock.me \r\n\r\n", address);
+    int len = sizeof(http);
+
+    char buffer[300];
+    memset(buffer, 0, 300);
+
+    if (NutTcpConnect(sock, inet_addr("62.195.226.247"), 80)) {
+        printf("Can't connect to server\n");
+    }else{
+        //FILE *stream;
+        //stream = _fdopen((int) sock, "r b");
+        if(NutTcpSend(sock, http, len) != len){
+            printf("Writing headers failed.\n");
+            NutDelay(1000);
+        }else{
+            printf("Headers %s writed. Now reading.", http);
+            NutDelay(1000);
+            NutTcpReceive(sock, buffer, sizeof(buffer));
+            //fread(buffer, 1, sizeof(buffer), stream);
+            NutDelay(1000);
+            printf(buffer);
+        };
+        //fclose(stream);
+    }
+    NutTcpCloseSocket(sock);
+    int i;
+    int enters = 0;
+    int t = 0;
+    char* content = (char*) calloc(1 , sizeof(buffer));
+    for(i = 0; i < strlen(buffer); i++)
+    {
+        if(enters == 4) {
+            content[t] = buffer[i];
+            t++;
+        }else {
+            if (buffer[i] == '\n' || buffer[i] == '\r') {
+                enters++;
+            }
+            else {
+                enters = 0;
+            }
+        }
+    }
+    content[t] = '\0';
+    printf("\nContent size: %d, Content: %s \n", t, content);
+    isReceiving = false;
+    return content;
+}
+
+int getTimeZone()
+{
+    char* content = httpGet("/gettimezone.php");
+    int timezone = atoi(content);
+    free(content);
+    printf("%d", timezone);
+    return timezone;
 }
+
+void parseAlarmJson(char* content){
+    int r;
+    int i;
+    jsmn_parser p;
+    jsmntok_t token[50]; /* We expect no more than 128 tokens */
+
+    jsmn_init(&p);
+    r = jsmn_parse(&p, content, strlen(content), token, sizeof(token)/sizeof(token[0]));
+    if (r < 0) {
+        printf("Failed to parse JSON: %d \n", r);
+    }else{
+        printf("Aantal tokens found: %d \n", r);
+    }
+
+    struct _tm time = GetRTCTime();
+
+    for (i = 1; i < r; i++) {
+        if (jsoneq(content, &token[i], "YYYY") == 0) {
+            time.tm_year= getIntegerToken(content, &token[i + 1]) - 1900;
+            i++;
+        }else if (jsoneq(content, &token[i], "MM") == 0) {
+            time.tm_mon=  getIntegerToken(content, &token[i + 1]) - 1;
+            i++;
+        }else if (jsoneq(content, &token[i], "DD") == 0) {
+            time.tm_mday =  getIntegerToken(content, &token[i + 1]);
+            i++;
+        }else if (jsoneq(content, &token[i], "hh") == 0) {
+            time.tm_hour = 	getIntegerToken(content, &token[i + 1]);
+            i++;
+        }else if (jsoneq(content, &token[i], "mm") == 0) {
+            time.tm_min = getIntegerToken(content, &token[i + 1]);
+            i++;
+        }else if (jsoneq(content, &token[i], "ss") == 0) {
+            time.tm_sec = getIntegerToken(content, &token[i + 1]);
+            i++;
+        }
+    }
+
+    printf("Alarm time is: %02d:%02d:%02d\n", time.tm_hour, time.tm_min, time.tm_sec);
+    printf("Alarm date is: %02d.%02d.%02d\n\n", time.tm_mday, (time.tm_mon + 1), (time.tm_year + 1900));
+
+    X12RtcSetAlarm(0,&time,0b11111111);
+    NutDelay(1000);
+}
+
+bool NetworkIsReceiving(void){
+    return isReceiving;
+}
+
+bool hasNetworkConnection(void){
+    return hasNetwork;
+}

+ 5 - 0
network.h

@@ -5,6 +5,11 @@
 #ifndef _Network_H
 #define _Network_H
 
+//bool hasNetworkConnection(void);
+//bool NetworkIsReceiving(void);
 extern void NetworkInit(void);
+char* httpGet(char address[]);
+void parseAlarmJson(char* content);
+int getTimeZone();
 
 #endif /* _Network_H */

+ 10 - 20
ntp.c

@@ -23,7 +23,7 @@
 #include "eeprom.h"
 #include "typedefs.h"
 
-#define TIME_ZONE 1
+int TIME_ZONE = 1;
 #define LOG_MODULE  LOG_NTP_MODULE
 
 bool isSyncing;
@@ -55,16 +55,15 @@ void NtpCheckValidTime(void){
     // Cache is present
     puts("NtpCheckValidTime(): Cache is available");
 
-    // Check if time is valid;
+    // Check time is valid;
     tm current_tm;
     X12RtcGetClock(&current_tm);
 
-    validTime = NtpCompareTime(current_tm, cache->last_sync);
-
+    validTime = NtpCompareTime(current_tm, stored_tm);
     if (validTime){
-        puts("NtpCheckValidTime(): Time was valid");
+        puts("NtpCheckValidTime(): Time was valid \n");
     }else {
-        puts("NtpCheckValidTime(): Invalid time!");
+        puts("NtpCheckValidTime(): Invalid time! \n");
     }
 
 //    Eeprom_tm eeprom_tm_struct;
@@ -97,7 +96,7 @@ void NtpCheckValidTime(void){
 //Tests if t1 is after t2.
 bool NtpCompareTime(tm t1, tm t2){
     char debug[120];
-    sprintf(&debug, "Comparing two times\nt1=%04d-%02d-%02d+%02d:%02d:%02d\nt2=%04d-%02d-%02d+%02d:%02d:%02d",
+    sprintf(&debug, "Comparing two times\nt1=%04d-%02d-%02d+%02d:%02d:%02d\nt2=%04d-%02d-%02d+%02d:%02d:%02d \n",
             t1.tm_year+1900,
             t1.tm_mon+1,
             t1.tm_mday,
@@ -138,6 +137,10 @@ bool NtpTimeIsValid(void){
 void NtpSync(void){
     /* Ophalen van pool.ntp.org */
     isSyncing = true;
+    _timezone = -getTimeZone() * 3600;
+    puts("NtpSync(): Timezone fetched. ");
+    printf(TIME_ZONE);
+    NutDelay(100);
     //puts("Tijd ophalen van pool.ntp.org (213.154.229.24)");
     timeserver = inet_addr("213.154.229.24");
 
@@ -168,18 +171,5 @@ void NtpWriteTimeToEeprom(tm time_struct){
 
     cache.last_sync = time_struct;
     EepromSetCache(&cache);
-
-//    Eeprom_tm eeprom_tm_struct;
-//
-//    eeprom_tm_struct.len = sizeof(eeprom_tm_struct);
-//    eeprom_tm_struct.tm_struct = time_struct;
-//
-//    int success = NutNvMemSave(256, &eeprom_tm_struct, sizeof(eeprom_tm_struct));
-//    if (success == 0){ puts("NtpWriteTimeToEeprom: Time succesfully written to eeprom"); }
-//
-//    NutDelay(100);
 }
 
-//unsigned long TmStructToEpoch(tm tm_struct){
-//
-//}

+ 1 - 1
rtc.c

@@ -352,7 +352,7 @@ int X12RtcGetStatus(u_long *sflgs)
  */
 int X12RtcClearStatus(u_long sflgs)
 {
-    rtc_status &= ~sflgs;
+    rtc_status &= sflgs;
 
     return(0);
 }

+ 1 - 1
vs10xx.c

@@ -505,7 +505,7 @@ int VsPlayerKick(void)
          *  for the VS1003 we need an extra reset
          *  here before we start playing a stream...
          */
-//        VsPlayerSetMode(VS_SM_RESET);
+        VsPlayerSetMode(VS_SM_RESET);
 //        NutDelay(10);
 //        LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));
 //        LogMsg_P(LOG_DEBUG,PSTR("Kick: CLOCKF = [0x%02X]"),VsRegRead(VS_CLOCKF_REG));