diff options
| author | Atsushi Saitoh <lynxeyed@xj9.so-net.ne.jp> | 2012-02-04 12:38:33 +0900 |
|---|---|---|
| committer | Atsushi Saitoh <lynxeyed@xj9.so-net.ne.jp> | 2012-02-04 12:38:33 +0900 |
| commit | 90506dd1ab7a48a4e2fbe6cf7224d27828abf869 (patch) | |
| tree | 23de598d6445aba54015c9b70f2d0fbded41c044 /src | |
| parent | eeda1597368fb49e254629e522295759d7f9c608 (diff) | |
new release
Diffstat (limited to 'src')
31 files changed, 9044 insertions, 0 deletions
diff --git a/src/FatFs/SD.cpp b/src/FatFs/SD.cpp new file mode 100755 index 0000000..f614794 --- /dev/null +++ b/src/FatFs/SD.cpp @@ -0,0 +1,120 @@ +/*
+ * SD.cpp
+ *
+ * Created on: 2011/08/19
+ * Author: atsu
+ */
+#include <libmary.h>
+#include "SD.h"
+//#include "pff.h"
+
+PETITFS SDFile;
+
+PETITFS::PETITFS()
+{
+ this->SDCS = C33;
+}
+
+PETITFS::~PETITFS()
+{
+}
+BOOL PETITFS::begin(int cs_pin)
+{
+ BOOL rt;
+ this->SDCS = cs_pin;
+ rt = begin();
+ return (rt);
+}
+
+BOOL PETITFS::begin(SSP_PORT port)
+{
+ BOOL rt;
+ SPI.begin(port);
+ if(port == LPCXSSP0)
+ rt = begin(P1_4); //for MAPLE
+ else
+ rt = begin();
+ return (rt);
+}
+
+BOOL PETITFS::begin()
+{
+ rc = pf_mount(&fatfs);
+ return (!rc)? TRUE:FALSE;
+}
+
+BOOL PETITFS::exists()
+{
+ return FALSE;
+}
+
+BOOL PETITFS::mkdir()
+{
+ return FALSE;
+}
+
+FRESULT PETITFS::open(const char* filename) //???
+{
+ rc = pf_open(filename);
+ return rc;
+}
+
+
+BOOL PETITFS::remove(const char* filename)
+{
+ return FALSE;
+}
+
+BOOL PETITFS::rmdir(const char* filename)
+{
+ return FALSE;
+}
+
+int PETITFS::available(){}
+void PETITFS::close(){}
+void PETITFS::flush(){}
+int PETITFS::peek(){}
+unsigned long PETITFS::position(){}
+void PETITFS::print(const char *s){}
+void PETITFS::print(int val, RADIX_FORMAT format){}
+void PETITFS::println(const char *s){}
+void PETITFS::println(int val, RADIX_FORMAT format){}
+BOOL PETITFS::seek(unsigned long pos){}
+unsigned long PETITFS::size(){}
+
+int PETITFS::read()
+{
+ rc = pf_read(buff, sizeof(char), &br); /* Read a chunk of file */
+ if (rc || !br)
+ return -1; /* Error or end of file */
+ else
+ return (int)buff[0];
+}
+void PETITFS::write(const char *s){}
+void PETITFS::write(const char *s,int length){}
+
+/*
+class FILE {
+private:
+ char buff[64];
+ FRESULT rc;
+
+public:
+ FILE();
+ ~FILE();
+ int available();
+ void close();
+ void flush();
+ int peek();
+ unsigned long position();
+ void print(const char *s);
+ void print(int val, RADIX_FORMAT format);
+ void println(const char *s);
+ void println(int val, RADIX_FORMAT format) ;
+ BOOL seek(unsigned long pos);
+ unsigned long size();
+ int read();
+ void write(const char *s);
+ void write(const char *s,int length);
+};
+*/
diff --git a/src/FatFs/SD.h b/src/FatFs/SD.h new file mode 100755 index 0000000..80a9cda --- /dev/null +++ b/src/FatFs/SD.h @@ -0,0 +1,74 @@ +/*
+ * SD.h
+ *
+ * Created on: 2011/08/19
+ * Author: atsu
+ */
+
+#ifndef SD_H_
+#define SD_H_
+
+
+#include <libmary.h>
+#include <SPI.h>
+#include "pff.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+class PETITFS{
+private:
+
+ FATFS fatfs; // File system object
+ DIR dir; // Directory object
+ FILINFO fno; // File information object
+ WORD bw, br, i;
+ char buff[64];
+ FRESULT rc;
+
+public:
+ int SDCS; //CS pin
+ PETITFS();
+ ~PETITFS();
+
+ BOOL begin(SSP_PORT port);
+ BOOL begin(int cs_pin);
+ BOOL begin();
+ BOOL exists();
+ BOOL mkdir();
+ FRESULT open(const char* filename); //???
+ BOOL remove(const char* filename);
+ BOOL rmdir(const char* filename);
+
+ int available();
+ void close();
+ void flush();
+ int peek();
+ unsigned long position();
+ void print(const char *s);
+ void print(int val, RADIX_FORMAT format);
+ void println(const char *s);
+ void println(int val, RADIX_FORMAT format) ;
+ BOOL seek(unsigned long pos);
+ unsigned long size();
+ int read();
+ void write(const char *s);
+ void write(const char *s,int length);
+};
+
+
+
+
+
+
+extern PETITFS SDFile;
+
+
+
+#ifdef __cplusplus
+ } //extern "C"
+#endif
+
+#endif /* SD_H_ */
diff --git a/src/FatFs/diskio.h b/src/FatFs/diskio.h new file mode 100755 index 0000000..253cff6 --- /dev/null +++ b/src/FatFs/diskio.h @@ -0,0 +1,41 @@ +/*-----------------------------------------------------------------------
+/ PFF - Low level disk interface modlue include file (C)ChaN, 2009
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO
+
+#include "integer.h"
+#include <stdint.h>
+
+/* Status of Disk Functions */
+typedef uint8_t DSTATUS;
+
+
+/* Results of Disk Functions */
+typedef enum {
+ RES_OK = 0, /* 0: Function succeeded */
+ RES_ERROR, /* 1: Disk error */
+ RES_NOTRDY, /* 2: Not ready */
+ RES_PARERR /* 3: Invalid parameter */
+} DRESULT;
+
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+DSTATUS disk_initialize (void);
+DRESULT disk_readp (uint8_t*, DWORD, WORD, WORD);
+DRESULT disk_writep (const uint8_t*, DWORD);
+
+#define STA_NOINIT 0x01 /* Drive not initialized */
+#define STA_NODISK 0x02 /* No medium in the drive */
+
+/* Card type flags (CardType) */
+#define CT_MMC 0x01 /* MMC ver 3 */
+#define CT_SD1 0x02 /* SD ver 1 */
+#define CT_SD2 0x04 /* SD ver 2 */
+#define CT_SDC (CT_SD1|CT_SD2) /* SD */
+#define CT_BLOCK 0x08 /* Block addressing */
+
+#define _DISKIO
+#endif
diff --git a/src/FatFs/integer.h b/src/FatFs/integer.h new file mode 100755 index 0000000..4dcd2dd --- /dev/null +++ b/src/FatFs/integer.h @@ -0,0 +1,37 @@ +/*-------------------------------------------*/
+/* Integer type definitions for FatFs module */
+/*-------------------------------------------*/
+
+#ifndef _INTEGER
+
+#if 0
+#include <windows.h>
+#else
+
+/* These types must be 16-bit, 32-bit or larger integer */
+typedef int INT;
+typedef unsigned int UINT;
+
+/* These types must be 8-bit integer */
+typedef signed char CHAR;
+typedef unsigned char UCHAR;
+//typedef unsigned char uint8_t;
+
+/* These types must be 16-bit integer */
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef unsigned short WORD;
+typedef unsigned short WCHAR;
+
+/* These types must be 32-bit integer */
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef unsigned long DWORD;
+
+/* Boolean type */
+typedef enum { FALSE = 0, TRUE } BOOL;
+
+#endif
+
+#define _INTEGER
+#endif
diff --git a/src/FatFs/pff.cpp b/src/FatFs/pff.cpp new file mode 100755 index 0000000..8b2de72 --- /dev/null +++ b/src/FatFs/pff.cpp @@ -0,0 +1,845 @@ +/*----------------------------------------------------------------------------/
+/ Petit FatFs - FAT file system module R0.02 (C)ChaN, 2009
+/-----------------------------------------------------------------------------/
+/ Petit FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/ Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/-----------------------------------------------------------------------------/
+/ Jun 15,'09 R0.01a First release. (Branched from FatFs R0.07b.)
+/
+/ Dec 14,'09 R0.02 Added multiple code page support.
+/ Added write funciton.
+/ Changed stream read mode interface.
+/----------------------------------------------------------------------------*/
+
+#include "pff.h" /* Petit FatFs configurations and declarations */
+#include "diskio.h" /* Declarations of low level disk I/O functions */
+#include <stdio.h>
+
+
+/*--------------------------------------------------------------------------
+
+ Private Functions
+
+---------------------------------------------------------------------------*/
+
+static
+FATFS *FatFs; /* Pointer to the file system object (logical drive) */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* String functions */
+/*-----------------------------------------------------------------------*/
+
+/* Fill memory */
+static
+void mem_set (void* dst, int val, int cnt) {
+ char *d = (char*)dst;
+ while (cnt--) *d++ = (char)val;
+}
+
+/* Compare memory to memory */
+static
+int mem_cmp (const void* dst, const void* src, int cnt) {
+ const char *d = (const char *)dst, *s = (const char *)src;
+ int r = 0;
+ while (cnt-- && (r = *d++ - *s++) == 0) ;
+ return r;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT access - Read value of a FAT entry */
+/*-----------------------------------------------------------------------*/
+
+static
+CLUST get_fat ( /* 1:IO error, Else:Cluster status */
+ CLUST clst /* Cluster# to get the link information */
+)
+{
+ WORD wc, bc, ofs;
+ uint8_t buf[4];
+ FATFS *fs = FatFs;
+
+
+ if (clst < 2 || clst >= fs->max_clust) /* Range check */
+ return 1;
+
+ switch (fs->fs_type) {
+ case FS_FAT12 :
+ bc = (WORD)clst; bc += bc / 2;
+ ofs = bc % 512; bc /= 512;
+ if (ofs != 511) {
+ if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;
+ } else {
+ if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;
+ if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;
+ }
+ wc = LD_WORD(buf);
+ return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
+
+ case FS_FAT16 :
+ if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;
+ return LD_WORD(buf);
+#if _FS_FAT32
+ case FS_FAT32 :
+ if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;
+ return LD_DWORD(buf) & 0x0FFFFFFF;
+#endif
+ }
+
+ return 1; /* An error occured at the disk I/O layer */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get sector# from cluster# */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
+ CLUST clst /* Cluster# to be converted */
+)
+{
+ FATFS *fs = FatFs;
+
+
+ clst -= 2;
+ if (clst >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */
+ return (DWORD)clst * fs->csize + fs->database;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Rewind directory index */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_rewind (
+ DIR *dj /* Pointer to directory object */
+)
+{
+ CLUST clst;
+ FATFS *fs = FatFs;
+
+
+ dj->index = 0;
+ clst = dj->sclust;
+ if (clst == 1 || clst >= fs->max_clust) /* Check start cluster range */
+ return FR_DISK_ERR;
+#if _FS_FAT32
+ if (!clst && fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
+ clst = fs->dirbase;
+#endif
+ dj->clust = clst; /* Current cluster */
+ dj->sect = clst ? clust2sect(clst) : fs->dirbase; /* Current sector */
+
+ return FR_OK; /* Seek succeeded */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Move directory index next */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table */
+ DIR *dj /* Pointer to directory object */
+)
+{
+ CLUST clst;
+ WORD i;
+ FATFS *fs = FatFs;
+
+
+ i = dj->index + 1;
+ if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
+ return FR_NO_FILE;
+
+ if (!(i & (16-1))) { /* Sector changed? */
+ dj->sect++; /* Next sector */
+
+ if (dj->clust == 0) { /* Static table */
+ if (i >= fs->n_rootdir) /* Report EOT when end of table */
+ return FR_NO_FILE;
+ }
+ else { /* Dynamic table */
+ if (((i / 16) & (fs->csize-1)) == 0) { /* Cluster changed? */
+ clst = get_fat(dj->clust); /* Get next cluster */
+ if (clst <= 1) return FR_DISK_ERR;
+ if (clst >= fs->max_clust) /* When it reached end of dynamic table */
+ return FR_NO_FILE; /* Report EOT */
+ dj->clust = clst; /* Initialize data for new cluster */
+ dj->sect = clust2sect(clst);
+ }
+ }
+ }
+
+ dj->index = i;
+
+ return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Find an object in the directory */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_find (
+ DIR *dj /* Pointer to the directory object linked to the file name */
+)
+{
+ FRESULT res;
+ uint8_t c, *dir;
+
+
+ res = dir_rewind(dj); /* Rewind directory object */
+ if (res != FR_OK) return res;
+
+ dir = FatFs->buf;
+ do {
+ res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */
+ ? FR_DISK_ERR : FR_OK;
+ if (res != FR_OK) break;
+ c = dir[DIR_Name]; /* First character */
+ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
+ if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
+ break;
+ res = dir_next(dj); /* Next entry */
+ } while (res == FR_OK);
+
+ return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read an object from the directory */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+static
+FRESULT dir_read (
+ DIR *dj /* Pointer to the directory object to store read object name */
+)
+{
+ FRESULT res;
+ uint8_t a, c, *dir;
+
+
+ res = FR_NO_FILE;
+ dir = FatFs->buf;
+ while (dj->sect) {
+ res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */
+ ? FR_DISK_ERR : FR_OK;
+ if (res != FR_OK) break;
+ c = dir[DIR_Name];
+ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
+ a = dir[DIR_Attr] & AM_MASK;
+ if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */
+ break;
+ res = dir_next(dj); /* Next entry */
+ if (res != FR_OK) break;
+ }
+
+ if (res != FR_OK) dj->sect = 0;
+
+ return res;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Pick a segment and create the object name in directory form */
+/*-----------------------------------------------------------------------*/
+
+#ifdef _EXCVT
+ static const uint8_t cvt[] = _EXCVT;
+#endif
+
+static
+FRESULT create_name (
+ DIR *dj, /* Pointer to the directory object */
+ const char **path /* Pointer to pointer to the segment in the path string */
+)
+{
+ uint8_t c, d, ni, si, i, *sfn;
+ const char *p;
+
+ /* Create file name in directory form */
+ sfn = dj->fn;
+ mem_set(sfn, ' ', 11);
+ si = i = 0; ni = 8;
+ p = *path;
+ for (;;) {
+ c = p[si++];
+ if (c <= ' ' || c == '/') break; /* Break on end of segment */
+ if (c == '.' || i >= ni) {
+ if (ni != 8 || c != '.') break;
+ i = 8; ni = 11;
+ continue;
+ }
+#ifdef _EXCVT
+ if (c >= 0x80) /* To upper extended char (SBCS) */
+ c = cvt[c - 0x80];
+#endif
+ //if (IsDBCS1(c) && i >= ni - 1) { /* DBC 1st uint8_t? */
+ if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st uint8_t? */
+ d = p[si++]; /* Get 2nd uint8_t */
+ sfn[i++] = c;
+ sfn[i++] = d;
+ } else { /* Single uint8_t code */
+ if (IsLower(c)) c -= 0x20; /* toupper */
+ sfn[i++] = c;
+ }
+ }
+ *path = &p[si]; /* Rerurn pointer to the next segment */
+
+ sfn[11] = (c <= ' ') ? 1 : 0; /* Set last segment flag if end of path */
+
+ return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get file information from directory entry */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+static
+void get_fileinfo ( /* No return code */
+ DIR *dj, /* Pointer to the directory object */
+ FILINFO *fno /* Pointer to store the file information */
+)
+{
+ uint8_t i, c, *dir;
+ char *p;
+
+
+ p = fno->fname;
+ if (dj->sect) {
+ dir = FatFs->buf;
+ for (i = 0; i < 8; i++) { /* Copy file name body */
+ c = dir[i];
+ if (c == ' ') break;
+ if (c == 0x05) c = 0xE5;
+ *p++ = c;
+ }
+ if (dir[8] != ' ') { /* Copy file name extension */
+ *p++ = '.';
+ for (i = 8; i < 11; i++) {
+ c = dir[i];
+ if (c == ' ') break;
+ *p++ = c;
+ }
+ }
+ fno->fattrib = dir[DIR_Attr]; /* Attribute */
+ fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */
+ fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */
+ fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */
+ }
+ *p = 0;
+}
+#endif /* _USE_DIR */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Follow a file path */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
+ DIR *dj, /* Directory object to return last directory and found object */
+ const char *path /* Full-path string to find a file or directory */
+)
+{
+ FRESULT res;
+ uint8_t *dir;
+
+
+ while (*path == ' ') path++; /* Skip leading spaces */
+ if (*path == '/') path++; /* Strip heading separator */
+ dj->sclust = 0; /* Set start directory (always root dir) */
+
+ if ((uint8_t)*path <= ' ') { /* Null path means the root directory */
+ res = dir_rewind(dj);
+ FatFs->buf[0] = 0;
+
+ } else { /* Follow path */
+ for (;;) {
+ res = create_name(dj, &path); /* Get a segment */
+ if (res != FR_OK) break;
+ res = dir_find(dj); /* Find it */
+ if (res != FR_OK) { /* Could not find the object */
+ if (res == FR_NO_FILE && !*(dj->fn+11))
+ res = FR_NO_PATH;
+ break;
+ }
+ if (*(dj->fn+11)) break; /* Last segment match. Function completed. */
+ dir = FatFs->buf; /* There is next segment. Follow the sub directory */
+ if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
+ res = FR_NO_PATH; break;
+ }
+ dj->sclust =
+#if _FS_FAT32
+ ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+ LD_WORD(dir+DIR_FstClusLO);
+ }
+ }
+
+ return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check a sector if it is an FAT boot record */
+/*-----------------------------------------------------------------------*/
+
+static
+uint8_t check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
+ uint8_t *buf, /* Working buffer */
+ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
+)
+{
+ if (disk_readp(buf, sect, 510, 2)) /* Read the boot sector */
+ return 3;
+ if (LD_WORD(buf) != 0xAA55) /* Check record signature */
+ return 2;
+
+ if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */
+ return 0;
+#if _FS_FAT32
+ if (!disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146) /* Check FAT32 */
+ return 0;
+#endif
+ return 1;
+}
+
+
+
+
+/*--------------------------------------------------------------------------
+
+ Public Functions
+
+--------------------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Mount/Unmount a Locical Drive */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_mount (
+ FATFS *fs /* Pointer to new file system object (NULL: Unmount) */
+)
+{
+ uint8_t fmt, buf[36];
+ DWORD bsect, fsize, tsect, mclst;
+
+
+ FatFs = 0;
+ if (!fs) return FR_OK; /* Unregister fs object */
+
+ if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */
+ return FR_NOT_READY;
+
+ /* Search FAT partition on the drive */
+ bsect = 0;
+ fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */
+ if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */
+ /* Check a partition listed in top of the partition table */
+ if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */
+ fmt = 3;
+ } else {
+ if (buf[4]) { /* Is the partition existing? */
+ bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */
+ fmt = check_fs(buf, bsect); /* Check the partition */
+ }
+ }
+ }
+ if (fmt == 3) return FR_DISK_ERR;
+ if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */
+
+ /* Initialize the file system object */
+ if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;
+
+ fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */
+ if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);
+
+ fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */
+ fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */
+ fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */
+ fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */
+ tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */
+ if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);
+ mclst = (tsect /* Last cluster# + 1 */
+ - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16
+ ) / fs->csize + 2;
+ fs->max_clust = (CLUST)mclst;
+
+ fmt = FS_FAT12; /* Determine the FAT sub type */
+ if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */
+ if (mclst >= 0xFFF7) /* Number of clusters >= 0xFFF5 */
+#if _FS_FAT32
+ fmt = FS_FAT32;
+#else
+ return FR_NO_FILESYSTEM;
+#endif
+
+ fs->fs_type = fmt; /* FAT sub-type */
+#if _FS_FAT32
+ if (fmt == FS_FAT32)
+ fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */
+ else
+#endif
+ fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */
+ fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */
+
+ fs->flag = 0;
+ FatFs = fs;
+
+ return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Open or Create a File */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_open (
+ const char *path /* Pointer to the file name */
+)
+{
+ FRESULT res;
+ DIR dj;
+ uint8_t sp[12], dir[32];
+ FATFS *fs = FatFs;
+
+
+ if (!fs) /* Check file system */
+ return FR_NOT_ENABLED;
+
+ fs->flag = 0;
+ fs->buf = dir;
+ dj.fn = sp;
+ res = follow_path(&dj, path); /* Follow the file path */
+ if (res != FR_OK) return res; /* Follow failed */
+ if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */
+ return FR_NO_FILE;
+
+ fs->org_clust = /* File start cluster */
+#if _FS_FAT32
+ ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+ LD_WORD(dir+DIR_FstClusLO);
+ fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
+ fs->fptr = 0; /* File pointer */
+ fs->flag = FA_OPENED;
+
+ return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read File */
+/*-----------------------------------------------------------------------*/
+#if _USE_READ
+
+FRESULT pf_read (
+ void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/
+ WORD btr, /* Number of uint8_ts to read */
+ WORD* br /* Pointer to number of uint8_ts read */
+)
+{
+ DRESULT dr;
+ CLUST clst;
+ DWORD sect, remain;
+ uint8_t *rbuff = (uint8_t *)buff;
+ WORD rcnt;
+ FATFS *fs = FatFs;
+
+
+ *br = 0;
+ if (!fs) return FR_NOT_ENABLED; /* Check file system */
+ if (!(fs->flag & FA_OPENED)) /* Check if opened */
+ return FR_NOT_OPENED;
+
+ remain = fs->fsize - fs->fptr;
+ if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining uint8_ts */
+
+ while (btr) { /* Repeat until all data transferred */
+ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */
+ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */
+ clst = (fs->fptr == 0) ? /* On the top of the file? */
+ fs->org_clust : get_fat(fs->curr_clust);
+ if (clst <= 1) goto fr_abort;
+ fs->curr_clust = clst; /* Update current cluster */
+ fs->csect = 0; /* Reset sector offset in the cluster */
+ }
+ sect = clust2sect(fs->curr_clust); /* Get current sector */
+ if (!sect) goto fr_abort;
+ fs->dsect = sect + fs->csect++;
+ }
+ rcnt = 512 - ((WORD)fs->fptr % 512); /* Get partial sector data from sector buffer */
+ if (rcnt > btr) rcnt = btr;
+ dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);
+ if (dr) goto fr_abort;
+ fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */
+ btr -= rcnt; *br += rcnt;
+ }
+
+ return FR_OK;
+
+fr_abort:
+ fs->flag = 0;
+ return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write File */
+/*-----------------------------------------------------------------------*/
+#if _USE_WRITE
+
+FRESULT pf_write (
+ const void* buff, /* Pointer to the data to be written */
+ WORD btw, /* Number of uint8_ts to write (0:Finalize the current write operation) */
+ WORD* bw /* Pointer to number of uint8_ts written */
+)
+{
+ CLUST clst;
+ DWORD sect, remain;
+ const uint8_t *p = (uint8_t *)buff;
+ WORD wcnt;
+ FATFS *fs = FatFs;
+
+
+ *bw = 0;
+ if (!fs) return FR_NOT_ENABLED; /* Check file system */
+ if (!(fs->flag & FA_OPENED)) /* Check if opened */
+ return FR_NOT_OPENED;
+
+ if (!btw) { /* Finalize request */
+ if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;
+ fs->flag &= ~FA__WIP;
+ return FR_OK;
+ } else { /* Write data request */
+ if (!(fs->flag & FA__WIP)) /* Round down fptr to the sector boundary */
+ fs->fptr &= 0xFFFFFE00;
+ }
+ remain = fs->fsize - fs->fptr;
+ if (btw > remain) btw = (WORD)remain; /* Truncate btw by remaining uint8_ts */
+
+ while (btw) { /* Repeat until all data transferred */
+ if (((WORD)fs->fptr % 512) == 0) { /* On the sector boundary? */
+ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */
+ clst = (fs->fptr == 0) ? /* On the top of the file? */
+ fs->org_clust : get_fat(fs->curr_clust);
+ if (clst <= 1) goto fw_abort;
+ fs->curr_clust = clst; /* Update current cluster */
+ fs->csect = 0; /* Reset sector offset in the cluster */
+ }
+ sect = clust2sect(fs->curr_clust); /* Get current sector */
+ if (!sect) goto fw_abort;
+ fs->dsect = sect + fs->csect++;
+ if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */
+ fs->flag |= FA__WIP;
+ }
+ wcnt = 512 - ((WORD)fs->fptr % 512); /* Number of uint8_ts to write to the sector */
+ if (wcnt > btw) wcnt = btw;
+ if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */
+ fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */
+ btw -= wcnt; *bw += wcnt;
+ if (((WORD)fs->fptr % 512) == 0) {
+ if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */
+ fs->flag &= ~FA__WIP;
+ }
+ }
+
+ return FR_OK;
+
+fw_abort:
+ fs->flag = 0;
+ return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Seek File R/W Pointer */
+/*-----------------------------------------------------------------------*/
+#if _USE_LSEEK
+
+FRESULT pf_lseek (
+ DWORD ofs /* File pointer from top of file */
+)
+{
+ CLUST clst;
+ DWORD bcs, sect, ifptr;
+ FATFS *fs = FatFs;
+
+
+ if (!fs) return FR_NOT_ENABLED; /* Check file system */
+ if (!(fs->flag & FA_OPENED)) /* Check if opened */
+ return FR_NOT_OPENED;
+
+ if (ofs > fs->fsize) ofs = fs->fsize; /* Clip offset with the file size */
+ ifptr = fs->fptr;
+ fs->fptr = 0;
+ if (ofs > 0) {
+ bcs = (DWORD)fs->csize * 512; /* Cluster size (uint8_t) */
+ if (ifptr > 0 &&
+ (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
+ fs->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */
+ ofs -= fs->fptr;
+ clst = fs->curr_clust;
+ } else { /* When seek to back cluster, */
+ clst = fs->org_clust; /* start from the first cluster */
+ fs->curr_clust = clst;
+ }
+ while (ofs > bcs) { /* Cluster following loop */
+ clst = get_fat(clst); /* Follow cluster chain */
+ if (clst <= 1 || clst >= fs->max_clust) goto fe_abort;
+ fs->curr_clust = clst;
+ fs->fptr += bcs;
+ ofs -= bcs;
+ }
+ fs->fptr += ofs;
+ sect = clust2sect(clst); /* Current sector */
+ if (!sect) goto fe_abort;
+ fs->csect = (uint8_t)(ofs / 512); /* Sector offset in the cluster */
+ if (ofs % 512)
+ fs->dsect = sect + fs->csect++;
+ }
+
+ return FR_OK;
+
+fe_abort:
+ fs->flag = 0;
+ return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create a Directroy Object */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+
+FRESULT pf_opendir (
+ DIR *dj, /* Pointer to directory object to create */
+ const char *path /* Pointer to the directory path */
+)
+{
+ FRESULT res;
+ uint8_t sp[12], dir[32];
+ FATFS *fs = FatFs;
+
+
+ if (!fs) { /* Check file system */
+ res = FR_NOT_ENABLED;
+ } else {
+ fs->buf = dir;
+ dj->fn = sp;
+ res = follow_path(dj, path); /* Follow the path to the directory */
+ if (res == FR_OK) { /* Follow completed */
+ if (dir[0]) { /* It is not the root dir */
+ if (dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
+ dj->sclust =
+#if _FS_FAT32
+ ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+ LD_WORD(dir+DIR_FstClusLO);
+ } else { /* The object is not a directory */
+ res = FR_NO_PATH;
+ }
+ }
+ if (res == FR_OK)
+ res = dir_rewind(dj); /* Rewind dir */
+ }
+ if (res == FR_NO_FILE) res = FR_NO_PATH;
+ }
+
+ return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Directory Entry in Sequense */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_readdir (
+ DIR *dj, /* Pointer to the open directory object */
+ FILINFO *fno /* Pointer to file information to return */
+)
+{
+ FRESULT res;
+ uint8_t sp[12], dir[32];
+ FATFS *fs = FatFs;
+
+
+ if (!fs) { /* Check file system */
+ res = FR_NOT_ENABLED;
+ } else {
+ fs->buf = dir;
+ dj->fn = sp;
+ if (!fno) {
+ res = dir_rewind(dj);
+ } else {
+ res = dir_read(dj);
+ if (res == FR_NO_FILE) {
+ dj->sect = 0;
+ res = FR_OK;
+ }
+ if (res == FR_OK) { /* A valid entry is found */
+ get_fileinfo(dj, fno); /* Get the object information */
+ res = dir_next(dj); /* Increment index for next */
+ if (res == FR_NO_FILE) {
+ dj->sect = 0;
+ res = FR_OK;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+#endif /* _USE_DIR */
+
diff --git a/src/FatFs/pff.h b/src/FatFs/pff.h new file mode 100755 index 0000000..e28542c --- /dev/null +++ b/src/FatFs/pff.h @@ -0,0 +1,469 @@ +/*---------------------------------------------------------------------------/
+/ Petit FatFs - FAT file system module include file R0.02 (C)ChaN, 2009
+/----------------------------------------------------------------------------/
+/ Petit FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/ Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/----------------------------------------------------------------------------*/
+
+#include "integer.h"
+#include <stdint.h>
+#include <libmary.h>
+/*---------------------------------------------------------------------------/
+/ Petit FatFs Configuration Options
+/
+/ CAUTION! Do not forget to make clean the project after any changes to
+/ the configuration options.
+/
+/----------------------------------------------------------------------------*/
+#ifndef _FATFS
+#define _FATFS
+
+#define _USE_READ 1 /* pf_read(): 0:Remove ,1:Enable */
+
+#define _USE_DIR 1 /* pf_opendir() and pf_readdir(): 0:Remove ,1:Enable */
+
+#define _USE_LSEEK 1 /* pf_lseek(): 0:Remove ,1:Enable */
+
+#define _USE_WRITE 1 /* pf_write(): 0:Remove ,1:Enable */
+
+#define _FS_FAT32 1 /* 0:Supports FAT12/16 only, 1:Enable FAT32 supprt */
+
+
+#define _CODE_PAGE 1
+/* Defines which code page is used for path name. Supported code pages are:
+/ 932, 936, 949, 950, 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866,
+/ 874, 1250, 1251, 1252, 1253, 1254, 1255, 1257, 1258 and 1 (ASCII only).
+/ SBCS configurations except for 1 requiers a case conversion table. This
+/ might occupy 128 bytes on the RAM on some platforms, e.g. avr-gcc. */
+
+
+#define _WORD_ACCESS 0 // 1
+/* The _WORD_ACCESS option defines which access method is used to the word
+/ data in the FAT structure.
+/
+/ 0: Byte-by-byte access. Always compatible with all platforms.
+/ 1: Word access. Do not choose this unless following condition is met.
+/
+/ When the byte order on the memory is big-endian or address miss-aligned
+/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
+/ If it is not the case, the value can also be set to 1 to improve the
+/ performance and code efficiency. */
+
+
+/* End of configuration options. Do not change followings without care. */
+/*--------------------------------------------------------------------------*/
+
+
+
+#if _FS_FAT32
+#define CLUST DWORD
+#else
+#define CLUST WORD
+#endif
+
+
+/* File system object structure */
+
+typedef struct _FATFS_ {
+ uint8_t fs_type; /* FAT sub type */
+ uint8_t csize; /* Number of sectors per cluster */
+ uint8_t flag; /* File status flags */
+ uint8_t csect; /* File sector address in the cluster */
+ WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */
+ uint8_t* buf; /* Pointer to the disk access buffer */
+ CLUST max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
+ DWORD fatbase; /* FAT start sector */
+ DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */
+ DWORD database; /* Data start sector */
+ DWORD fptr; /* File R/W pointer */
+ DWORD fsize; /* File size */
+ CLUST org_clust; /* File start cluster */
+ CLUST curr_clust; /* File current cluster */
+ DWORD dsect; /* File current data sector */
+} FATFS;
+
+
+
+/* Directory object structure */
+
+typedef struct _DIR_ {
+ WORD index; /* Current read/write index number */
+ uint8_t* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+ CLUST sclust; /* Table start cluster (0:Static table) */
+ CLUST clust; /* Current cluster */
+ DWORD sect; /* Current sector */
+} DIR;
+
+
+
+/* File status structure */
+
+typedef struct _FILINFO_ {
+ DWORD fsize; /* File size */
+ WORD fdate; /* Last modified date */
+ WORD ftime; /* Last modified time */
+ uint8_t fattrib; /* Attribute */
+ char fname[13]; /* File name */
+} FILINFO;
+
+
+
+/* File function return code (FRESULT) */
+
+typedef enum {
+ FR_OK = 0, /* 0 */
+ FR_DISK_ERR, /* 1 */
+ FR_NOT_READY, /* 2 */
+ FR_NO_FILE, /* 3 */
+ FR_NO_PATH, /* 4 */
+ FR_NOT_OPENED, /* 5 */
+ FR_NOT_ENABLED, /* 6 */
+ FR_NO_FILESYSTEM /* 7 */
+} FRESULT;
+
+
+
+/*--------------------------------------------------------------*/
+/* Petit FatFs module application interface */
+
+FRESULT pf_mount (FATFS*); /* Mount/Unmount a logical drive */
+FRESULT pf_open (const char*); /* Open a file */
+FRESULT pf_read (void*, WORD, WORD*); /* Read data from the open file */
+FRESULT pf_write (const void*, WORD, WORD*); /* Write data to the open file */
+FRESULT pf_lseek (DWORD); /* Move file pointer of the open file */
+FRESULT pf_opendir (DIR*, const char*); /* Open a directory */
+FRESULT pf_readdir (DIR*, FILINFO*); /* Read a directory item from the open directory */
+
+
+
+/*--------------------------------------------------------------*/
+/* Flags and offset address */
+
+/* File status flag (FATFS.flag) */
+
+#define FA_OPENED 0x01
+#define FA_WPRT 0x02
+#define FA__WIP 0x40
+
+
+/* FAT sub type (FATFS.fs_type) */
+
+#define FS_FAT12 1
+#define FS_FAT16 2
+#define FS_FAT32 3
+
+
+/* File attribute bits for directory entry */
+
+#define AM_RDO 0x01 /* Read only */
+#define AM_HID 0x02 /* Hidden */
+#define AM_SYS 0x04 /* System */
+#define AM_VOL 0x08 /* Volume label */
+#define AM_LFN 0x0F /* LFN entry */
+#define AM_DIR 0x10 /* Directory */
+#define AM_ARC 0x20 /* Archive */
+#define AM_MASK 0x3F /* Mask of defined bits */
+
+
+/* FatFs refers the members in the FAT structures with uint8_t offset instead
+/ of structure member because there are incompatibility of the packing option
+/ between various compilers. */
+
+#define BS_jmpBoot 0
+#define BS_OEMName 3
+#define BPB_BytsPerSec 11
+#define BPB_SecPerClus 13
+#define BPB_RsvdSecCnt 14
+#define BPB_NumFATs 16
+#define BPB_RootEntCnt 17
+#define BPB_TotSec16 19
+#define BPB_Media 21
+#define BPB_FATSz16 22
+#define BPB_SecPerTrk 24
+#define BPB_NumHeads 26
+#define BPB_HiddSec 28
+#define BPB_TotSec32 32
+#define BS_55AA 510
+
+#define BS_DrvNum 36
+#define BS_BootSig 38
+#define BS_VolID 39
+#define BS_VolLab 43
+#define BS_FilSysType 54
+
+#define BPB_FATSz32 36
+#define BPB_ExtFlags 40
+#define BPB_FSVer 42
+#define BPB_RootClus 44
+#define BPB_FSInfo 48
+#define BPB_BkBootSec 50
+#define BS_DrvNum32 64
+#define BS_BootSig32 66
+#define BS_VolID32 67
+#define BS_VolLab32 71
+#define BS_FilSysType32 82
+
+#define MBR_Table 446
+
+#define DIR_Name 0
+#define DIR_Attr 11
+#define DIR_NTres 12
+#define DIR_CrtTime 14
+#define DIR_CrtDate 16
+#define DIR_FstClusHI 20
+#define DIR_WrtTime 22
+#define DIR_WrtDate 24
+#define DIR_FstClusLO 26
+#define DIR_FileSize 28
+
+
+
+/*--------------------------------*/
+/* Multi-uint8_t word access macros */
+
+#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
+#define LD_WORD(ptr) (WORD)(*(WORD*)(uint8_t*)(ptr))
+#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(uint8_t*)(ptr))
+#define ST_WORD(ptr,val) *(WORD*)(uint8_t*)(ptr)=(WORD)(val)
+#define ST_DWORD(ptr,val) *(DWORD*)(uint8_t*)(ptr)=(DWORD)(val)
+#else /* Use uint8_t-by-uint8_t access to the FAT structure */
+#define LD_WORD(ptr) (WORD)(((WORD)*(uint8_t*)((ptr)+1)<<8)|(WORD)*(uint8_t*)(ptr))
+#define LD_DWORD(ptr) (DWORD)(((DWORD)*(uint8_t*)((ptr)+3)<<24)|((DWORD)*(uint8_t*)((ptr)+2)<<16)|((WORD)*(uint8_t*)((ptr)+1)<<8)|*(uint8_t*)(ptr))
+#define ST_WORD(ptr,val) *(uint8_t*)(ptr)=(uint8_t)(val); *(uint8_t*)((ptr)+1)=(uint8_t)((WORD)(val)>>8)
+#define ST_DWORD(ptr,val) *(uint8_t*)(ptr)=(uint8_t)(val); *(uint8_t*)((ptr)+1)=(uint8_t)((WORD)(val)>>8); *(uint8_t*)((ptr)+2)=(uint8_t)((DWORD)(val)>>16); *(uint8_t*)((ptr)+3)=(uint8_t)((DWORD)(val)>>24)
+#endif
+
+
+/*--------------------------------------------------------*/
+/* DBCS code ranges and SBCS extend char conversion table */
+
+#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
+#define _DF1S 0x81 /* DBC 1st uint8_t range 1 start */
+#define _DF1E 0x9F /* DBC 1st uint8_t range 1 end */
+#define _DF2S 0xE0 /* DBC 1st uint8_t range 2 start */
+#define _DF2E 0xFC /* DBC 1st uint8_t range 2 end */
+#define _DS1S 0x40 /* DBC 2nd uint8_t range 1 start */
+#define _DS1E 0x7E /* DBC 2nd uint8_t range 1 end */
+#define _DS2S 0x80 /* DBC 2nd uint8_t range 2 start */
+#define _DS2E 0xFC /* DBC 2nd uint8_t range 2 end */
+
+#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x40
+#define _DS1E 0x7E
+#define _DS2S 0x80
+#define _DS2E 0xFE
+
+#elif _CODE_PAGE == 949 /* Korean */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x41
+#define _DS1E 0x5A
+#define _DS2S 0x61
+#define _DS2E 0x7A
+#define _DS3S 0x81
+#define _DS3E 0xFE
+
+#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
+#define _DF1S 0x81
+#define _DF1E 0xFE
+#define _DS1S 0x40
+#define _DS1E 0x7E
+#define _DS2S 0xA1
+#define _DS2E 0xFE
+
+#elif _CODE_PAGE == 437 /* U.S. (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 720 /* Arabic (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 737 /* Greek (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
+ 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 775 /* Baltic (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+ 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
+ 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
+
+#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
+ 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
+ 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 857 /* Turkish (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
+ 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+ 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 866 /* Russian (OEM) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+
+#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
+ 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
+
+#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
+ 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+
+#elif _CODE_PAGE == 1253 /* Greek (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
+ 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
+
+#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
+ 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
+
+#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
+
+#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+ 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
+
+#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
+#define _DF1S 0
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
+ 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+ 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
+
+#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
+#define _DF1S 0
+
+#else
+#error Unknown code page
+
+#endif
+
+
+
+/* Character code support macros */
+
+#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
+#define IsLower(c) (((c)>='a')&&((c)<='z'))
+
+#if _DF1S /* DBCS configuration */
+
+#ifdef _DF2S /* Two 1st uint8_t areas */
+#define IsDBCS1(c) (((uint8_t)(c) >= _DF1S && (uint8_t)(c) <= _DF1E) || ((uint8_t)(c) >= _DF2S && (uint8_t)(c) <= _DF2E))
+#else /* One 1st uint8_t area */
+#define IsDBCS1(c) ((uint8_t)(c) >= _DF1S && (uint8_t)(c) <= _DF1E)
+#endif
+
+#ifdef _DS3S /* Three 2nd uint8_t areas */
+#define IsDBCS2(c) (((uint8_t)(c) >= _DS1S && (uint8_t)(c) <= _DS1E) || ((uint8_t)(c) >= _DS2S && (uint8_t)(c) <= _DS2E) || ((uint8_t)(c) >= _DS3S && (uint8_t)(c) <= _DS3E))
+#else /* Two 2nd uint8_t areas */
+#define IsDBCS2(c) (((uint8_t)(c) >= _DS1S && (uint8_t)(c) <= _DS1E) || ((uint8_t)(c) >= _DS2S && (uint8_t)(c) <= _DS2E))
+#endif
+
+#else /* SBCS configuration */
+
+#define IsDBCS1(c) 0
+#define IsDBCS2(c) 0
+
+#endif /* _DF1S */
+
+
+#endif /* _FATFS */
diff --git a/src/FatFs/sdcard.cpp b/src/FatFs/sdcard.cpp new file mode 100755 index 0000000..b37ad5a --- /dev/null +++ b/src/FatFs/sdcard.cpp @@ -0,0 +1,287 @@ +/*-----------------------------------------------------------------------*/
+/* PFF - Low level disk control module for ATtiny85 (C)ChaN, 2009 */
+/*-----------------------------------------------------------------------*/
+
+#define _WRITE_FUNC 1
+
+#include "diskio.h"
+#include <libmary.h>
+#include <SPI.h>
+#include <SD.h>
+
+
+/* Definitions for MMC/SDC command */
+#define CMD0 (0x40+0) /* GO_IDLE_STATE */
+#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
+#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
+#define CMD8 (0x40+8) /* SEND_IF_COND */
+#define CMD16 (0x40+16) /* SET_BLOCKLEN */
+#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
+#define CMD24 (0x40+24) /* WRITE_BLOCK */
+#define CMD55 (0x40+55) /* APP_CMD */
+#define CMD58 (0x40+58) /* READ_OCR */
+
+
+/* USI control functions (Defined in usi.S, Platform dependent) */
+//void xmit_spi (BYTE); /* Send a byte */
+//BYTE rcv_spi (void); /* Send 0xFF and receive a byte */
+void xmit_spi (uint8_t data)
+{
+ SPI.transfer(data);
+}
+int rcv_spi(void)
+{
+ return SPI.transfer(0xff);
+}
+
+/* Port Controls (Platform dependent) */
+//#define SELECT() PORTB &= ~0x08 /* MMC CS = L */
+//#define DESELECT() PORTB |= 0x08 /* MMC CS = H */
+//#define MMC_SEL !(PORTB & 0x08) /* MMC CS status (true:selected) */
+//#define INIT_SPI() { USICR = 0b00011000; } /* Initialize SPI port */
+#define SELECT() digitalWrite(SDFile.SDCS,LOW) // MMC CS = PIO0_2
+#define DESELECT() digitalWrite(SDFile.SDCS,HIGH)
+#define MMC_SEL !digitalRead(SDFile.SDCS)
+#define INIT_SPI_SD(speed) Init_SPI(8, speed, SPI_SDCARD)
+
+/*--------------------------------------------------------------------------
+
+ Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+static
+uint8_t CardType;
+
+
+/*-----------------------------------------------------------------------*/
+/* Deselect the card and release SPI bus */
+/*-----------------------------------------------------------------------*/
+
+static
+void release_spi (void)
+{
+ DESELECT();
+ rcv_spi();
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Send a command packet to MMC */
+/*-----------------------------------------------------------------------*/
+
+static
+uint8_t send_cmd (
+ uint8_t cmd, /* Command uint8_t */
+ DWORD arg /* Argument */
+)
+{
+ uint8_t n, res;
+
+
+ if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
+ cmd &= 0x7F;
+ res = send_cmd(CMD55, 0);
+ if (res > 1) return res;
+ }
+
+ /* Select the card */
+ DESELECT();
+ rcv_spi();
+ SELECT();
+ rcv_spi();
+
+ /* Send a command packet */
+ xmit_spi(cmd); /* Start + Command index */
+ xmit_spi((uint8_t)(arg >> 24)); /* Argument[31..24] */
+ xmit_spi((uint8_t)(arg >> 16)); /* Argument[23..16] */
+ xmit_spi((uint8_t)(arg >> 8)); /* Argument[15..8] */
+ xmit_spi((uint8_t)arg); /* Argument[7..0] */
+ n = 0x01; /* Dummy CRC + Stop */
+ if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
+ if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
+ xmit_spi(n);
+
+ /* Receive a command response */
+ n = 10; /* Wait for a valid response in timeout of 10 attempts */
+ do {
+ res = rcv_spi();
+ } while ((res & 0x80) && --n);
+
+ return res; /* Return with the response value */
+}
+
+
+
+/*--------------------------------------------------------------------------
+
+ Public Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (void)
+{
+ uint8_t n, cmd, ty, ocr[4];
+ WORD tmr;
+
+
+ //INIT_SPI();
+ //INIT_SPI_SD(SPI_SLOW);
+ pinMode(SDFile.SDCS,OUTPUT); //CS initialize
+ SPI.setBitLength(8);
+ SPI.setDataMode(SPI_MODE0);
+ SPI.setClockDivider(SPI_CLOCK_DIV32);
+ SPI.begin();
+
+#if _WRITE_FUNC
+ if (MMC_SEL) disk_writep(0, 0); /* Finalize write process if it is in progress */
+#endif
+ for (n = 100; n; n--) rcv_spi(); /* Dummy clocks */
+
+ ty = 0;
+ if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
+ if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
+ for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */
+ if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
+ for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */
+ if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
+ for (n = 0; n < 4; n++) ocr[n] = rcv_spi();
+ ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
+ }
+ }
+ } else { /* SDv1 or MMCv3 */
+ if (send_cmd(ACMD41, 0) <= 1) {
+ ty = CT_SD1; cmd = ACMD41; /* SDv1 */
+ } else {
+ ty = CT_MMC; cmd = CMD1; /* MMCv3 */
+ }
+ for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */
+ if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
+ ty = 0;
+ }
+ }
+ CardType = ty;
+ release_spi();
+
+ if (ty) SPI.setClockDivider(SPI_CLOCK_DIV4);//INIT_SPI_SD(SPI_FAST);
+
+ return ty ? 0 : STA_NOINIT;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read partial sector */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_readp (
+ uint8_t *buff, /* Pointer to the read buffer (NULL:Read uint8_ts are forwarded to the stream) */
+ DWORD lba, /* Sector number (LBA) */
+ WORD ofs, /* uint8_t offset to read from (0..511) */
+ WORD cnt /* Number of uint8_ts to read (ofs + cnt mus be <= 512) */
+)
+{
+ DRESULT res;
+ uint8_t rc;
+ WORD bc;
+
+
+ if (!(CardType & CT_BLOCK)) lba *= 512; /* Convert to uint8_t address if needed */
+
+ res = RES_ERROR;
+ if (send_cmd(CMD17, lba) == 0) { /* READ_SINGLE_BLOCK */
+
+ bc = 30000;
+ do { /* Wait for data packet in timeout of 100ms */
+ rc = rcv_spi();
+ } while (rc == 0xFF && --bc);
+
+ if (rc == 0xFE) { /* A data packet arrived */
+ bc = 514 - ofs - cnt;
+
+ /* Skip leading uint8_ts */
+ if (ofs) {
+ do rcv_spi(); while (--ofs);
+ }
+
+ /* Receive a part of the sector */
+ if (buff) { /* Store data to the memory */
+ do
+ *buff++ = rcv_spi();
+ while (--cnt);
+ } else { /* Forward data to the outgoing stream (depends on the project) */
+ do
+ //xmit(rcv_spi()); /* (Console output) */
+ Serial.println(rcv_spi(),DEC); // Console output
+ while (--cnt);
+ }
+
+ /* Skip trailing uint8_ts and CRC */
+ do rcv_spi(); while (--bc);
+
+ res = RES_OK;
+ }
+ }
+
+ release_spi();
+
+ return res;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write partial sector */
+/*-----------------------------------------------------------------------*/
+#if _WRITE_FUNC
+
+DRESULT disk_writep (
+ const uint8_t *buff, /* Pointer to the uint8_ts to be written (NULL:Initiate/Finalize sector write) */
+ DWORD sa /* Number of uint8_ts to send, Sector number (LBA) or zero */
+)
+{
+ DRESULT res;
+ WORD bc;
+ static WORD wc;
+
+ res = RES_ERROR;
+
+ if (buff) { /* Send data uint8_ts */
+ bc = (WORD)sa;
+ while (bc && wc) { /* Send data uint8_ts to the card */
+ xmit_spi(*buff++);
+ wc--; bc--;
+ }
+ res = RES_OK;
+ } else {
+ if (sa) { /* Initiate sector write process */
+ if (!(CardType & CT_BLOCK)) sa *= 512; /* Convert to uint8_t address if needed */
+ if (send_cmd(CMD24, sa) == 0) { /* WRITE_SINGLE_BLOCK */
+ xmit_spi(0xFF); xmit_spi(0xFE); /* Data block header */
+ wc = 512; /* Set uint8_t counter */
+ res = RES_OK;
+ }
+ } else { /* Finalize sector write process */
+ bc = wc + 2;
+ //while (bc--) xmit_spi(0); /* Fill left uint8_ts and CRC with zeros */
+ while (bc) /* Fill left uint8_ts and CRC with zeros */
+ {
+ xmit_spi(0);
+ bc--;
+ }
+ if ((rcv_spi() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */
+ for (bc = 65000; rcv_spi() != 0xFF && bc; bc--) ; /* Wait ready */
+ if (bc) res = RES_OK;
+ }
+ release_spi();
+ }
+ }
+
+ return res;
+}
+#endif
diff --git a/src/TFTLCD/TFTLCD.h b/src/TFTLCD/TFTLCD.h new file mode 100755 index 0000000..797383c --- /dev/null +++ b/src/TFTLCD/TFTLCD.h @@ -0,0 +1,220 @@ +#include <libmary.h> +#include <SPI.h> + +#define LCD_CS C33//4 //cs +#define LCD_DC C21//5 //data command +#define LCD_RES C31//6 //reset +//MOSI 11 C47 +//CLK 13 C43 +#define DC_DATA HIGH +#define DC_CMD LOW + +//#define STICK_A 7 +//#define STICK_B 8 +//#define STICK_C 9 +//#define STICK_D 10 +//#define STICK_CT 2 + + +#define select_disp() digitalWrite(LCD_CS,LOW) //PORTD &= ~(1 << PORTD4) +#define unselect_disp() digitalWrite(LCD_CS,HIGH) //PORTD |= (1 << PORTD4) + +#define set_disp_command() digitalWrite(LCD_DC,LOW) //PORTD &= ~(1 << PORTD5) +#define set_disp_data() digitalWrite(LCD_DC,HIGH) //PORTD |= (1 << PORTD5) + +/* SSD1283A Unique Value */ +/* MUST be need for SSD1283A */ +#define OFS_COL 2 +#define OFS_RAW 0 +#define MAX_X 130 +#define MAX_Y 130 + + + +void sendCmd(unsigned int cmd){ + select_disp(); + set_disp_command(); + // shiftOut2(PIN_MOSI,PIN_CLK,MSBFIRST,cmd); + SPI.transfer(cmd); + set_disp_data(); +} + +void sendData(unsigned int data){ + select_disp(); + set_disp_data(); + //shiftOut2(PIN_MOSI,PIN_CLK,MSBFIRST,data); + SPI.transfer(data); +} + +void sendData16(unsigned int data1,unsigned int data2){ + select_disp(); + set_disp_data(); + //shiftOut2(PIN_MOSI,PIN_CLK,MSBFIRST,data); + SPI.transfer(data1); + SPI.transfer(data2); +} + +void sendColor(unsigned int color){ + sendData(color&0x00ff); +} + + + + +void initDisplay(){ + select_disp(); + + digitalWrite(LCD_RES, LOW); + delay(80); + digitalWrite(LCD_RES, HIGH); + delay(20); + + /* SSD1283A */ + sendCmd(0x10); /* Power Control (1) */ + sendData16(0x2f,0x8e); /* Onchip DCDC Clock,Fine*2 StartCycle,VGH unregurated */ + /* StepUpCycle fosc,Internal OPAMP Current reserved,Sleep Mode OFF */ + + sendCmd(0x11); /* Power Control (2) */ + sendData16(0x00,0x0c); /* VGH/VCI ratio x4 */ + + sendCmd(0x07); /* Display Control */ + sendData16(0x00,0x21); /* Nomalize source out zero, Vartical Scroll not pafomed */ + /* 1 Divison Display,Source output GND, Gate output GVOFFL */ + + sendCmd(0x28); /* VCOM-OTP1 */ + sendData16(0x00,0x06); + + sendCmd(0x28); /* VCOM-OTP1 */ + sendData16(0x00,0x05); + + sendCmd(0x27); /* VCOM-OTP */ + sendData16(0x05,0x7f); + + sendCmd(0x29); /* VCOM-OTP2 */ + sendData16(0x89,0xa1); + + sendCmd(0x00); /* Oscillator On */ + sendData16(0x00,0x01); + delay(150); + + sendCmd(0x29); /* VCOM-OTP2 */ + sendData16(0x80,0xb0); + delay(50); + + sendCmd(0x29); /* VCOM-OTP2 */ + sendData16(0xff,0xfe); + + sendCmd(0x07); /* Display Control */ + sendData16(0x00,0x23); + delay(50); + + sendCmd(0x07); /* Display Control (Confirm) */ + sendData16(0x00,0x23); + delay(50); + + sendCmd(0x07); /* Display Control */ + sendData16(0x00,0x33); /* Nomalize source out zero, Vartical Scroll not pafomed */ + /* 1 Divison Display,,Source output GND (OFF) */ + /* Gate output Selected VGH, others GVOFFL */ + + sendCmd(0x01); /* Driver Output Control */ + sendData16(0x21,0x83); /* Reversal ON ,Cs On Common,BGR,Scanning Mounting Method */ + /* Output Shift Direction of Gate Driver G131->G0, */ + /* Output Shift Direction of Source Driver S0->S395, */ + /* Number of Gate Driver 131 */ + + sendCmd(0x2f); /* ??? */ + sendData16(0xff,0xff); + + sendCmd(0x2c); /* Oscillator frequency */ + sendData16(0x80,0x00); /* 520kHz */ + + sendCmd(0x03); /* Entry mode */ + sendData16(0x68,0x30); /* Colour mode 65k,OE defines Display Window,D-mode from internal ram */ + /* Horizontal increment & Vertical increment & AM 0 Horizontal */ + + sendCmd(0x40); /* Set Offset */ + sendData16(0x00,0x02); + + sendCmd(0x27); /* Further bias current setting */ + sendData16(0x05,0x70); /* Maximum */ + + sendCmd(0x02); /* LCD-Driving-Waveform Control */ + sendData16(0x03,0x00); /* the odd/even frame-select signals and the N-line inversion */ + /* signals are EORed for alternating drive */ + + sendCmd(0x0b); /* Frame Cycle Control */ + sendData16(0x58,0x0c); /* Amount of Overlap 4 clock cycle */ + /* Delay amount of the source output 2 clock cycle */ + /* EQ period 2 clock cycle, Division Ratio 2 */ + + sendCmd(0x12); /* Power Control 3 */ + sendData16(0x06,0x09); /* Set amplitude magnification of VLCD63 = Vref x 2.175 */ + + sendCmd(0x13); /* Power Control 4 */ + sendData16(0x31,0x00); /* Set output voltage of VcomL = VLCD63 x 1.02 */ + + sendCmd(0x2a); /* Test Commands ? */ + sendData16(0x1d,0xd0); + + sendCmd(0x2b); /* Test Commands ? */ + sendData16(0x0a,0x90); + + sendCmd(0x2d); /* Test Commands ? */ + sendData16(0x31,0x0f); + delay(100); + + sendCmd(0x44); /* Set CAS Address */ + sendData16(0x83,0x00); + + sendCmd(0x45); /* Set RAS Address */ + sendData16(0x83,0x00); + + sendCmd(0x21); /* Set RAM Address */ + sendData16(0x00,0x00); + + sendCmd(0x1e); /* Power Control 5 */ + sendData16(0x00,0xbf); /* VcomH = VLCD63 x 0.99 */ + delay(1); + + sendCmd(0x1e); /* Power Control 5 */ + sendData16(0x00,0x00); /* VcomH =VLCD63 x 0.36 */ + delay(100); + + unselect_disp(); +} + +void resetArea(){ + int x=0,y=0; + int xwidth=130 , yheight=130; + + select_disp(); + + /* Set CAS Address */ + sendCmd(0x44); + sendData16(OFS_COL + xwidth - 1, OFS_COL + x); + + /* Set RAS Address */ + sendCmd(0x45); + sendData16(OFS_RAW + yheight - 1, OFS_RAW + y); + + /* Set RAM Address */ + sendCmd(0x21); + sendData16(OFS_RAW + y, OFS_COL + x); + + /* Write RAM */ + sendCmd(0x22); + + set_disp_data(); + unselect_disp(); +} + +void fillScreen(unsigned int color_H,unsigned int color_L){ + select_disp(); + int i; + resetArea(); + for(i=0;i<16900;i++){ + sendData16(color_H,color_L); + } + unselect_disp(); +} diff --git a/src/XBee/XBee.cpp b/src/XBee/XBee.cpp new file mode 100755 index 0000000..fedcfdb --- /dev/null +++ b/src/XBee/XBee.cpp @@ -0,0 +1,1355 @@ +/** + * Copyright (c) 2009 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-Arduino. + * + * XBee-Arduino is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-Arduino 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 XBee-Arduino. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libmary.h> +#include "XBee.h" +#include <uart.h> + +//#include "WProgram.h" +//#include "HardwareSerial.h" + + + +XBeeResponse::XBeeResponse() { + +} + +uint8_t XBeeResponse::getApiId() { + return _apiId; +} + +void XBeeResponse::setApiId(uint8_t apiId) { + _apiId = apiId; +} + +uint8_t XBeeResponse::getMsbLength() { + return _msbLength; +} + +void XBeeResponse::setMsbLength(uint8_t msbLength) { + _msbLength = msbLength; +} + +uint8_t XBeeResponse::getLsbLength() { + return _lsbLength; +} + +void XBeeResponse::setLsbLength(uint8_t lsbLength) { + _lsbLength = lsbLength; +} + +uint8_t XBeeResponse::getChecksum() { + return _checksum; +} + +void XBeeResponse::setChecksum(uint8_t checksum) { + _checksum = checksum; +} + +uint8_t XBeeResponse::getFrameDataLength() { + return _frameLength; +} + +void XBeeResponse::setFrameLength(uint8_t frameLength) { + _frameLength = frameLength; +} + +bool XBeeResponse::isAvailable() { + return _complete; +} + +void XBeeResponse::setAvailable(bool complete) { + _complete = complete; +} + +bool XBeeResponse::isError() { + return _errorCode > 0; +} + +uint8_t XBeeResponse::getErrorCode() { + return _errorCode; +} + +void XBeeResponse::setErrorCode(uint8_t errorCode) { + _errorCode = errorCode; +} + +// copy common fields from xbee response to target response +void XBeeResponse::setCommon(XBeeResponse &target) { + target.setApiId(getApiId()); + target.setAvailable(isAvailable()); + target.setChecksum(getChecksum()); + target.setErrorCode(getErrorCode()); + target.setFrameLength(getFrameDataLength()); + target.setMsbLength(getMsbLength()); + target.setLsbLength(getLsbLength()); +} + +#ifdef SERIES_2 + +ZBTxStatusResponse::ZBTxStatusResponse() : FrameIdResponse() { + +} + +uint16_t ZBTxStatusResponse::getRemoteAddress() { + return (getFrameData()[1] << 8) + getFrameData()[2]; +} + +uint8_t ZBTxStatusResponse::getTxRetryCount() { + return getFrameData()[3]; +} + +uint8_t ZBTxStatusResponse::getDeliveryStatus() { + return getFrameData()[4]; +} + +uint8_t ZBTxStatusResponse::getDiscoveryStatus() { + return getFrameData()[5]; +} + +bool ZBTxStatusResponse::isSuccess() { + return getDeliveryStatus() == SUCCESS; +} + +void XBeeResponse::getZBTxStatusResponse(XBeeResponse &zbXBeeResponse) { + + // way off? + ZBTxStatusResponse* zb = static_cast<ZBTxStatusResponse*>(&zbXBeeResponse); + // pass pointer array to subclass + zb->setFrameData(getFrameData()); + setCommon(zbXBeeResponse); +} + +ZBRxResponse::ZBRxResponse(): RxDataResponse() { + _remoteAddress64 = XBeeAddress64(); +} + +uint16_t ZBRxResponse::getRemoteAddress16() { + return (getFrameData()[8] << 8) + getFrameData()[9]; +} + +uint8_t ZBRxResponse::getOption() { + return getFrameData()[10]; +} + +// markers to read data from packet array. this is the index, so the 12th item in the array +uint8_t ZBRxResponse::getDataOffset() { + return 11; +} + +uint8_t ZBRxResponse::getDataLength() { + return getPacketLength() - getDataOffset() - 1; +} + +XBeeAddress64& ZBRxResponse::getRemoteAddress64() { + return _remoteAddress64; +} + +void XBeeResponse::getZBRxResponse(XBeeResponse &rxResponse) { + + ZBRxResponse* zb = static_cast<ZBRxResponse*>(&rxResponse); + + //TODO verify response api id matches this api for this response + + // pass pointer array to subclass + zb->setFrameData(getFrameData()); + setCommon(rxResponse); + + zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]); + zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7])); +} + + +ZBRxIoSampleResponse::ZBRxIoSampleResponse() : ZBRxResponse() { + +} + +// 64 + 16 addresses, sample size, option = 12 (index 11), so this starts at 12 +uint8_t ZBRxIoSampleResponse::getDigitalMaskMsb() { + return getFrameData()[12] & 0x1c; +} + +uint8_t ZBRxIoSampleResponse::getDigitalMaskLsb() { + return getFrameData()[13]; +} + +uint8_t ZBRxIoSampleResponse::getAnalogMask() { + return getFrameData()[14] & 0x8f; +} + +bool ZBRxIoSampleResponse::containsAnalog() { + return getAnalogMask() > 0; +} + +bool ZBRxIoSampleResponse::containsDigital() { + return getDigitalMaskMsb() > 0 || getDigitalMaskLsb() > 0; +} + +bool ZBRxIoSampleResponse::isAnalogEnabled(uint8_t pin) { + return ((getAnalogMask() >> pin) & 1) == 1; +} + +bool ZBRxIoSampleResponse::isDigitalEnabled(uint8_t pin) { + if (pin <= 7) { + // added extra parens to calm avr compiler + return ((getDigitalMaskLsb() >> pin) & 1) == 1; + } else { + return ((getDigitalMaskMsb() >> (pin - 8)) & 1) == 1; + } +} + +uint16_t ZBRxIoSampleResponse::getAnalog(uint8_t pin) { + // analog starts 13 bytes after sample size, if no dio enabled + uint8_t start = 15; + + if (containsDigital()) { + // make room for digital i/o + start+=2; + } + +// std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl; + + // start depends on how many pins before this pin are enabled + for (int i = 0; i < pin; i++) { + if (isAnalogEnabled(pin)) { + start+=2; + } + } + +// std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl; + +// std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl; + + return (uint16_t)((getFrameData()[start] << 8) + getFrameData()[start + 1]); +} + +bool ZBRxIoSampleResponse::isDigitalOn(uint8_t pin) { + if (pin <= 7) { + // D0-7 + // DIO LSB is index 5 + return ((getFrameData()[16] >> pin) & 1) == 1; + } else { + // D10-12 + // DIO MSB is index 4 + return ((getFrameData()[15] >> (pin - 8)) & 1) == 1; + } +} + +void XBeeResponse::getZBRxIoSampleResponse(XBeeResponse &response) { + ZBRxIoSampleResponse* zb = static_cast<ZBRxIoSampleResponse*>(&response); + + + // pass pointer array to subclass + zb->setFrameData(getFrameData()); + setCommon(response); + + zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]); + zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7])); +} + +#endif + +#ifdef SERIES_1 + +RxResponse::RxResponse() : RxDataResponse() { + +} + +uint16_t Rx16Response::getRemoteAddress16() { + return (getFrameData()[0] << 8) + getFrameData()[1]; +} + +XBeeAddress64& Rx64Response::getRemoteAddress64() { + return _remoteAddress; +} + +Rx64Response::Rx64Response() : RxResponse() { + _remoteAddress = XBeeAddress64(); +} + +Rx16Response::Rx16Response() : RxResponse() { + +} + +RxIoSampleBaseResponse::RxIoSampleBaseResponse() : RxResponse() { + +} + +uint8_t RxIoSampleBaseResponse::getSampleOffset() { + // sample starts 2 bytes after rssi + return getRssiOffset() + 2; +} + + +uint8_t RxIoSampleBaseResponse::getSampleSize() { + return getFrameData()[getSampleOffset()]; +} + +bool RxIoSampleBaseResponse::containsAnalog() { + return (getFrameData()[getSampleOffset() + 1] & 0x7e) > 0; +} + +bool RxIoSampleBaseResponse::containsDigital() { + return (getFrameData()[getSampleOffset() + 1] & 0x1) > 0 || getFrameData()[getSampleOffset() + 2] > 0; +} + +//uint16_t RxIoSampleBaseResponse::getAnalog0(uint8_t sample) { +// return getAnalog(0, sample); +//} + +bool RxIoSampleBaseResponse::isAnalogEnabled(uint8_t pin) { + return (((getFrameData()[getSampleOffset() + 1] >> (pin + 1)) & 1) == 1); +} + +bool RxIoSampleBaseResponse::isDigitalEnabled(uint8_t pin) { + if (pin < 8) { + return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1; + } else { + return (getFrameData()[getSampleOffset() + 3] & 1) == 1; + } +} + +uint16_t RxIoSampleBaseResponse::getAnalog(uint8_t pin, uint8_t sample) { + + // analog starts 3 bytes after sample size, if no dio enabled + uint8_t start = 3; + + if (containsDigital()) { + // make room for digital i/o sample (2 bytes per sample) + start+=2*(sample + 1); + } + + uint8_t spacing = 0; + + // spacing between samples depends on how many are enabled. add one for each analog that's enabled + for (int i = 0; i <= 5; i++) { + if (isAnalogEnabled(i)) { + // each analog is two bytes + spacing+=2; + } + } + +// std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl; + + // start depends on how many pins before this pin are enabled + for (int i = 0; i < pin; i++) { + if (isAnalogEnabled(pin)) { + start+=2; + } + } + + start+= sample * spacing; + +// std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl; + +// std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl; + + return (uint16_t)((getFrameData()[getSampleOffset() + start] << 8) + getFrameData()[getSampleOffset() + start + 1]); +} + +bool RxIoSampleBaseResponse::isDigitalOn(uint8_t pin, uint8_t sample) { + if (pin < 8) { + return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1; + } else { + return (getFrameData()[getSampleOffset() + 3] & 1) == 1; + } +} + + +//bool RxIoSampleBaseResponse::isDigital0On(uint8_t sample) { +// return isDigitalOn(0, sample); +//} + +Rx16IoSampleResponse::Rx16IoSampleResponse() : RxIoSampleBaseResponse() { + +} + +uint16_t Rx16IoSampleResponse::getRemoteAddress16() { + return (uint16_t)((getFrameData()[0] << 8) + getFrameData()[1]); +} + +uint8_t Rx16IoSampleResponse::getRssiOffset() { + return 2; +} + +void XBeeResponse::getRx16IoSampleResponse(XBeeResponse &response) { + Rx16IoSampleResponse* rx = static_cast<Rx16IoSampleResponse*>(&response); + + rx->setFrameData(getFrameData()); + setCommon(response); +} + + +Rx64IoSampleResponse::Rx64IoSampleResponse() : RxIoSampleBaseResponse() { + _remoteAddress = XBeeAddress64(); +} + +XBeeAddress64& Rx64IoSampleResponse::getRemoteAddress64() { + return _remoteAddress; +} + +uint8_t Rx64IoSampleResponse::getRssiOffset() { + return 8; +} + +void XBeeResponse::getRx64IoSampleResponse(XBeeResponse &response) { + Rx64IoSampleResponse* rx = static_cast<Rx64IoSampleResponse*>(&response); + + rx->setFrameData(getFrameData()); + setCommon(response); + + rx->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]); + rx->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]); +} + +TxStatusResponse::TxStatusResponse() : FrameIdResponse() { + +} + +uint8_t TxStatusResponse::getStatus() { + return getFrameData()[1]; +} + +bool TxStatusResponse::isSuccess() { + return getStatus() == SUCCESS; +} + +void XBeeResponse::getTxStatusResponse(XBeeResponse &txResponse) { + + TxStatusResponse* txStatus = static_cast<TxStatusResponse*>(&txResponse); + + // pass pointer array to subclass + txStatus->setFrameData(getFrameData()); + setCommon(txResponse); +} + +uint8_t RxResponse::getRssi() { + return getFrameData()[getRssiOffset()]; +} + +uint8_t RxResponse::getOption() { + return getFrameData()[getRssiOffset() + 1]; +} + +bool RxResponse::isAddressBroadcast() { + return (getOption() & 2) == 2; +} + +bool RxResponse::isPanBroadcast() { + return (getOption() & 4) == 4; +} + +uint8_t RxResponse::getDataLength() { + return getPacketLength() - getDataOffset() - 1; +} + +uint8_t RxResponse::getDataOffset() { + return getRssiOffset() + 2; +} + +uint8_t Rx16Response::getRssiOffset() { + return RX_16_RSSI_OFFSET; +} + +void XBeeResponse::getRx16Response(XBeeResponse &rx16Response) { + + Rx16Response* rx16 = static_cast<Rx16Response*>(&rx16Response); + + // pass pointer array to subclass + rx16->setFrameData(getFrameData()); + setCommon(rx16Response); + +// rx16->getRemoteAddress16().setAddress((getFrameData()[0] << 8) + getFrameData()[1]); +} + +uint8_t Rx64Response::getRssiOffset() { + return RX_64_RSSI_OFFSET; +} + +void XBeeResponse::getRx64Response(XBeeResponse &rx64Response) { + + Rx64Response* rx64 = static_cast<Rx64Response*>(&rx64Response); + + // pass pointer array to subclass + rx64->setFrameData(getFrameData()); + setCommon(rx64Response); + + rx64->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]); + rx64->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]); +} + +#endif + +RemoteAtCommandResponse::RemoteAtCommandResponse() : AtCommandResponse() { + +} + +uint8_t* RemoteAtCommandResponse::getCommand() { + return getFrameData() + 11; +} + +uint8_t RemoteAtCommandResponse::getStatus() { + return getFrameData()[13]; +} + +bool RemoteAtCommandResponse::isOk() { + // weird c++ behavior. w/o this method, it calls AtCommandResponse::isOk(), which calls the AtCommandResponse::getStatus, not this.getStatus!!! + return getStatus() == AT_OK; +} + +uint8_t RemoteAtCommandResponse::getValueLength() { + return getFrameDataLength() - 14; +} + +uint8_t* RemoteAtCommandResponse::getValue() { + if (getValueLength() > 0) { + // value is only included for query commands. set commands does not return a value + return getFrameData() + 14; + } + + return NULL; +} + +uint16_t RemoteAtCommandResponse::getRemoteAddress16() { + return uint16_t((getFrameData()[9] << 8) + getFrameData()[10]); +} + +XBeeAddress64& RemoteAtCommandResponse::getRemoteAddress64() { + return _remoteAddress64; +} + +void XBeeResponse::getRemoteAtCommandResponse(XBeeResponse &response) { + + // TODO no real need to cast. change arg to match expected class + RemoteAtCommandResponse* at = static_cast<RemoteAtCommandResponse*>(&response); + + // pass pointer array to subclass + at->setFrameData(getFrameData()); + setCommon(response); + + at->getRemoteAddress64().setMsb((uint32_t(getFrameData()[1]) << 24) + (uint32_t(getFrameData()[2]) << 16) + (uint16_t(getFrameData()[3]) << 8) + getFrameData()[4]); + at->getRemoteAddress64().setLsb((uint32_t(getFrameData()[5]) << 24) + (uint32_t(getFrameData()[6]) << 16) + (uint16_t(getFrameData()[7]) << 8) + (getFrameData()[8])); + +} + +RxDataResponse::RxDataResponse() : XBeeResponse() { + +} + +uint8_t RxDataResponse::getData(int index) { + return getFrameData()[getDataOffset() + index]; +} + +uint8_t* RxDataResponse::getData() { + return getFrameData() + getDataOffset(); +} + +FrameIdResponse::FrameIdResponse() { + +} + +uint8_t FrameIdResponse::getFrameId() { + return getFrameData()[0]; +} + + +ModemStatusResponse::ModemStatusResponse() { + +} + +uint8_t ModemStatusResponse::getStatus() { + return getFrameData()[0]; +} + +void XBeeResponse::getModemStatusResponse(XBeeResponse &modemStatusResponse) { + + ModemStatusResponse* modem = static_cast<ModemStatusResponse*>(&modemStatusResponse); + + // pass pointer array to subclass + modem->setFrameData(getFrameData()); + setCommon(modemStatusResponse); + +} + +AtCommandResponse::AtCommandResponse() { + +} + +uint8_t* AtCommandResponse::getCommand() { + return getFrameData() + 1; +} + +uint8_t AtCommandResponse::getStatus() { + return getFrameData()[3]; +} + +uint8_t AtCommandResponse::getValueLength() { + return getFrameDataLength() - 4; +} + +uint8_t* AtCommandResponse::getValue() { + if (getValueLength() > 0) { + // value is only included for query commands. set commands does not return a value + return getFrameData() + 4; + } + + return NULL; +} + +bool AtCommandResponse::isOk() { + return getStatus() == AT_OK; +} + +void XBeeResponse::getAtCommandResponse(XBeeResponse &atCommandResponse) { + + AtCommandResponse* at = static_cast<AtCommandResponse*>(&atCommandResponse); + + // pass pointer array to subclass + at->setFrameData(getFrameData()); + setCommon(atCommandResponse); +} + +uint16_t XBeeResponse::getPacketLength() { + return ((_msbLength << 8) & 0xff) + (_lsbLength & 0xff); +} + +uint8_t* XBeeResponse::getFrameData() { + return _frameDataPtr; +} + +void XBeeResponse::setFrameData(uint8_t* frameDataPtr) { + _frameDataPtr = frameDataPtr; +} + +void XBeeResponse::init() { + _complete = false; + _errorCode = NO_ERROR; + _checksum = 0; +} + +void XBeeResponse::reset() { + init(); + _apiId = 0; + _msbLength = 0; + _lsbLength = 0; + _checksum = 0; + _frameLength = 0; + + for (int i = 0; i < MAX_FRAME_DATA_SIZE; i++) { + getFrameData()[i] = 0; + } +} + +void XBee::resetResponse() { + _pos = 0; + _escape = false; + _response.reset(); +} + +XBee::XBee(): _response(XBeeResponse()) { + _pos = 0; + _escape = false; + _checksumTotal = 0; + _nextFrameId = 0; + + _response.init(); + _response.setFrameData(_responseFrameData); +} + +uint8_t XBee::getNextFrameId() { + + _nextFrameId++; + + if (_nextFrameId == 0) { + // can't send 0 because that disables status response + _nextFrameId = 1; + } + + return _nextFrameId; +} + +void XBee::begin(int baud) +{ + Serial.begin(baud);//Serial.begin(baud); +} + +/*void XBee::setSerial(HardwareSerial serial) { + Serial = serial; +}*/ + +XBeeResponse& XBee::getResponse() { + return _response; +} + +// TODO how to convert response to proper subclass? +void XBee::getResponse(XBeeResponse &response) { + + response.setMsbLength(_response.getMsbLength()); + response.setLsbLength(_response.getLsbLength()); + response.setApiId(_response.getApiId()); + response.setFrameLength(_response.getFrameDataLength()); + + response.setFrameData(_response.getFrameData()); +} + +void XBee::readPacketUntilAvailable() { + while (!(getResponse().isAvailable() || getResponse().isError())) { + // read some more + readPacket(); + } +} + +bool XBee::readPacket(int timeout) { + + if (timeout < 0) { + return false; + } + + unsigned long start = millis(); + + while (int((millis() - start)) < timeout) { + + readPacket(); + + if (getResponse().isAvailable()) { + return true; + } else if (getResponse().isError()) { + return false; + } + } + + // timed out + return false; +} + +void XBee::readPacket() { + // reset previous response + if (_response.isAvailable() || _response.isError()) { + // discard previous packet and start over + resetResponse(); + } + + while (Serial.available()) { + + b = Serial.read(); + + if (_pos > 0 && b == START_BYTE && ATAP == 2) { + // new packet start before previous packeted completed -- discard previous packet and start over + _response.setErrorCode(UNEXPECTED_START_BYTE); + return; + } + + if (_pos > 0 && b == ESCAPE) { + if (Serial.available()) { + b = Serial.read(); + b = 0x20 ^ b; + } else { + // escape byte. next byte will be + _escape = true; + continue; + } + } + + if (_escape == true) { + b = 0x20 ^ b; + _escape = false; + } + + // checksum includes all bytes starting with api id + if (_pos >= API_ID_INDEX) { + _checksumTotal+= b; + } + + switch(_pos) { + case 0: + if (b == START_BYTE) { + _pos++; + } + + break; + case 1: + // length msb + _response.setMsbLength(b); + _pos++; + + break; + case 2: + // length lsb + _response.setLsbLength(b); + _pos++; + + break; + case 3: + _response.setApiId(b); + _pos++; + + break; + default: + // starts at fifth byte + + if (_pos > MAX_FRAME_DATA_SIZE) { + // exceed max size. should never occur + _response.setErrorCode(PACKET_EXCEEDS_BYTE_ARRAY_LENGTH); + return; + } + + // check if we're at the end of the packet + // packet length does not include start, length, or checksum bytes, so add 3 + if (_pos == (_response.getPacketLength() + 3)) { + // verify checksum + + //std::cout << "read checksum " << static_cast<unsigned int>(b) << " at pos " << static_cast<unsigned int>(_pos) << std::endl; + + if ((_checksumTotal & 0xff) == 0xff) { + _response.setChecksum(b); + _response.setAvailable(true); + + _response.setErrorCode(NO_ERROR); + } else { + // checksum failed + _response.setErrorCode(CHECKSUM_FAILURE); + } + + // minus 4 because we start after start,msb,lsb,api and up to but not including checksum + // e.g. if frame was one byte, _pos=4 would be the byte, pos=5 is the checksum, where end stop reading + _response.setFrameLength(_pos - 4); + + // reset state vars + _pos = 0; + + _checksumTotal = 0; + + return; + } else { + // add to packet array, starting with the fourth byte of the apiFrame + _response.getFrameData()[_pos - 4] = b; + _pos++; + } + } + } +} + +// it's peanut butter jelly time!! + +XBeeRequest::XBeeRequest(uint8_t apiId, uint8_t frameId) { + _apiId = apiId; + _frameId = frameId; +} + +void XBeeRequest::setFrameId(uint8_t frameId) { + _frameId = frameId; +} + +uint8_t XBeeRequest::getFrameId() { + return _frameId; +} + +uint8_t XBeeRequest::getApiId() { + return _apiId; +} + +void XBeeRequest::setApiId(uint8_t apiId) { + _apiId = apiId; +} + +//void XBeeRequest::reset() { +// _frameId = DEFAULT_FRAME_ID; +//} + +//uint8_t XBeeRequest::getPayloadOffset() { +// return _payloadOffset; +//} +// +//uint8_t XBeeRequest::setPayloadOffset(uint8_t payloadOffset) { +// _payloadOffset = payloadOffset; +//} + + +PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength) : XBeeRequest(apiId, frameId) { + _payloadPtr = payload; + _payloadLength = payloadLength; +} + +uint8_t* PayloadRequest::getPayload() { + return _payloadPtr; +} + +void PayloadRequest::setPayload(uint8_t* payload) { + _payloadPtr = payload; +} + +uint8_t PayloadRequest::getPayloadLength() { + return _payloadLength; +} + +void PayloadRequest::setPayloadLength(uint8_t payloadLength) { + _payloadLength = payloadLength; +} + + +XBeeAddress::XBeeAddress() { + +} + +XBeeAddress64::XBeeAddress64() : XBeeAddress() { + +} + +XBeeAddress64::XBeeAddress64(uint32_t msb, uint32_t lsb) : XBeeAddress() { + _msb = msb; + _lsb = lsb; +} + +uint32_t XBeeAddress64::getMsb() { + return _msb; +} + +void XBeeAddress64::setMsb(uint32_t msb) { + _msb = msb; +} + +uint32_t XBeeAddress64::getLsb() { + return _lsb; +} + +void XBeeAddress64::setLsb(uint32_t lsb) { + _lsb = lsb; +} + + +#ifdef SERIES_2 + +ZBTxRequest::ZBTxRequest() : PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, NULL, 0) { + +} + +ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId): PayloadRequest(ZB_TX_REQUEST, frameId, data, dataLength) { + _addr64 = addr64; + _addr16 = addr16; + _broadcastRadius = broadcastRadius; + _option = option; +} + +ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) { + _addr64 = addr64; + _addr16 = ZB_BROADCAST_ADDRESS; + _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS; + _option = ZB_TX_UNICAST; +} + +uint8_t ZBTxRequest::getFrameData(uint8_t pos) { + if (pos == 0) { + return (_addr64.getMsb() >> 24) & 0xff; + } else if (pos == 1) { + return (_addr64.getMsb() >> 16) & 0xff; + } else if (pos == 2) { + return (_addr64.getMsb() >> 8) & 0xff; + } else if (pos == 3) { + return _addr64.getMsb() & 0xff; + } else if (pos == 4) { + return (_addr64.getLsb() >> 24) & 0xff; + } else if (pos == 5) { + return (_addr64.getLsb() >> 16) & 0xff; + } else if (pos == 6) { + return (_addr64.getLsb() >> 8) & 0xff; + } else if (pos == 7) { + return _addr64.getLsb() & 0xff; + } else if (pos == 8) { + return (_addr16 >> 8) & 0xff; + } else if (pos == 9) { + return _addr16 & 0xff; + } else if (pos == 10) { + return _broadcastRadius; + } else if (pos == 11) { + return _option; + } else { + return getPayload()[pos - ZB_TX_API_LENGTH]; + } +} + +uint8_t ZBTxRequest::getFrameDataLength() { + return ZB_TX_API_LENGTH + getPayloadLength(); +} + +XBeeAddress64& ZBTxRequest::getAddress64() { + return _addr64; +} + +uint16_t ZBTxRequest::getAddress16() { + return _addr16; +} + +uint8_t ZBTxRequest::getBroadcastRadius() { + return _broadcastRadius; +} + +uint8_t ZBTxRequest::getOption() { + return _option; +} + +void ZBTxRequest::setAddress64(XBeeAddress64& addr64) { + _addr64 = addr64; +} + +void ZBTxRequest::setAddress16(uint16_t addr16) { + _addr16 = addr16; +} + +void ZBTxRequest::setBroadcastRadius(uint8_t broadcastRadius) { + _broadcastRadius = broadcastRadius; +} + +void ZBTxRequest::setOption(uint8_t option) { + _option = option; +} + +#endif + +#ifdef SERIES_1 + +Tx16Request::Tx16Request() : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, NULL, 0) { + +} + +Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) { + _addr16 = addr16; + _option = option; +} + +Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) { + _addr16 = addr16; + _option = ACK_OPTION; +} + +uint8_t Tx16Request::getFrameData(uint8_t pos) { + + if (pos == 0) { + return (_addr16 >> 8) & 0xff; + } else if (pos == 1) { + return _addr16 & 0xff; + } else if (pos == 2) { + return _option; + } else { + return getPayload()[pos - TX_16_API_LENGTH]; + } +} + +uint8_t Tx16Request::getFrameDataLength() { + return TX_16_API_LENGTH + getPayloadLength(); +} + +uint16_t Tx16Request::getAddress16() { + return _addr16; +} + +void Tx16Request::setAddress16(uint16_t addr16) { + _addr16 = addr16; +} + +uint8_t Tx16Request::getOption() { + return _option; +} + +void Tx16Request::setOption(uint8_t option) { + _option = option; +} + +Tx64Request::Tx64Request() : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, NULL, 0) { + +} + +Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) { + _addr64 = addr64; + _option = option; +} + +Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) { + _addr64 = addr64; + _option = ACK_OPTION; +} + +uint8_t Tx64Request::getFrameData(uint8_t pos) { + + if (pos == 0) { + return (_addr64.getMsb() >> 24) & 0xff; + } else if (pos == 1) { + return (_addr64.getMsb() >> 16) & 0xff; + } else if (pos == 2) { + return (_addr64.getMsb() >> 8) & 0xff; + } else if (pos == 3) { + return _addr64.getMsb() & 0xff; + } else if (pos == 4) { + return (_addr64.getLsb() >> 24) & 0xff; + } else if (pos == 5) { + return (_addr64.getLsb() >> 16) & 0xff; + } else if (pos == 6) { + return(_addr64.getLsb() >> 8) & 0xff; + } else if (pos == 7) { + return _addr64.getLsb() & 0xff; + } else if (pos == 8) { + return _option; + } else { + return getPayload()[pos - TX_64_API_LENGTH]; + } +} + +uint8_t Tx64Request::getFrameDataLength() { + return TX_64_API_LENGTH + getPayloadLength(); +} + +XBeeAddress64& Tx64Request::getAddress64() { + return _addr64; +} + +void Tx64Request::setAddress64(XBeeAddress64& addr64) { + _addr64 = addr64; +} + +uint8_t Tx64Request::getOption() { + return _option; +} + +void Tx64Request::setOption(uint8_t option) { + _option = option; +} + +#endif + +AtCommandRequest::AtCommandRequest() : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) { + _command = NULL; + clearCommandValue(); +} + +AtCommandRequest::AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) { + _command = command; + _commandValue = commandValue; + _commandValueLength = commandValueLength; +} + +AtCommandRequest::AtCommandRequest(uint8_t *command) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) { + _command = command; + clearCommandValue(); +} + +uint8_t* AtCommandRequest::getCommand() { + return _command; +} + +uint8_t* AtCommandRequest::getCommandValue() { + return _commandValue; +} + +uint8_t AtCommandRequest::getCommandValueLength() { + return _commandValueLength; +} + +void AtCommandRequest::setCommand(uint8_t* command) { + _command = command; +} + +void AtCommandRequest::setCommandValue(uint8_t* value) { + _commandValue = value; +} + +void AtCommandRequest::setCommandValueLength(uint8_t length) { + _commandValueLength = length; +} + +uint8_t AtCommandRequest::getFrameData(uint8_t pos) { + + if (pos == 0) { + return _command[0]; + } else if (pos == 1) { + return _command[1]; + } else { + return _commandValue[pos - AT_COMMAND_API_LENGTH]; + } +} + +void AtCommandRequest::clearCommandValue() { + _commandValue = NULL; + _commandValueLength = 0; +} + +//void AtCommandRequest::reset() { +// XBeeRequest::reset(); +//} + +uint8_t AtCommandRequest::getFrameDataLength() { + // command is 2 byte + length of value + return AT_COMMAND_API_LENGTH + _commandValueLength; +} + +XBeeAddress64 RemoteAtCommandRequest::broadcastAddress64 = XBeeAddress64(0x0, BROADCAST_ADDRESS); + +RemoteAtCommandRequest::RemoteAtCommandRequest() : AtCommandRequest(NULL, NULL, 0) { + _remoteAddress16 = 0; + _applyChanges = false; + setApiId(REMOTE_AT_REQUEST); +} + +RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) { + _remoteAddress64 = broadcastAddress64; + _remoteAddress16 = remoteAddress16; + _applyChanges = true; + setApiId(REMOTE_AT_REQUEST); +} + +RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command) : AtCommandRequest(command, NULL, 0) { + _remoteAddress64 = broadcastAddress64; + _remoteAddress16 = remoteAddress16; + _applyChanges = false; + setApiId(REMOTE_AT_REQUEST); +} + +RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) { + _remoteAddress64 = remoteAddress64; + // don't worry.. works for series 1 too! + _remoteAddress16 = ZB_BROADCAST_ADDRESS; + _applyChanges = true; + setApiId(REMOTE_AT_REQUEST); +} + +RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command) : AtCommandRequest(command, NULL, 0) { + _remoteAddress64 = remoteAddress64; + _remoteAddress16 = ZB_BROADCAST_ADDRESS; + _applyChanges = false; + setApiId(REMOTE_AT_REQUEST); +} + +uint16_t RemoteAtCommandRequest::getRemoteAddress16() { + return _remoteAddress16; +} + +void RemoteAtCommandRequest::setRemoteAddress16(uint16_t remoteAddress16) { + _remoteAddress16 = remoteAddress16; +} + +XBeeAddress64& RemoteAtCommandRequest::getRemoteAddress64() { + return _remoteAddress64; +} + +void RemoteAtCommandRequest::setRemoteAddress64(XBeeAddress64 &remoteAddress64) { + _remoteAddress64 = remoteAddress64; +} + +bool RemoteAtCommandRequest::getApplyChanges() { + return _applyChanges; +} + +void RemoteAtCommandRequest::setApplyChanges(bool applyChanges) { + _applyChanges = applyChanges; +} + + +uint8_t RemoteAtCommandRequest::getFrameData(uint8_t pos) { + if (pos == 0) { + return (_remoteAddress64.getMsb() >> 24) & 0xff; + } else if (pos == 1) { + return (_remoteAddress64.getMsb() >> 16) & 0xff; + } else if (pos == 2) { + return (_remoteAddress64.getMsb() >> 8) & 0xff; + } else if (pos == 3) { + return _remoteAddress64.getMsb() & 0xff; + } else if (pos == 4) { + return (_remoteAddress64.getLsb() >> 24) & 0xff; + } else if (pos == 5) { + return (_remoteAddress64.getLsb() >> 16) & 0xff; + } else if (pos == 6) { + return(_remoteAddress64.getLsb() >> 8) & 0xff; + } else if (pos == 7) { + return _remoteAddress64.getLsb() & 0xff; + } else if (pos == 8) { + return (_remoteAddress16 >> 8) & 0xff; + } else if (pos == 9) { + return _remoteAddress16 & 0xff; + } else if (pos == 10) { + return _applyChanges ? 2: 0; + } else if (pos == 11) { + return getCommand()[0]; + } else if (pos == 12) { + return getCommand()[1]; + } else { + return getCommandValue()[pos - REMOTE_AT_COMMAND_API_LENGTH]; + } +} + +uint8_t RemoteAtCommandRequest::getFrameDataLength() { + return REMOTE_AT_COMMAND_API_LENGTH + getCommandValueLength(); +} + + +// TODO +//GenericRequest::GenericRequest(uint8_t* frame, uint8_t len, uint8_t apiId): XBeeRequest(apiId, *(frame), len) { +// _frame = frame; +//} + +void XBee::send(XBeeRequest &request) { + // the new new deal + + sendByte(START_BYTE, false); + + // send length + uint8_t msbLen = ((request.getFrameDataLength() + 2) >> 8) & 0xff; + uint8_t lsbLen = (request.getFrameDataLength() + 2) & 0xff; + + sendByte(msbLen, true); + sendByte(lsbLen, true); + + // api id + sendByte(request.getApiId(), true); + sendByte(request.getFrameId(), true); + + uint8_t checksum = 0; + + // compute checksum, start at api id + checksum+= request.getApiId(); + checksum+= request.getFrameId(); + + //std::cout << "frame length is " << static_cast<unsigned int>(request.getFrameDataLength()) << std::endl; + + for (int i = 0; i < request.getFrameDataLength(); i++) { +// std::cout << "sending byte [" << static_cast<unsigned int>(i) << "] " << std::endl; + sendByte(request.getFrameData(i), true); + checksum+= request.getFrameData(i); + } + + // perform 2s complement + checksum = 0xff - checksum; + +// std::cout << "checksum is " << static_cast<unsigned int>(checksum) << std::endl; + + // send checksum + sendByte(checksum, true); + + // send packet + //Serial.flush(); +} + +void XBee::sendByte(uint8_t b, bool escape) { + + if (escape && (b == START_BYTE || b == ESCAPE || b == XON || b == XOFF)) { +// std::cout << "escaping byte [" << toHexString(b) << "] " << std::endl; + Serial.print(ESCAPE, BYTE); + Serial.print(b ^ 0x20, BYTE); + } else { + Serial.print(b, BYTE); + } +} + diff --git a/src/XBee/XBee.h b/src/XBee/XBee.h new file mode 100755 index 0000000..1874ec3 --- /dev/null +++ b/src/XBee/XBee.h @@ -0,0 +1,964 @@ +/** + * Copyright (c) 2009 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-Arduino. + * + * XBee-Arduino is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-Arduino 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 XBee-Arduino. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef XBee_h +#define XBee_h + +#include <libmary.h> +#include <inttypes.h> + +#ifdef __cplusplus + extern "C" { +#endif + + + + + +//#define SERIES_1 +#define SERIES_2 + +// set to ATAP value of XBee. AP=2 is recommended +#define ATAP 2 + +#define START_BYTE 0x7e +#define ESCAPE 0x7d +#define XON 0x11 +#define XOFF 0x13 + + +#ifndef NULL + #define NULL 0 +#endif +// This value determines the size of the byte array for receiving RX packets +// Most users won't be dealing with packets this large so you can adjust this +// value to reduce memory consumption. But, remember that +// if a RX packet exceeds this size, it cannot be parsed! + +// This value is determined by the largest packet size (100 byte payload + 64-bit address + option byte and rssi byte) of a series 1 radio +#define MAX_FRAME_DATA_SIZE 110 + +#define BROADCAST_ADDRESS 0xffff +#define ZB_BROADCAST_ADDRESS 0xfffe + +// the non-variable length of the frame data (not including frame id or api id or variable data size (e.g. payload, at command set value) +#define ZB_TX_API_LENGTH 12 +#define TX_16_API_LENGTH 3 +#define TX_64_API_LENGTH 9 +#define AT_COMMAND_API_LENGTH 2 +#define REMOTE_AT_COMMAND_API_LENGTH 13 +// start/length(2)/api/frameid/checksum bytes +#define PACKET_OVERHEAD_LENGTH 6 +// api is always the third byte in packet +#define API_ID_INDEX 3 + +// frame position of rssi byte +#define RX_16_RSSI_OFFSET 2 +#define RX_64_RSSI_OFFSET 8 + +#define DEFAULT_FRAME_ID 1 +#define NO_RESPONSE_FRAME_ID 0 + +// TODO put in tx16 class +#define ACK_OPTION 0 +#define DISABLE_ACK_OPTION 1 +#define BROADCAST_OPTION 4 + +// RX options +#define ZB_PACKET_ACKNOWLEDGED 0x01 +#define ZB_BROADCAST_PACKET 0x02 + +// not everything is implemented! +/** + * Api Id constants + */ +#define TX_64_REQUEST 0x0 +#define TX_16_REQUEST 0x1 +#define AT_COMMAND_REQUEST 0x08 +#define AT_COMMAND_QUEUE_REQUEST 0x09 +#define REMOTE_AT_REQUEST 0x17 +#define ZB_TX_REQUEST 0x10 +#define ZB_EXPLICIT_TX_REQUEST 0x11 +#define RX_64_RESPONSE 0x80 +#define RX_16_RESPONSE 0x81 +#define RX_64_IO_RESPONSE 0x82 +#define RX_16_IO_RESPONSE 0x83 +#define AT_RESPONSE 0x88 +#define TX_STATUS_RESPONSE 0x89 +#define MODEM_STATUS_RESPONSE 0x8a +#define ZB_RX_RESPONSE 0x90 +#define ZB_EXPLICIT_RX_RESPONSE 0x91 +#define ZB_TX_STATUS_RESPONSE 0x8b +#define ZB_IO_SAMPLE_RESPONSE 0x92 +#define ZB_IO_NODE_IDENTIFIER_RESPONSE 0x95 +#define AT_COMMAND_RESPONSE 0x88 +#define REMOTE_AT_COMMAND_RESPONSE 0x97 + + +/** + * TX STATUS constants + */ +#define SUCCESS 0x0 +#define CCA_FAILURE 0x2 +#define INVALID_DESTINATION_ENDPOINT_SUCCESS 0x15 +#define NETWORK_ACK_FAILURE 0x21 +#define NOT_JOINED_TO_NETWORK 0x22 +#define SELF_ADDRESSED 0x23 +#define ADDRESS_NOT_FOUND 0x24 +#define ROUTE_NOT_FOUND 0x25 +#define PAYLOAD_TOO_LARGE 0x74 + +// modem status +#define HARDWARE_RESET 0 +#define WATCHDOG_TIMER_RESET 1 +#define ASSOCIATED 2 +#define DISASSOCIATED 3 +#define SYNCHRONIZATION_LOST 4 +#define COORDINATOR_REALIGNMENT 5 +#define COORDINATOR_STARTED 6 + +#define ZB_BROADCAST_RADIUS_MAX_HOPS 0 + +#define ZB_TX_UNICAST 0 +#define ZB_TX_BROADCAST 8 + +#define AT_OK 0 +#define AT_ERROR 1 +#define AT_INVALID_COMMAND 2 +#define AT_INVALID_PARAMETER 3 +#define AT_NO_RESPONSE 4 + +#define NO_ERROR 0 +#define CHECKSUM_FAILURE 1 +#define PACKET_EXCEEDS_BYTE_ARRAY_LENGTH 2 +#define UNEXPECTED_START_BYTE 3 + +/** + * The super class of all XBee responses (RX packets) + * Users should never attempt to create an instance of this class; instead + * create an instance of a subclass + * It is recommend to reuse subclasses to conserve memory + */ +class XBeeResponse { +public: + //static const int MODEM_STATUS = 0x8a; + /** + * Default constructor + */ + XBeeResponse(); + /** + * Returns Api Id of the response + */ + uint8_t getApiId(); + void setApiId(uint8_t apiId); + /** + * Returns the MSB length of the packet + */ + uint8_t getMsbLength(); + void setMsbLength(uint8_t msbLength); + /** + * Returns the LSB length of the packet + */ + uint8_t getLsbLength(); + void setLsbLength(uint8_t lsbLength); + /** + * Returns the packet checksum + */ + uint8_t getChecksum(); + void setChecksum(uint8_t checksum); + /** + * Returns the length of the frame data: all bytes after the api id, and prior to the checksum + * Note up to release 0.1.2, this was incorrectly including the checksum in the length. + */ + uint8_t getFrameDataLength(); + void setFrameData(uint8_t* frameDataPtr); + /** + * Returns the buffer that contains the response. + * Starts with byte that follows API ID and includes all bytes prior to the checksum + * Length is specified by getFrameDataLength() + * Note: Unlike Digi's definition of the frame data, this does not start with the API ID.. + * The reason for this is all responses include an API ID, whereas my frame data + * includes only the API specific data. + */ + uint8_t* getFrameData(); + + void setFrameLength(uint8_t frameLength); + // to support future 65535 byte packets I guess + /** + * Returns the length of the packet + */ + uint16_t getPacketLength(); + /** + * Resets the response to default values + */ + void reset(); + /** + * Initializes the response + */ + void init(); +#ifdef SERIES_2 + /** + * Call with instance of ZBTxStatusResponse class only if getApiId() == ZB_TX_STATUS_RESPONSE + * to populate response + */ + void getZBTxStatusResponse(XBeeResponse &response); + /** + * Call with instance of ZBRxResponse class only if getApiId() == ZB_RX_RESPONSE + * to populate response + */ + void getZBRxResponse(XBeeResponse &response); + /** + * Call with instance of ZBRxIoSampleResponse class only if getApiId() == ZB_IO_SAMPLE_RESPONSE + * to populate response + */ + void getZBRxIoSampleResponse(XBeeResponse &response); +#endif +#ifdef SERIES_1 + /** + * Call with instance of TxStatusResponse only if getApiId() == TX_STATUS_RESPONSE + */ + void getTxStatusResponse(XBeeResponse &response); + /** + * Call with instance of Rx16Response only if getApiId() == RX_16_RESPONSE + */ + void getRx16Response(XBeeResponse &response); + /** + * Call with instance of Rx64Response only if getApiId() == RX_64_RESPONSE + */ + void getRx64Response(XBeeResponse &response); + /** + * Call with instance of Rx16IoSampleResponse only if getApiId() == RX_16_IO_RESPONSE + */ + void getRx16IoSampleResponse(XBeeResponse &response); + /** + * Call with instance of Rx64IoSampleResponse only if getApiId() == RX_64_IO_RESPONSE + */ + void getRx64IoSampleResponse(XBeeResponse &response); +#endif + /** + * Call with instance of AtCommandResponse only if getApiId() == AT_COMMAND_RESPONSE + */ + void getAtCommandResponse(XBeeResponse &responses); + /** + * Call with instance of RemoteAtCommandResponse only if getApiId() == REMOTE_AT_COMMAND_RESPONSE + */ + void getRemoteAtCommandResponse(XBeeResponse &response); + /** + * Call with instance of ModemStatusResponse only if getApiId() == MODEM_STATUS_RESPONSE + */ + void getModemStatusResponse(XBeeResponse &response); + /** + * Returns true if the response has been successfully parsed and is complete and ready for use + */ + bool isAvailable(); + void setAvailable(bool complete); + /** + * Returns true if the response contains errors + */ + bool isError(); + /** + * Returns an error code, or zero, if successful. + * Error codes include: CHECKSUM_FAILURE, PACKET_EXCEEDS_BYTE_ARRAY_LENGTH, UNEXPECTED_START_BYTE + */ + uint8_t getErrorCode(); + void setErrorCode(uint8_t errorCode); +protected: + // pointer to frameData + uint8_t* _frameDataPtr; +private: + void setCommon(XBeeResponse &target); + uint8_t _apiId; + uint8_t _msbLength; + uint8_t _lsbLength; + uint8_t _checksum; + uint8_t _frameLength; + bool _complete; + uint8_t _errorCode; +}; + +class XBeeAddress { +public: + XBeeAddress(); +}; + +/** + * Represents a 64-bit XBee Address + */ +class XBeeAddress64 : public XBeeAddress { +public: + XBeeAddress64(uint32_t msb, uint32_t lsb); + XBeeAddress64(); + uint32_t getMsb(); + uint32_t getLsb(); + void setMsb(uint32_t msb); + void setLsb(uint32_t lsb); +private: + uint32_t _msb; + uint32_t _lsb; +}; + +//class XBeeAddress16 : public XBeeAddress { +//public: +// XBeeAddress16(uint16_t addr); +// XBeeAddress16(); +// uint16_t getAddress(); +// void setAddress(uint16_t addr); +//private: +// uint16_t _addr; +//}; + +/** + * This class is extended by all Responses that include a frame id + */ +class FrameIdResponse : public XBeeResponse { +public: + FrameIdResponse(); + uint8_t getFrameId(); +private: + uint8_t _frameId; +}; + +/** + * Common functionality for both Series 1 and 2 data RX data packets + */ +class RxDataResponse : public XBeeResponse { +public: + RxDataResponse(); + /** + * Returns the specified index of the payload. The index may be 0 to getDataLength() - 1 + * This method is deprecated; use uint8_t* getData() + */ + uint8_t getData(int index); + /** + * Returns the payload array. This may be accessed from index 0 to getDataLength() - 1 + */ + uint8_t* getData(); + /** + * Returns the length of the payload + */ + virtual uint8_t getDataLength() = 0; + /** + * Returns the position in the frame data where the data begins + */ + virtual uint8_t getDataOffset() = 0; +}; + +// getResponse to return the proper subclass: +// we maintain a pointer to each type of response, when a response is parsed, it is allocated only if NULL +// can we allocate an object in a function? + +#ifdef SERIES_2 +/** + * Represents a Series 2 TX status packet + */ +class ZBTxStatusResponse : public FrameIdResponse { + public: + ZBTxStatusResponse(); + uint16_t getRemoteAddress(); + uint8_t getTxRetryCount(); + uint8_t getDeliveryStatus(); + uint8_t getDiscoveryStatus(); + bool isSuccess(); +}; + +/** + * Represents a Series 2 RX packet + */ +class ZBRxResponse : public RxDataResponse { +public: + ZBRxResponse(); + XBeeAddress64& getRemoteAddress64(); + uint16_t getRemoteAddress16(); + uint8_t getOption(); + uint8_t getDataLength(); + // frame position where data starts + uint8_t getDataOffset(); +private: + XBeeAddress64 _remoteAddress64; +}; + +/** + * Represents a Series 2 RX I/O Sample packet + */ +class ZBRxIoSampleResponse : public ZBRxResponse { +public: + ZBRxIoSampleResponse(); + bool containsAnalog(); + bool containsDigital(); + /** + * Returns true if the pin is enabled + */ + bool isAnalogEnabled(uint8_t pin); + /** + * Returns true if the pin is enabled + */ + bool isDigitalEnabled(uint8_t pin); + /** + * Returns the 10-bit analog reading of the specified pin. + * Valid pins include ADC:xxx. + */ + uint16_t getAnalog(uint8_t pin); + /** + * Returns true if the specified pin is high/on. + * Valid pins include DIO:xxx. + */ + bool isDigitalOn(uint8_t pin); + uint8_t getDigitalMaskMsb(); + uint8_t getDigitalMaskLsb(); + uint8_t getAnalogMask(); +}; + +#endif + +#ifdef SERIES_1 +/** + * Represents a Series 1 TX Status packet + */ +class TxStatusResponse : public FrameIdResponse { + public: + TxStatusResponse(); + uint8_t getStatus(); + bool isSuccess(); +}; + +/** + * Represents a Series 1 RX packet + */ +class RxResponse : public RxDataResponse { +public: + RxResponse(); + // remember rssi is negative but this is unsigned byte so it's up to you to convert + uint8_t getRssi(); + uint8_t getOption(); + bool isAddressBroadcast(); + bool isPanBroadcast(); + uint8_t getDataLength(); + uint8_t getDataOffset(); + virtual uint8_t getRssiOffset() = 0; +}; + +/** + * Represents a Series 1 16-bit address RX packet + */ +class Rx16Response : public RxResponse { +public: + Rx16Response(); + uint8_t getRssiOffset(); + uint16_t getRemoteAddress16(); +protected: + uint16_t _remoteAddress; +}; + +/** + * Represents a Series 1 64-bit address RX packet + */ +class Rx64Response : public RxResponse { +public: + Rx64Response(); + uint8_t getRssiOffset(); + XBeeAddress64& getRemoteAddress64(); +private: + XBeeAddress64 _remoteAddress; +}; + +/** + * Represents a Series 1 RX I/O Sample packet + */ +class RxIoSampleBaseResponse : public RxResponse { + public: + RxIoSampleBaseResponse(); + /** + * Returns the number of samples in this packet + */ + uint8_t getSampleSize(); + bool containsAnalog(); + bool containsDigital(); + /** + * Returns true if the specified analog pin is enabled + */ + bool isAnalogEnabled(uint8_t pin); + /** + * Returns true if the specified digital pin is enabled + */ + bool isDigitalEnabled(uint8_t pin); + /** + * Returns the 10-bit analog reading of the specified pin. + * Valid pins include ADC:0-5. Sample index starts at 0 + */ + uint16_t getAnalog(uint8_t pin, uint8_t sample); + /** + * Returns true if the specified pin is high/on. + * Valid pins include DIO:0-8. Sample index starts at 0 + */ + bool isDigitalOn(uint8_t pin, uint8_t sample); + uint8_t getSampleOffset(); + private: +}; + +class Rx16IoSampleResponse : public RxIoSampleBaseResponse { +public: + Rx16IoSampleResponse(); + uint16_t getRemoteAddress16(); + uint8_t getRssiOffset(); + +}; + +class Rx64IoSampleResponse : public RxIoSampleBaseResponse { +public: + Rx64IoSampleResponse(); + XBeeAddress64& getRemoteAddress64(); + uint8_t getRssiOffset(); +private: + XBeeAddress64 _remoteAddress; +}; + +#endif + +/** + * Represents a Modem Status RX packet + */ +class ModemStatusResponse : public XBeeResponse { +public: + ModemStatusResponse(); + uint8_t getStatus(); +}; + +/** + * Represents an AT Command RX packet + */ +class AtCommandResponse : public FrameIdResponse { + public: + AtCommandResponse(); + /** + * Returns an array containing the two character command + */ + uint8_t* getCommand(); + /** + * Returns the command status code. + * Zero represents a successful command + */ + uint8_t getStatus(); + /** + * Returns an array containing the command value. + * This is only applicable to query commands. + */ + uint8_t* getValue(); + /** + * Returns the length of the command value array. + */ + uint8_t getValueLength(); + /** + * Returns true if status equals AT_OK + */ + bool isOk(); +}; + +/** + * Represents a Remote AT Command RX packet + */ +class RemoteAtCommandResponse : public AtCommandResponse { + public: + RemoteAtCommandResponse(); + /** + * Returns an array containing the two character command + */ + uint8_t* getCommand(); + /** + * Returns the command status code. + * Zero represents a successful command + */ + uint8_t getStatus(); + /** + * Returns an array containing the command value. + * This is only applicable to query commands. + */ + uint8_t* getValue(); + /** + * Returns the length of the command value array. + */ + uint8_t getValueLength(); + /** + * Returns the 16-bit address of the remote radio + */ + uint16_t getRemoteAddress16(); + /** + * Returns the 64-bit address of the remote radio + */ + XBeeAddress64& getRemoteAddress64(); + /** + * Returns true if command was successful + */ + bool isOk(); + private: + XBeeAddress64 _remoteAddress64; +}; + + +/** + * Super class of all XBee requests (TX packets) + * Users should never create an instance of this class; instead use an subclass of this class + * It is recommended to reuse Subclasses of the class to conserve memory + * <p/> + * This class allocates a buffer to + */ +class XBeeRequest { +public: + /** + * Constructor + * TODO make protected + */ + XBeeRequest(uint8_t apiId, uint8_t frameId); + /** + * Sets the frame id. Must be between 1 and 255 inclusive to get a TX status response. + */ + void setFrameId(uint8_t frameId); + /** + * Returns the frame id + */ + uint8_t getFrameId(); + /** + * Returns the API id + */ + uint8_t getApiId(); + // setting = 0 makes this a pure virtual function, meaning the subclass must implement, like abstract in java + /** + * Starting after the frame id (pos = 0) and up to but not including the checksum + * Note: Unlike Digi's definition of the frame data, this does not start with the API ID. + * The reason for this is the API ID and Frame ID are common to all requests, whereas my definition of + * frame data is only the API specific data. + */ + virtual uint8_t getFrameData(uint8_t pos) = 0; + /** + * Returns the size of the api frame (not including frame id or api id or checksum). + */ + virtual uint8_t getFrameDataLength() = 0; + //void reset(); +protected: + void setApiId(uint8_t apiId); +private: + uint8_t _apiId; + uint8_t _frameId; +}; + +// TODO add reset/clear method since responses are often reused +/** + * Primary interface for communicating with an XBee Radio. + * This class provides methods for sending and receiving packets with an XBee radio via the serial port. + * The XBee radio must be configured in API (packet) mode (AP=2) + * in order to use this software. + * <p/> + * Since this code is designed to run on a microcontroller, with only one thread, you are responsible for reading the + * data off the serial buffer in a timely manner. This involves a call to a variant of readPacket(...). + * If your serial port is receiving data faster than you are reading, you can expect to lose packets. + * Arduino only has a 128 byte serial buffer so it can easily overflow if two or more packets arrive + * without a call to readPacket(...) + * <p/> + * In order to conserve resources, this class only supports storing one response packet in memory at a time. + * This means that you must fully consume the packet prior to calling readPacket(...), because calling + * readPacket(...) overwrites the previous response. + * <p/> + * This class creates an array of size MAX_FRAME_DATA_SIZE for storing the response packet. You may want + * to adjust this value to conserve memory. + * + * \author Andrew Rapp + */ +class XBee { +public: + XBee(); + // for eclipse dev only + //void setSerial(HardwareSerial serial); + /** + * Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty. + * You may call <i>xbee</i>.getResponse().isAvailable() after calling this method to determine if + * a packet is ready, or <i>xbee</i>.getResponse().isError() to determine if + * a error occurred. + * <p/> + * This method should always return quickly since it does not wait for serial data to arrive. + * You will want to use this method if you are doing other timely stuff in your loop, where + * a delay would cause problems. + * NOTE: calling this method resets the current response, so make sure you first consume the + * current response + */ + void readPacket(); + /** + * Waits a maximum of <i>timeout</i> milliseconds for a response packet before timing out; returns true if packet is read. + * Returns false if timeout or error occurs. + */ + bool readPacket(int timeout); + /** + * Reads until a packet is received or an error occurs. + * Caution: use this carefully since if you don't get a response, your Arduino code will hang on this + * call forever!! often it's better to use a timeout: readPacket(int) + */ + void readPacketUntilAvailable(); + /** + * Starts the serial connection at the supplied baud rate + */ + void begin(int baud); + void getResponse(XBeeResponse &response); + /** + * Returns a reference to the current response + * Note: once readPacket is called again this response will be overwritten! + */ + XBeeResponse& getResponse(); + /** + * Sends a XBeeRequest (TX packet) out the serial port + */ + void send(XBeeRequest &request); + //uint8_t sendAndWaitForResponse(XBeeRequest &request, int timeout); + /** + * Returns a sequential frame id between 1 and 255 + */ + uint8_t getNextFrameId(); +private: + void sendByte(uint8_t b, bool escape); + void resetResponse(); + XBeeResponse _response; + bool _escape; + // current packet position for response. just a state variable for packet parsing and has no relevance for the response otherwise + uint8_t _pos; + // last byte read + uint8_t b; + uint8_t _checksumTotal; + uint8_t _nextFrameId; + // buffer for incoming RX packets. holds only the api specific frame data, starting after the api id byte and prior to checksum + uint8_t _responseFrameData[MAX_FRAME_DATA_SIZE]; +}; + +/** + * All TX packets that support payloads extend this class + */ +class PayloadRequest : public XBeeRequest { +public: + PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength); + /** + * Returns the payload of the packet, if not null + */ + uint8_t* getPayload(); + /** + * Sets the payload array + */ + void setPayload(uint8_t* payloadPtr); + /** + * Returns the length of the payload array, as specified by the user. + */ + uint8_t getPayloadLength(); + /** + * Sets the length of the payload to include in the request. For example if the payload array + * is 50 bytes and you only want the first 10 to be included in the packet, set the length to 10. + * Length must be <= to the array length. + */ + void setPayloadLength(uint8_t payloadLength); +private: + uint8_t* _payloadPtr; + uint8_t _payloadLength; +}; + +#ifdef SERIES_1 + +/** + * Represents a Series 1 TX packet that corresponds to Api Id: TX_16_REQUEST + * <p/> + * Be careful not to send a data array larger than the max packet size of your radio. + * This class does not perform any validation of packet size and there will be no indication + * if the packet is too large, other than you will not get a TX Status response. + * The datasheet says 100 bytes is the maximum, although that could change in future firmware. + */ +class Tx16Request : public PayloadRequest { +public: + Tx16Request(uint16_t addr16, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); + /** + * Creates a Unicast Tx16Request with the ACK option and DEFAULT_FRAME_ID + */ + Tx16Request(uint16_t addr16, uint8_t *payload, uint8_t payloadLength); + /** + * Creates a default instance of this class. At a minimum you must specify + * a payload, payload length and a destination address before sending this request. + */ + Tx16Request(); + uint16_t getAddress16(); + void setAddress16(uint16_t addr16); + uint8_t getOption(); + void setOption(uint8_t option); + uint8_t getFrameData(uint8_t pos); + uint8_t getFrameDataLength(); +protected: +private: + uint16_t _addr16; + uint8_t _option; +}; + +/** + * Represents a Series 1 TX packet that corresponds to Api Id: TX_64_REQUEST + * + * Be careful not to send a data array larger than the max packet size of your radio. + * This class does not perform any validation of packet size and there will be no indication + * if the packet is too large, other than you will not get a TX Status response. + * The datasheet says 100 bytes is the maximum, although that could change in future firmware. + */ +class Tx64Request : public PayloadRequest { +public: + Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); + /** + * Creates a unicast Tx64Request with the ACK option and DEFAULT_FRAME_ID + */ + Tx64Request(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength); + /** + * Creates a default instance of this class. At a minimum you must specify + * a payload, payload length and a destination address before sending this request. + */ + Tx64Request(); + XBeeAddress64& getAddress64(); + void setAddress64(XBeeAddress64& addr64); + // TODO move option to superclass + uint8_t getOption(); + void setOption(uint8_t option); + uint8_t getFrameData(uint8_t pos); + uint8_t getFrameDataLength(); +private: + XBeeAddress64 _addr64; + uint8_t _option; +}; + +#endif + + +#ifdef SERIES_2 + +/** + * Represents a Series 2 TX packet that corresponds to Api Id: ZB_TX_REQUEST + * + * Be careful not to send a data array larger than the max packet size of your radio. + * This class does not perform any validation of packet size and there will be no indication + * if the packet is too large, other than you will not get a TX Status response. + * The datasheet says 72 bytes is the maximum for ZNet firmware and ZB Pro firmware provides + * the ATNP command to get the max supported payload size. This command is useful since the + * maximum payload size varies according to certain settings, such as encryption. + * ZB Pro firmware provides a PAYLOAD_TOO_LARGE that is returned if payload size + * exceeds the maximum. + */ +class ZBTxRequest : public PayloadRequest { +public: + /** + * Creates a unicast ZBTxRequest with the ACK option and DEFAULT_FRAME_ID + */ + ZBTxRequest(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength); + ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId); + /** + * Creates a default instance of this class. At a minimum you must specify + * a payload, payload length and a destination address before sending this request. + */ + ZBTxRequest(); + XBeeAddress64& getAddress64(); + uint16_t getAddress16(); + uint8_t getBroadcastRadius(); + uint8_t getOption(); + void setAddress64(XBeeAddress64& addr64); + void setAddress16(uint16_t addr16); + void setBroadcastRadius(uint8_t broadcastRadius); + void setOption(uint8_t option); +protected: + // declare virtual functions + uint8_t getFrameData(uint8_t pos); + uint8_t getFrameDataLength(); +private: + XBeeAddress64 _addr64; + uint16_t _addr16; + uint8_t _broadcastRadius; + uint8_t _option; +}; + +#endif + +/** + * Represents an AT Command TX packet + * The command is used to configure the serially connected XBee radio + */ +class AtCommandRequest : public XBeeRequest { +public: + AtCommandRequest(); + AtCommandRequest(uint8_t *command); + AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); + uint8_t getFrameData(uint8_t pos); + uint8_t getFrameDataLength(); + uint8_t* getCommand(); + void setCommand(uint8_t* command); + uint8_t* getCommandValue(); + void setCommandValue(uint8_t* command); + uint8_t getCommandValueLength(); + void setCommandValueLength(uint8_t length); + /** + * Clears the optional commandValue and commandValueLength so that a query may be sent + */ + void clearCommandValue(); + //void reset(); +private: + uint8_t *_command; + uint8_t *_commandValue; + uint8_t _commandValueLength; +}; + +/** + * Represents an Remote AT Command TX packet + * The command is used to configure a remote XBee radio + */ +class RemoteAtCommandRequest : public AtCommandRequest { +public: + RemoteAtCommandRequest(); + /** + * Creates a RemoteAtCommandRequest with 16-bit address to set a command. + * 64-bit address defaults to broadcast and applyChanges is true. + */ + RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); + /** + * Creates a RemoteAtCommandRequest with 16-bit address to query a command. + * 64-bit address defaults to broadcast and applyChanges is true. + */ + RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command); + /** + * Creates a RemoteAtCommandRequest with 64-bit address to set a command. + * 16-bit address defaults to broadcast and applyChanges is true. + */ + RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength); + /** + * Creates a RemoteAtCommandRequest with 16-bit address to query a command. + * 16-bit address defaults to broadcast and applyChanges is true. + */ + RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command); + uint16_t getRemoteAddress16(); + void setRemoteAddress16(uint16_t remoteAddress16); + XBeeAddress64& getRemoteAddress64(); + void setRemoteAddress64(XBeeAddress64 &remoteAddress64); + bool getApplyChanges(); + void setApplyChanges(bool applyChanges); + uint8_t getFrameData(uint8_t pos); + uint8_t getFrameDataLength(); + static XBeeAddress64 broadcastAddress64; +// static uint16_t broadcast16Address; +private: + XBeeAddress64 _remoteAddress64; + uint16_t _remoteAddress16; + bool _applyChanges; +}; + +#ifdef __cplusplus + } +#endif + +#endif //XBee_h diff --git a/src/core/LPC11xx.h b/src/core/LPC11xx.h new file mode 100755 index 0000000..854f719 --- /dev/null +++ b/src/core/LPC11xx.h @@ -0,0 +1,559 @@ +/****************************************************************************
+ * $Id:: LPC11xx.h 3635 2010-06-02 00:31:46Z usb00423 $
+ * Project: NXP LPC11xx software example
+ *
+ * Description:
+ * CMSIS Cortex-M0 Core Peripheral Access Layer Header File for
+ * NXP LPC11xx Device Series
+ *
+ ****************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+****************************************************************************/
+#ifndef __LPC11xx_H__
+#define __LPC11xx_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** @addtogroup LPC11xx_Definitions LPC11xx Definitions
+ This file defines all structures and symbols for LPC11xx:
+ - Registers and bitfields
+ - peripheral base address
+ - peripheral ID
+ - PIO definitions
+ @{
+*/
+
+
+/******************************************************************************/
+/* Processor and Core Peripherals */
+/******************************************************************************/
+/** @addtogroup LPC11xx_CMSIS LPC11xx CMSIS Definitions
+ Configuration of the Cortex-M0 Processor and Core Peripherals
+ @{
+*/
+
+/*
+ * ==========================================================================
+ * ---------- Interrupt Number Definition -----------------------------------
+ * ==========================================================================
+ */
+
+typedef enum IRQn
+{
+/****** Cortex-M0 Processor Exceptions Numbers ***************************************************/
+ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
+ HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */
+ SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */
+ PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */
+ SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */
+
+/****** LPC11xx Specific Interrupt Numbers *******************************************************/
+ WAKEUP0_IRQn = 0, /*!< All I/O pins can be used as wakeup source. */
+ WAKEUP1_IRQn = 1, /*!< There are 13 pins in total for LPC11xx */
+ WAKEUP2_IRQn = 2,
+ WAKEUP3_IRQn = 3,
+ WAKEUP4_IRQn = 4,
+ WAKEUP5_IRQn = 5,
+ WAKEUP6_IRQn = 6,
+ WAKEUP7_IRQn = 7,
+ WAKEUP8_IRQn = 8,
+ WAKEUP9_IRQn = 9,
+ WAKEUP10_IRQn = 10,
+ WAKEUP11_IRQn = 11,
+ WAKEUP12_IRQn = 12,
+ CAN_IRQn = 13, /*!< CAN Interrupt */
+ SSP1_IRQn = 14, /*!< SSP1 Interrupt */
+ I2C_IRQn = 15, /*!< I2C Interrupt */
+ TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */
+ TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */
+ TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */
+ TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */
+ SSP0_IRQn = 20, /*!< SSP0 Interrupt */
+ UART_IRQn = 21, /*!< UART Interrupt */
+ ADC_IRQn = 24, /*!< A/D Converter Interrupt */
+ WDT_IRQn = 25, /*!< Watchdog timer Interrupt */
+ BOD_IRQn = 26, /*!< Brown Out Detect(BOD) Interrupt */
+ EINT3_IRQn = 28, /*!< External Interrupt 3 Interrupt */
+ EINT2_IRQn = 29, /*!< External Interrupt 2 Interrupt */
+ EINT1_IRQn = 30, /*!< External Interrupt 1 Interrupt */
+ EINT0_IRQn = 31, /*!< External Interrupt 0 Interrupt */
+} IRQn_Type;
+
+
+/*
+ * ==========================================================================
+ * ----------- Processor and Core Peripheral Section ------------------------
+ * ==========================================================================
+ */
+
+/* Configuration of the Cortex-M3 Processor and Core Peripherals */
+#define __MPU_PRESENT 0 /*!< MPU present or not */
+#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */
+#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
+
+/*@}*/ /* end of group LPC11xx_CMSIS */
+
+
+#include "core_cm0.h" /* Cortex-M0 processor and core peripherals */
+#include "system_LPC11xx.h" /* System Header */
+
+
+/******************************************************************************/
+/* Device Specific Peripheral Registers structures */
+/******************************************************************************/
+
+#if defined ( __CC_ARM )
+#pragma anon_unions
+#endif
+
+/*------------- System Control (SYSCON) --------------------------------------*/
+/** @addtogroup LPC11xx_SYSCON LPC11xx System Control Block
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t SYSMEMREMAP; /*!< Offset: 0x000 System memory remap (R/W) */
+ __IO uint32_t PRESETCTRL; /*!< Offset: 0x004 Peripheral reset control (R/W) */
+ __IO uint32_t SYSPLLCTRL; /*!< Offset: 0x008 System PLL control (R/W) */
+ __IO uint32_t SYSPLLSTAT; /*!< Offset: 0x00C System PLL status (R/ ) */
+ uint32_t RESERVED0[4];
+
+ __IO uint32_t SYSOSCCTRL; /*!< Offset: 0x020 System oscillator control (R/W) */
+ __IO uint32_t WDTOSCCTRL; /*!< Offset: 0x024 Watchdog oscillator control (R/W) */
+ __IO uint32_t IRCCTRL; /*!< Offset: 0x028 IRC control (R/W) */
+ uint32_t RESERVED1[1];
+ __IO uint32_t SYSRESSTAT; /*!< Offset: 0x030 System reset status Register (R/ ) */
+ uint32_t RESERVED2[3];
+ __IO uint32_t SYSPLLCLKSEL; /*!< Offset: 0x040 System PLL clock source select (R/W) */
+ __IO uint32_t SYSPLLCLKUEN; /*!< Offset: 0x044 System PLL clock source update enable (R/W) */
+ uint32_t RESERVED3[10];
+
+ __IO uint32_t MAINCLKSEL; /*!< Offset: 0x070 Main clock source select (R/W) */
+ __IO uint32_t MAINCLKUEN; /*!< Offset: 0x074 Main clock source update enable (R/W) */
+ __IO uint32_t SYSAHBCLKDIV; /*!< Offset: 0x078 System AHB clock divider (R/W) */
+ uint32_t RESERVED4[1];
+
+ __IO uint32_t SYSAHBCLKCTRL; /*!< Offset: 0x080 System AHB clock control (R/W) */
+ uint32_t RESERVED5[4];
+ __IO uint32_t SSP0CLKDIV; /*!< Offset: 0x094 SSP0 clock divider (R/W) */
+ __IO uint32_t UARTCLKDIV; /*!< Offset: 0x098 UART clock divider (R/W) */
+ __IO uint32_t SSP1CLKDIV; /*!< Offset: 0x09C SSP1 clock divider (R/W) */
+ uint32_t RESERVED6[4];
+
+ __IO uint32_t SYSTICKCLKDIV; /*!< Offset: 0x0B0 SYSTICK clock divider (R/W) */
+ uint32_t RESERVED7[7];
+
+ __IO uint32_t WDTCLKSEL; /*!< Offset: 0x0D0 WDT clock source select (R/W) */
+ __IO uint32_t WDTCLKUEN; /*!< Offset: 0x0D4 WDT clock source update enable (R/W) */
+ __IO uint32_t WDTCLKDIV; /*!< Offset: 0x0D8 WDT clock divider (R/W) */
+ uint32_t RESERVED8[1];
+ __IO uint32_t CLKOUTCLKSEL; /*!< Offset: 0x0E0 CLKOUT clock source select (R/W) */
+ __IO uint32_t CLKOUTUEN; /*!< Offset: 0x0E4 CLKOUT clock source update enable (R/W) */
+ __IO uint32_t CLKOUTDIV; /*!< Offset: 0x0E8 CLKOUT clock divider (R/W) */
+ uint32_t RESERVED9[5];
+
+ __IO uint32_t PIOPORCAP0; /*!< Offset: 0x100 POR captured PIO status 0 (R/ ) */
+ __IO uint32_t PIOPORCAP1; /*!< Offset: 0x104 POR captured PIO status 1 (R/ ) */
+ uint32_t RESERVED10[18];
+
+ __IO uint32_t BODCTRL; /*!< Offset: 0x150 BOD control (R/W) */
+ uint32_t RESERVED11[1];
+ __IO uint32_t SYSTCKCAL; /*!< Offset: 0x158 System tick counter calibration (R/W) */
+ uint32_t RESERVED12;
+ __IO uint32_t MAINREGVOUT0CFG; /*!< Offset: 0x160 Main Regulator Voltage 0 Configuration */
+ __IO uint32_t MAINREGVOUT1CFG; /*!< Offset: 0x164 Main Regulator Voltage 1 Configuration */
+ uint32_t RESERVED13[38];
+
+ __IO uint32_t STARTAPRP0; /*!< Offset: 0x200 Start logic edge control Register 0 (R/W) */
+ __IO uint32_t STARTERP0; /*!< Offset: 0x204 Start logic signal enable Register 0 (R/W) */
+ __IO uint32_t STARTRSRP0CLR; /*!< Offset: 0x208 Start logic reset Register 0 ( /W) */
+ __IO uint32_t STARTSRP0; /*!< Offset: 0x20C Start logic status Register 0 (R/W) */
+ uint32_t RESERVED14[8];
+
+ __IO uint32_t PDSLEEPCFG; /*!< Offset: 0x230 Power-down states in Deep-sleep mode (R/W) */
+ __IO uint32_t PDAWAKECFG; /*!< Offset: 0x234 Power-down states after wake-up (R/W) */
+ __IO uint32_t PDRUNCFG; /*!< Offset: 0x238 Power-down configuration Register (R/W) */
+ uint32_t RESERVED15[101];
+ __O uint32_t VOUTCFGPROT; /*!< Offset: 0x3D0 Voltage Output Configuration Protection Register (W) */
+ uint32_t RESERVED16[8];
+ __I uint32_t DEVICE_ID; /*!< Offset: 0x3F4 Device ID (R/ ) */
+} LPC_SYSCON_TypeDef;
+/*@}*/ /* end of group LPC11xx_SYSCON */
+
+
+/*------------- Pin Connect Block (IOCON) --------------------------------*/
+/** @addtogroup LPC11xx_IOCON LPC11xx I/O Configuration Block
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t PIO2_6; /*!< Offset: 0x000 I/O configuration for pin PIO2_6 (R/W) */
+ uint32_t RESERVED0[1];
+ __IO uint32_t PIO2_0; /*!< Offset: 0x008 I/O configuration for pin PIO2_0/DTR/SSEL1 (R/W) */
+ __IO uint32_t RESET_PIO0_0; /*!< Offset: 0x00C I/O configuration for pin RESET/PIO0_0 (R/W) */
+ __IO uint32_t PIO0_1; /*!< Offset: 0x010 I/O configuration for pin PIO0_1/CLKOUT/CT32B0_MAT2 (R/W) */
+ __IO uint32_t PIO1_8; /*!< Offset: 0x014 I/O configuration for pin PIO1_8/CT16B1_CAP0 (R/W) */
+ uint32_t RESERVED1[1];
+ __IO uint32_t PIO0_2; /*!< Offset: 0x01C I/O configuration for pin PIO0_2/SSEL0/CT16B0_CAP0 (R/W) */
+
+ __IO uint32_t PIO2_7; /*!< Offset: 0x020 I/O configuration for pin PIO2_7 (R/W) */
+ __IO uint32_t PIO2_8; /*!< Offset: 0x024 I/O configuration for pin PIO2_8 (R/W) */
+ __IO uint32_t PIO2_1; /*!< Offset: 0x028 I/O configuration for pin PIO2_1/nDSR/SCK1 (R/W) */
+ __IO uint32_t PIO0_3; /*!< Offset: 0x02C I/O configuration for pin PIO0_3 (R/W) */
+ __IO uint32_t PIO0_4; /*!< Offset: 0x030 I/O configuration for pin PIO0_4/SCL (R/W) */
+ __IO uint32_t PIO0_5; /*!< Offset: 0x034 I/O configuration for pin PIO0_5/SDA (R/W) */
+ __IO uint32_t PIO1_9; /*!< Offset: 0x038 I/O configuration for pin PIO1_9/CT16B1_MAT0 (R/W) */
+ __IO uint32_t PIO3_4; /*!< Offset: 0x03C I/O configuration for pin PIO3_4 (R/W) */
+
+ __IO uint32_t PIO2_4; /*!< Offset: 0x040 I/O configuration for pin PIO2_4 (R/W) */
+ __IO uint32_t PIO2_5; /*!< Offset: 0x044 I/O configuration for pin PIO2_5 (R/W) */
+ __IO uint32_t PIO3_5; /*!< Offset: 0x048 I/O configuration for pin PIO3_5 (R/W) */
+ __IO uint32_t PIO0_6; /*!< Offset: 0x04C I/O configuration for pin PIO0_6/SCK0 (R/W) */
+ __IO uint32_t PIO0_7; /*!< Offset: 0x050 I/O configuration for pin PIO0_7/nCTS (R/W) */
+ __IO uint32_t PIO2_9; /*!< Offset: 0x054 I/O configuration for pin PIO2_9 (R/W) */
+ __IO uint32_t PIO2_10; /*!< Offset: 0x058 I/O configuration for pin PIO2_10 (R/W) */
+ __IO uint32_t PIO2_2; /*!< Offset: 0x05C I/O configuration for pin PIO2_2/DCD/MISO1 (R/W) */
+
+ __IO uint32_t PIO0_8; /*!< Offset: 0x060 I/O configuration for pin PIO0_8/MISO0/CT16B0_MAT0 (R/W) */
+ __IO uint32_t PIO0_9; /*!< Offset: 0x064 I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1 (R/W) */
+ __IO uint32_t SWCLK_PIO0_10; /*!< Offset: 0x068 I/O configuration for pin SWCLK/PIO0_10/SCK0/CT16B0_MAT2 (R/W) */
+ __IO uint32_t PIO1_10; /*!< Offset: 0x06C I/O configuration for pin PIO1_10/AD6/CT16B1_MAT1 (R/W) */
+ __IO uint32_t PIO2_11; /*!< Offset: 0x070 I/O configuration for pin PIO2_11/SCK0 (R/W) */
+ __IO uint32_t R_PIO0_11; /*!< Offset: 0x074 I/O configuration for pin TDI/PIO0_11/AD0/CT32B0_MAT3 (R/W) */
+ __IO uint32_t R_PIO1_0; /*!< Offset: 0x078 I/O configuration for pin TMS/PIO1_0/AD1/CT32B1_CAP0 (R/W) */
+ __IO uint32_t R_PIO1_1; /*!< Offset: 0x07C I/O configuration for pin TDO/PIO1_1/AD2/CT32B1_MAT0 (R/W) */
+
+ __IO uint32_t R_PIO1_2; /*!< Offset: 0x080 I/O configuration for pin nTRST/PIO1_2/AD3/CT32B1_MAT1 (R/W) */
+ __IO uint32_t PIO3_0; /*!< Offset: 0x084 I/O configuration for pin PIO3_0/nDTR (R/W) */
+ __IO uint32_t PIO3_1; /*!< Offset: 0x088 I/O configuration for pin PIO3_1/nDSR (R/W) */
+ __IO uint32_t PIO2_3; /*!< Offset: 0x08C I/O configuration for pin PIO2_3/RI/MOSI1 (R/W) */
+ __IO uint32_t SWDIO_PIO1_3; /*!< Offset: 0x090 I/O configuration for pin SWDIO/PIO1_3/AD4/CT32B1_MAT2 (R/W) */
+ __IO uint32_t PIO1_4; /*!< Offset: 0x094 I/O configuration for pin PIO1_4/AD5/CT32B1_MAT3 (R/W) */
+ __IO uint32_t PIO1_11; /*!< Offset: 0x098 I/O configuration for pin PIO1_11/AD7 (R/W) */
+ __IO uint32_t PIO3_2; /*!< Offset: 0x09C I/O configuration for pin PIO3_2/nDCD (R/W) */
+
+ __IO uint32_t PIO1_5; /*!< Offset: 0x0A0 I/O configuration for pin PIO1_5/nRTS/CT32B0_CAP0 (R/W) */
+ __IO uint32_t PIO1_6; /*!< Offset: 0x0A4 I/O configuration for pin PIO1_6/RXD/CT32B0_MAT0 (R/W) */
+ __IO uint32_t PIO1_7; /*!< Offset: 0x0A8 I/O configuration for pin PIO1_7/TXD/CT32B0_MAT1 (R/W) */
+ __IO uint32_t PIO3_3; /*!< Offset: 0x0AC I/O configuration for pin PIO3_3/nRI (R/W) */
+ __IO uint32_t SCK_LOC; /*!< Offset: 0x0B0 SCK pin location select Register (R/W) */
+ __IO uint32_t DSR_LOC; /*!< Offset: 0x0B4 DSR pin location select Register (R/W) */
+ __IO uint32_t DCD_LOC; /*!< Offset: 0x0B8 DCD pin location select Register (R/W) */
+ __IO uint32_t RI_LOC; /*!< Offset: 0x0BC RI pin location Register (R/W) */
+} LPC_IOCON_TypeDef;
+/*@}*/ /* end of group LPC11xx_IOCON */
+
+
+/*------------- Power Management Unit (PMU) --------------------------*/
+/** @addtogroup LPC11xx_PMU LPC11xx Power Management Unit
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t PCON; /*!< Offset: 0x000 Power control Register (R/W) */
+ __IO uint32_t GPREG0; /*!< Offset: 0x004 General purpose Register 0 (R/W) */
+ __IO uint32_t GPREG1; /*!< Offset: 0x008 General purpose Register 1 (R/W) */
+ __IO uint32_t GPREG2; /*!< Offset: 0x00C General purpose Register 2 (R/W) */
+ __IO uint32_t GPREG3; /*!< Offset: 0x010 General purpose Register 3 (R/W) */
+ __IO uint32_t GPREG4; /*!< Offset: 0x014 General purpose Register 4 (R/W) */
+} LPC_PMU_TypeDef;
+/*@}*/ /* end of group LPC11xx_PMU */
+
+
+/*------------- General Purpose Input/Output (GPIO) --------------------------*/
+/** @addtogroup LPC11xx_GPIO LPC11xx General Purpose Input/Output
+ @{
+*/
+typedef struct
+{
+ union {
+ __IO uint32_t MASKED_ACCESS[4096]; /*!< Offset: 0x0000 to 0x3FFC Port data Register for pins PIOn_0 to PIOn_11 (R/W) */
+ struct {
+ uint32_t RESERVED0[4095];
+ __IO uint32_t DATA; /*!< Offset: 0x3FFC Port data Register (R/W) */
+ };
+ };
+ uint32_t RESERVED1[4096];
+ __IO uint32_t DIR; /*!< Offset: 0x8000 Data direction Register (R/W) */
+ __IO uint32_t IS; /*!< Offset: 0x8004 Interrupt sense Register (R/W) */
+ __IO uint32_t IBE; /*!< Offset: 0x8008 Interrupt both edges Register (R/W) */
+ __IO uint32_t IEV; /*!< Offset: 0x800C Interrupt event Register (R/W) */
+ __IO uint32_t IE; /*!< Offset: 0x8010 Interrupt mask Register (R/W) */
+ __IO uint32_t RIS; /*!< Offset: 0x8014 Raw interrupt status Register (R/ ) */
+ __IO uint32_t MIS; /*!< Offset: 0x8018 Masked interrupt status Register (R/ ) */
+ __IO uint32_t IC; /*!< Offset: 0x801C Interrupt clear Register (R/W) */
+} LPC_GPIO_TypeDef;
+/*@}*/ /* end of group LPC11xx_GPIO */
+
+
+/*------------- Timer (TMR) --------------------------------------------------*/
+/** @addtogroup LPC11xx_TMR LPC11xx 16/32-bit Counter/Timer
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t IR; /*!< Offset: 0x000 Interrupt Register (R/W) */
+ __IO uint32_t TCR; /*!< Offset: 0x004 Timer Control Register (R/W) */
+ __IO uint32_t TC; /*!< Offset: 0x008 Timer Counter Register (R/W) */
+ __IO uint32_t PR; /*!< Offset: 0x00C Prescale Register (R/W) */
+ __IO uint32_t PC; /*!< Offset: 0x010 Prescale Counter Register (R/W) */
+ __IO uint32_t MCR; /*!< Offset: 0x014 Match Control Register (R/W) */
+ __IO uint32_t MR0; /*!< Offset: 0x018 Match Register 0 (R/W) */
+ __IO uint32_t MR1; /*!< Offset: 0x01C Match Register 1 (R/W) */
+ __IO uint32_t MR2; /*!< Offset: 0x020 Match Register 2 (R/W) */
+ __IO uint32_t MR3; /*!< Offset: 0x024 Match Register 3 (R/W) */
+ __IO uint32_t CCR; /*!< Offset: 0x028 Capture Control Register (R/W) */
+ __I uint32_t CR0; /*!< Offset: 0x02C Capture Register 0 (R/ ) */
+ uint32_t RESERVED1[3];
+ __IO uint32_t EMR; /*!< Offset: 0x03C External Match Register (R/W) */
+ uint32_t RESERVED2[12];
+ __IO uint32_t CTCR; /*!< Offset: 0x070 Count Control Register (R/W) */
+ __IO uint32_t PWMC; /*!< Offset: 0x074 PWM Control Register (R/W) */
+} LPC_TMR_TypeDef;
+/*@}*/ /* end of group LPC11xx_TMR */
+
+
+/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
+/** @addtogroup LPC11xx_UART LPC11xx Universal Asynchronous Receiver/Transmitter
+ @{
+*/
+typedef struct
+{
+ union {
+ __I uint32_t RBR; /*!< Offset: 0x000 Receiver Buffer Register (R/ ) */
+ __O uint32_t THR; /*!< Offset: 0x000 Transmit Holding Register ( /W) */
+ __IO uint32_t DLL; /*!< Offset: 0x000 Divisor Latch LSB (R/W) */
+ };
+ union {
+ __IO uint32_t DLM; /*!< Offset: 0x004 Divisor Latch MSB (R/W) */
+ __IO uint32_t IER; /*!< Offset: 0x000 Interrupt Enable Register (R/W) */
+ };
+ union {
+ __I uint32_t IIR; /*!< Offset: 0x008 Interrupt ID Register (R/ ) */
+ __O uint32_t FCR; /*!< Offset: 0x008 FIFO Control Register ( /W) */
+ };
+ __IO uint32_t LCR; /*!< Offset: 0x00C Line Control Register (R/W) */
+ __IO uint32_t MCR; /*!< Offset: 0x010 Modem control Register (R/W) */
+ __I uint32_t LSR; /*!< Offset: 0x014 Line Status Register (R/ ) */
+ __I uint32_t MSR; /*!< Offset: 0x018 Modem status Register (R/ ) */
+ __IO uint32_t SCR; /*!< Offset: 0x01C Scratch Pad Register (R/W) */
+ __IO uint32_t ACR; /*!< Offset: 0x020 Auto-baud Control Register (R/W) */
+ uint32_t RESERVED0;
+ __IO uint32_t FDR; /*!< Offset: 0x028 Fractional Divider Register (R/W) */
+ uint32_t RESERVED1;
+ __IO uint32_t TER; /*!< Offset: 0x030 Transmit Enable Register (R/W) */
+ uint32_t RESERVED2[6];
+ __IO uint32_t RS485CTRL; /*!< Offset: 0x04C RS-485/EIA-485 Control Register (R/W) */
+ __IO uint32_t ADRMATCH; /*!< Offset: 0x050 RS-485/EIA-485 address match Register (R/W) */
+ __IO uint32_t RS485DLY; /*!< Offset: 0x054 RS-485/EIA-485 direction control delay Register (R/W) */
+ __I uint32_t FIFOLVL; /*!< Offset: 0x058 FIFO Level Register (R/ ) */
+} LPC_UART_TypeDef;
+/*@}*/ /* end of group LPC11xx_UART */
+
+
+/*------------- Synchronous Serial Communication (SSP) -----------------------*/
+/** @addtogroup LPC11xx_SSP LPC11xx Synchronous Serial Port
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t CR0; /*!< Offset: 0x000 Control Register 0 (R/W) */
+ __IO uint32_t CR1; /*!< Offset: 0x004 Control Register 1 (R/W) */
+ __IO uint32_t DR; /*!< Offset: 0x008 Data Register (R/W) */
+ __I uint32_t SR; /*!< Offset: 0x00C Status Registe (R/ ) */
+ __IO uint32_t CPSR; /*!< Offset: 0x010 Clock Prescale Register (R/W) */
+ __IO uint32_t IMSC; /*!< Offset: 0x014 Interrupt Mask Set and Clear Register (R/W) */
+ __IO uint32_t RIS; /*!< Offset: 0x018 Raw Interrupt Status Register (R/W) */
+ __IO uint32_t MIS; /*!< Offset: 0x01C Masked Interrupt Status Register (R/W) */
+ __IO uint32_t ICR; /*!< Offset: 0x020 SSPICR Interrupt Clear Register (R/W) */
+} LPC_SSP_TypeDef;
+/*@}*/ /* end of group LPC11xx_SSP */
+
+
+/*------------- Inter-Integrated Circuit (I2C) -------------------------------*/
+/** @addtogroup LPC11xx_I2C LPC11xx I2C-Bus Interface
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t CONSET; /*!< Offset: 0x000 I2C Control Set Register (R/W) */
+ __I uint32_t STAT; /*!< Offset: 0x004 I2C Status Register (R/ ) */
+ __IO uint32_t DAT; /*!< Offset: 0x008 I2C Data Register (R/W) */
+ __IO uint32_t ADR0; /*!< Offset: 0x00C I2C Slave Address Register 0 (R/W) */
+ __IO uint32_t SCLH; /*!< Offset: 0x010 SCH Duty Cycle Register High Half Word (R/W) */
+ __IO uint32_t SCLL; /*!< Offset: 0x014 SCL Duty Cycle Register Low Half Word (R/W) */
+ __O uint32_t CONCLR; /*!< Offset: 0x018 I2C Control Clear Register ( /W) */
+ __IO uint32_t MMCTRL; /*!< Offset: 0x01C Monitor mode control register (R/W) */
+ __IO uint32_t ADR1; /*!< Offset: 0x020 I2C Slave Address Register 1 (R/W) */
+ __IO uint32_t ADR2; /*!< Offset: 0x024 I2C Slave Address Register 2 (R/W) */
+ __IO uint32_t ADR3; /*!< Offset: 0x028 I2C Slave Address Register 3 (R/W) */
+ __I uint32_t DATA_BUFFER; /*!< Offset: 0x02C Data buffer register ( /W) */
+ __IO uint32_t MASK0; /*!< Offset: 0x030 I2C Slave address mask register 0 (R/W) */
+ __IO uint32_t MASK1; /*!< Offset: 0x034 I2C Slave address mask register 1 (R/W) */
+ __IO uint32_t MASK2; /*!< Offset: 0x038 I2C Slave address mask register 2 (R/W) */
+ __IO uint32_t MASK3; /*!< Offset: 0x03C I2C Slave address mask register 3 (R/W) */
+} LPC_I2C_TypeDef;
+/*@}*/ /* end of group LPC11xx_I2C */
+
+
+/*------------- Watchdog Timer (WDT) -----------------------------------------*/
+/** @addtogroup LPC11xx_WDT LPC11xx WatchDog Timer
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t MOD; /*!< Offset: 0x000 Watchdog mode register (R/W) */
+ __IO uint32_t TC; /*!< Offset: 0x004 Watchdog timer constant register (R/W) */
+ __O uint32_t FEED; /*!< Offset: 0x008 Watchdog feed sequence register ( /W) */
+ __I uint32_t TV; /*!< Offset: 0x00C Watchdog timer value register (R/ ) */
+ uint32_t RESERVED0;
+ __IO uint32_t WARNINT;
+ __IO uint32_t WINDOW;
+} LPC_WDT_TypeDef;
+/*@}*/ /* end of group LPC11xx_WDT */
+
+
+/*------------- Analog-to-Digital Converter (ADC) ----------------------------*/
+/** @addtogroup LPC11xx_ADC LPC11xx Analog-to-Digital Converter
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t CR; /*!< Offset: 0x000 A/D Control Register (R/W) */
+ __IO uint32_t GDR; /*!< Offset: 0x004 A/D Global Data Register (R/W) */
+ uint32_t RESERVED0;
+ __IO uint32_t INTEN; /*!< Offset: 0x00C A/D Interrupt Enable Register (R/W) */
+ __IO uint32_t DR[8]; /*!< Offset: 0x010-0x02C A/D Channel 0..7 Data Register (R/W) */
+ __I uint32_t STAT; /*!< Offset: 0x030 A/D Status Register (R/ ) */
+} LPC_ADC_TypeDef;
+/*@}*/ /* end of group LPC11xx_ADC */
+
+
+/*------------- CAN Controller (CAN) ----------------------------*/
+/** @addtogroup LPC11xx_CAN LPC11xx Controller Area Network(CAN)
+ @{
+*/
+typedef struct
+{
+ __IO uint32_t CNTL; /* 0x000 */
+ __IO uint32_t STAT;
+ __IO uint32_t EC;
+ __IO uint32_t BT;
+ __IO uint32_t INT;
+ __IO uint32_t TEST;
+ __IO uint32_t BRPE;
+ uint32_t RESERVED0;
+ __IO uint32_t IF1_CMDREQ; /* 0x020 */
+ __IO uint32_t IF1_CMDMSK;
+ __IO uint32_t IF1_MSK1;
+ __IO uint32_t IF1_MSK2;
+ __IO uint32_t IF1_ARB1;
+ __IO uint32_t IF1_ARB2;
+ __IO uint32_t IF1_MCTRL;
+ __IO uint32_t IF1_DA1;
+ __IO uint32_t IF1_DA2;
+ __IO uint32_t IF1_DB1;
+ __IO uint32_t IF1_DB2;
+ uint32_t RESERVED1[13];
+ __IO uint32_t IF2_CMDREQ; /* 0x080 */
+ __IO uint32_t IF2_CMDMSK;
+ __IO uint32_t IF2_MSK1;
+ __IO uint32_t IF2_MSK2;
+ __IO uint32_t IF2_ARB1;
+ __IO uint32_t IF2_ARB2;
+ __IO uint32_t IF2_MCTRL;
+ __IO uint32_t IF2_DA1;
+ __IO uint32_t IF2_DA2;
+ __IO uint32_t IF2_DB1;
+ __IO uint32_t IF2_DB2;
+ uint32_t RESERVED2[21];
+ __I uint32_t TXREQ1; /* 0x100 */
+ __I uint32_t TXREQ2;
+ uint32_t RESERVED3[6];
+ __I uint32_t ND1; /* 0x120 */
+ __I uint32_t ND2;
+ uint32_t RESERVED4[6];
+ __I uint32_t IR1; /* 0x140 */
+ __I uint32_t IR2;
+ uint32_t RESERVED5[6];
+ __I uint32_t MSGV1; /* 0x160 */
+ __I uint32_t MSGV2;
+ uint32_t RESERVED6[6];
+ __IO uint32_t CLKDIV; /* 0x180 */
+} LPC_CAN_TypeDef;
+/*@}*/ /* end of group LPC11xx_CAN */
+
+#if defined ( __CC_ARM )
+#pragma no_anon_unions
+#endif
+
+/******************************************************************************/
+/* Peripheral memory map */
+/******************************************************************************/
+/* Base addresses */
+#define LPC_FLASH_BASE (0x00000000UL)
+#define LPC_RAM_BASE (0x10000000UL)
+#define LPC_APB0_BASE (0x40000000UL)
+#define LPC_AHB_BASE (0x50000000UL)
+
+/* APB0 peripherals */
+#define LPC_I2C_BASE (LPC_APB0_BASE + 0x00000)
+#define LPC_WDT_BASE (LPC_APB0_BASE + 0x04000)
+#define LPC_UART_BASE (LPC_APB0_BASE + 0x08000)
+#define LPC_CT16B0_BASE (LPC_APB0_BASE + 0x0C000)
+#define LPC_CT16B1_BASE (LPC_APB0_BASE + 0x10000)
+#define LPC_CT32B0_BASE (LPC_APB0_BASE + 0x14000)
+#define LPC_CT32B1_BASE (LPC_APB0_BASE + 0x18000)
+#define LPC_ADC_BASE (LPC_APB0_BASE + 0x1C000)
+#define LPC_PMU_BASE (LPC_APB0_BASE + 0x38000)
+#define LPC_SSP0_BASE (LPC_APB0_BASE + 0x40000)
+#define LPC_IOCON_BASE (LPC_APB0_BASE + 0x44000)
+#define LPC_SYSCON_BASE (LPC_APB0_BASE + 0x48000)
+#define LPC_CAN_BASE (LPC_APB0_BASE + 0x50000)
+#define LPC_SSP1_BASE (LPC_APB0_BASE + 0x58000)
+
+/* AHB peripherals */
+#define LPC_GPIO_BASE (LPC_AHB_BASE + 0x00000)
+#define LPC_GPIO0_BASE (LPC_AHB_BASE + 0x00000)
+#define LPC_GPIO1_BASE (LPC_AHB_BASE + 0x10000)
+#define LPC_GPIO2_BASE (LPC_AHB_BASE + 0x20000)
+#define LPC_GPIO3_BASE (LPC_AHB_BASE + 0x30000)
+
+/******************************************************************************/
+/* Peripheral declaration */
+/******************************************************************************/
+#define LPC_I2C ((LPC_I2C_TypeDef *) LPC_I2C_BASE )
+#define LPC_WDT ((LPC_WDT_TypeDef *) LPC_WDT_BASE )
+#define LPC_UART ((LPC_UART_TypeDef *) LPC_UART_BASE )
+#define LPC_TMR16B0 ((LPC_TMR_TypeDef *) LPC_CT16B0_BASE)
+#define LPC_TMR16B1 ((LPC_TMR_TypeDef *) LPC_CT16B1_BASE)
+#define LPC_TMR32B0 ((LPC_TMR_TypeDef *) LPC_CT32B0_BASE)
+#define LPC_TMR32B1 ((LPC_TMR_TypeDef *) LPC_CT32B1_BASE)
+#define LPC_ADC ((LPC_ADC_TypeDef *) LPC_ADC_BASE )
+#define LPC_PMU ((LPC_PMU_TypeDef *) LPC_PMU_BASE )
+#define LPC_SSP0 ((LPC_SSP_TypeDef *) LPC_SSP0_BASE )
+#define LPC_SSP1 ((LPC_SSP_TypeDef *) LPC_SSP1_BASE )
+#define LPC_CAN ((LPC_CAN_TypeDef *) LPC_CAN_BASE )
+#define LPC_IOCON ((LPC_IOCON_TypeDef *) LPC_IOCON_BASE )
+#define LPC_SYSCON ((LPC_SYSCON_TypeDef *) LPC_SYSCON_BASE)
+#define LPC_GPIO0 ((LPC_GPIO_TypeDef *) LPC_GPIO0_BASE )
+#define LPC_GPIO1 ((LPC_GPIO_TypeDef *) LPC_GPIO1_BASE )
+#define LPC_GPIO2 ((LPC_GPIO_TypeDef *) LPC_GPIO2_BASE )
+#define LPC_GPIO3 ((LPC_GPIO_TypeDef *) LPC_GPIO3_BASE )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LPC11xx_H__ */
diff --git a/src/core/SPI.cpp b/src/core/SPI.cpp new file mode 100755 index 0000000..53108a9 --- /dev/null +++ b/src/core/SPI.cpp @@ -0,0 +1,213 @@ +/* + * ssp.cpp + * + * Created on: 2011/07/30 + * Author: lynxeyed + */ +#include "gpio.h" +#include "SPI.h" + + +SSP SPI; + +SSP::SSP() //define constructor +{ + this->port = marySSP0; + bitOrder = LSBFIRST; + divider = SPI_CLOCK_DIV4; //Arduino's default + dataMode = SPI_MODE0; + bitlength = 8; + setClockDivider(divider); + setBitLength(bitlength); + setBitOrder(LSBFIRST); + begin(); +} + +SSP::~SSP() // destructor +{ + +} +void SSP::begin() +{ + ssp_begin(port,divider,dataMode,bitlength); + return; +} +void SSP::begin(SSP_PORT port) +{ + this->port = port; + ssp_begin(port,divider,dataMode,bitlength); + return; +} +void SSP::setBitLength(int bitlength) +{ + this->bitlength = bitlength; + return; +} +void SSP::end() +{ + LPC_SSP0->CR1 &= ~(1U << 1); //the SPI controller is disabled + return; +} + +void SSP::setBitOrder(SSP_BIT_ORDER bitOrder) +{ + this->bitOrder = bitOrder; + if(bitOrder == MSBFIRST) + { + ; + } + else + { + ; + } + return; +} + +void SSP::setClockDivider(SSP_CLK_DIVIDER divider) //See also SSP1CLKDIV(user.manual p.24) +{ + this->divider = divider; + return; + +} + +void SSP::setDataMode(SSP_DATA_MODE mode) +{ + this->dataMode = mode; + +} + +unsigned long SSP::transfer(unsigned long txdata) +{ + return ssp_transfer(txdata); +} + + + +// lowlevel + +void ssp_begin(SSP_PORT port,SSP_CLK_DIVIDER divider,SSP_DATA_MODE dataMode,int bitlength) +{ + // Initialize SSP + // PIO0_2(CN3_3) : SSEL + // PIO0_6(CN4_3) : SCLK + // PIO0_8(CN4_5) : MISO + // PIO0_9(CN4_7) : MOSI + + volatile int sspPhase; //SSP's clock phase + + pinMode(P0_2,OUTPUT); // PIO0_2(CN3_3) out + LPC_IOCON->PIO0_2 = 0x00000000; // GPIO, disable pu/pd mos + digitalWrite(P0_2,HIGH); // PIO0_2(CN3_3) = 1 + + switch(port){ + case LPCXSSP0: + LPC_IOCON->SCK_LOC = 0x00000001;//2; // SCK is PIO2_11 + LPC_IOCON->PIO2_11 = 0x00000001;//2; // SCK, disable pu/pd mos + break; + case marySSP0: + LPC_IOCON->SCK_LOC = 0x00000002; // SCK is PIO0_6 + LPC_IOCON->PIO0_6 = 0x00000002; // SCK, disable pu/pd mos + break; + default: //default = MARY + LPC_IOCON->SCK_LOC = 0x00000002; // SCK is PIO0_6 + LPC_IOCON->PIO0_6 = 0x00000002; // SCK, disable pu/pd mos + break; + } + LPC_IOCON->PIO0_9 = 0x00000001; // MOSI, disable pu/pd mos + LPC_IOCON->PIO0_8 = 0x00000011; // MISO, enable pu/pd mos + + // + // Initialize SPI + // + LPC_SYSCON->PRESETCTRL |= (0x1<<0); + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); + //clockDivider + LPC_SYSCON->SSP0CLKDIV = 0x01; // Divided by 1 + switch(divider) + { + case SPI_CLOCK_DIV1: //Special code + LPC_SYSCON->SSP0CLKDIV = 0x01; + break; + case SPI_CLOCK_DIV2: + LPC_SYSCON->SSP0CLKDIV = 0x02; + break; + case SPI_CLOCK_DIV4: + LPC_SYSCON->SSP0CLKDIV = 0x04; + break; + case SPI_CLOCK_DIV8: + LPC_SYSCON->SSP0CLKDIV = 0x08; + break; + case SPI_CLOCK_DIV16: + LPC_SYSCON->SSP0CLKDIV = 0x10; + break; + case SPI_CLOCK_DIV32: + LPC_SYSCON->SSP0CLKDIV = 0x20; + break; + case SPI_CLOCK_DIV64: + LPC_SYSCON->SSP0CLKDIV = 0x40; + break; + case SPI_CLOCK_DIV128: + LPC_SYSCON->SSP0CLKDIV = 0x80; + break; + default: + LPC_SYSCON->SSP0CLKDIV = 0x04; //default + break; + } + // dataMode(MODE0,1,2,3) + switch(dataMode) + { + // SSP0CR0::bit6 = CPOL, bit7 = CPHA + case SPI_MODE0: // CPOL=0, CPHA = 0 + sspPhase = 0; + break; + case SPI_MODE1: // CPOL=0, CPHA = 1 + sspPhase = 1; + break; + case SPI_MODE2: // CPOL=1, CPHA = 0 + sspPhase = 2; + break; + case SPI_MODE3: // CPOL=1, CPHA = 1 + sspPhase = 3; + break; + case TI_SERIAL_MODE: + default: + break; + }//end switch(dataMode) + + // bitLength + LPC_SSP0->CR0 = (sspPhase << 6); + LPC_SSP0->CR0 |= (bitlength - 1); + + //SCLKDivider + LPC_SSP0->CPSR = 2; //2 or more but even value + + + // Enable the SSP Interrupt + NVIC_EnableIRQ(SSP0_IRQn); + NVIC_SetPriority(SSP0_IRQn, 3); + + // Device select as master, SSP Enabled (see also user.manual p.143) + LPC_SSP0->CR1 = (1U << 1); + return; +} + +unsigned long ssp_transfer(unsigned long txdata) +{ + volatile unsigned long rxdata; + // Tx + while ((LPC_SSP0->SR & ((1U<<1)|(1U<<4))) != 1U << 1); + // Send a byte + LPC_SSP0->DR = txdata; + // Wait until the Busy bit is cleared + while ( LPC_SSP0->SR & (1<<4) ); + + // Rx + while ((LPC_SSP0->SR & (1U<<2)) != 1U << 2 ); + rxdata = LPC_SSP0->DR; + + return rxdata; +} + + + + diff --git a/src/core/SPI.h b/src/core/SPI.h new file mode 100755 index 0000000..6040e74 --- /dev/null +++ b/src/core/SPI.h @@ -0,0 +1,120 @@ +#ifndef SSP_H_ +#define SSP_H_ + + +/**************************************************************************//** + * @file SPI.h + * @brief Arduino-like library for MARY + * @version V0.50 + * @date 1. August 2011. + * @author @@lynxeyed_atsu + * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR> + * 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: <BR> + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.<BR> + * 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 "LPC11xx.h" +#include "gpio.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/*! @enum SSP_PORT + @brief SPIポートのチャンネル選択。使用時のCS信号を選択する + @note SPIが1ポートしかないMARYでは使用していないので特に影響はないが、2ポート以上あるLPCXpressoやmbedシリーズとの後方互換性を考慮し用意している +*/ +typedef enum { + marySSP0, /*!< MARYのSSPポート(デフォルト) */ + LPCXSSP0, /*!< LPCXPressoのSSP0ポート */ + LPCXSSP1 /*!< LPCXpressoのSSP1ポート */ +} SSP_PORT; // Defaults:marySSP1 + +/*! @enum SSP_BIT_ORDER + @brief SSPIバスの入出力に使用するビットオーダーを設定 + @warning この機能はまだ実装されていない + */ +typedef enum { + LSBFIRST, /*!< LSBを最初に送出(least-significant bit first) */ + MSBFIRST /*!< MSBを最初に送出(most-significant bit first) */ +} SSP_BIT_ORDER; + +/*! @enum SSP_CLK_DIVIDER + @brief SPIクロック分周器の設定. 分周値は2、4、8、16、32、64、128のいずれか +*/ +typedef enum { + SPI_CLOCK_DIV1, /*!< SPIクロックはシステムクロックと同じ(MARY-DUINOオリジナル) */ + SPI_CLOCK_DIV2, /*!< SPIクロックはシステムクロックの1/2 */ + SPI_CLOCK_DIV4, /*!< SPIクロックはシステムクロックの1/4 */ + SPI_CLOCK_DIV8, /*!< SPIクロックはシステムクロックの1/8 */ + SPI_CLOCK_DIV16, /*!< SPIクロックはシステムクロックの1/16 */ + SPI_CLOCK_DIV32, /*!< SPIクロックはシステムクロックの1/32 */ + SPI_CLOCK_DIV64, /*!< SPIクロックはシステムクロックの1/64 */ + SPI_CLOCK_DIV128 /*!< SPIクロックはシステムクロックの1/128 */ +} SSP_CLK_DIVIDER; + +/*! @enum SSP_DATA_MODE + @brief SPIの転送モードの設定 +*/ +typedef enum { + SPI_MODE0 , /*!< SPIモード0 ( CPOL = 0, CPHA = 0 ) */ + SPI_MODE1 , /*!< SPIモード1 ( CPOL = 0, CPHA = 1 ) */ + SPI_MODE2 , /*!< SPIモード2 ( CPOL = 1, CPHA = 0 ) */ + SPI_MODE3 , /*!< SPIモード3 ( CPOL = 1, CPHA = 1 ) */ + TI_SERIAL_MODE , /*!< Texas Instrumentsの提唱するシリアル方式 */ + NXP_I2S /*!< I2Sモード(I2S搭載機種のみ) */ +} SSP_DATA_MODE; + +/*! @class SSP + @brief SPIを制御するクラス +*/ +class SSP { +private: + SSP_PORT port; /*!< 使用するポート */ + SSP_BIT_ORDER bitOrder; + SSP_CLK_DIVIDER divider; + SSP_DATA_MODE dataMode; + int bitlength; + +public: + SSP(); // announce the constructor to initialize + ~SSP(); + void begin(); + void begin(SSP_PORT port); + void end(); + void setBitLength(int bitLength); + void setBitOrder(SSP_BIT_ORDER bitOrder) ; + void setClockDivider(SSP_CLK_DIVIDER divider); + void setDataMode(SSP_DATA_MODE mode); + unsigned long transfer(unsigned long txdata) ; +}; + + +// lowlevel +void ssp_begin(SSP_PORT port,SSP_CLK_DIVIDER divider,SSP_DATA_MODE dataMode,int bitLength); +unsigned long ssp_transfer(unsigned long txdata); + + + +extern SSP SPI; + + +#ifdef __cplusplus + } +#endif + + +#endif /* SSP_H_ */ diff --git a/src/core/SPI1.cpp b/src/core/SPI1.cpp new file mode 100755 index 0000000..a164004 --- /dev/null +++ b/src/core/SPI1.cpp @@ -0,0 +1,220 @@ +/*
+ * ssp.cpp
+ *
+ * Created on: 2011/07/30
+ * Author: lynxeyed
+ */
+#include "gpio.h"
+#include "SPI1.h"
+
+
+SSP1 SPI1;
+
+SSP1::SSP1() //define constructor
+{
+ this->port = LPCXSSP1;
+ bitOrder = LSBFIRST;
+ divider = SPI_CLOCK_DIV4; //Arduino's default
+ dataMode = SPI_MODE0;
+ bitlength = 8;
+ setClockDivider(divider);
+ setBitLength(bitlength);
+ setBitOrder(LSBFIRST);
+ begin();
+}
+
+SSP1::~SSP1() // destructor
+{
+
+}
+void SSP1::begin()
+{
+ ssp1_begin(port,divider,dataMode,bitlength);
+ return;
+}
+void SSP1::begin(SSP_PORT port)
+{
+ this->port = port;
+ ssp1_begin(port,divider,dataMode,bitlength);
+ return;
+}
+void SSP1::setBitLength(int bitlength)
+{
+ this->bitlength = bitlength;
+ return;
+}
+void SSP1::end()
+{
+ LPC_SSP1->CR1 &= ~(1U << 1); //the SPI controller is disabled
+ return;
+}
+
+void SSP1::setBitOrder(SSP_BIT_ORDER bitOrder)
+{
+ this->bitOrder = bitOrder;
+ if(bitOrder == MSBFIRST)
+ {
+ ;
+ }
+ else
+ {
+ ;
+ }
+ return;
+}
+
+void SSP1::setClockDivider(SSP_CLK_DIVIDER divider) //See also SSP1CLKDIV(user.manual p.24)
+{
+ this->divider = divider;
+ return;
+
+}
+
+void SSP1::setDataMode(SSP_DATA_MODE mode)
+{
+ this->dataMode = mode;
+
+}
+
+unsigned long SSP1::transfer(unsigned long txdata)
+{
+ return ssp1_transfer(txdata);
+}
+
+
+
+// lowlevel
+
+void ssp1_begin(SSP_PORT port,SSP_CLK_DIVIDER divider,SSP_DATA_MODE dataMode,int bitlength)
+{
+ // Initialize SSP
+ // PIO2_0 : SSEL
+ // PIO2_1 : SCLK
+ // PIO2_2 : MISO
+ // PIO2_3 : MOSI
+
+ volatile int sspPhase; //SSP's clock phase
+
+ pinMode(P2_0,OUTPUT); // PIO2_0 out
+ LPC_IOCON->PIO2_0 = 0x00000000; // GPIO, disable pu/pd mos
+ digitalWrite(P2_0,HIGH); // PIO2_0 = 1
+
+ LPC_IOCON->PIO2_1 = 0x00000002; // SCK, disable pu/pd mos
+ LPC_IOCON->PIO2_3 = 0x00000002; // MOSI, disable pu/pd mos
+ LPC_IOCON->PIO2_2 = 0x00000012; // MISO, enable pu/pd mos
+
+ /*
+ switch(port){
+ case LPCXSSP0:
+ LPC_IOCON->SCK_LOC = 0x00000001;//2; // SCK is PIO2_11
+ LPC_IOCON->PIO2_11 = 0x00000001;//2; // SCK, disable pu/pd mos
+ break;
+ case marySSP0:
+ LPC_IOCON->SCK_LOC = 0x00000002; // SCK is PIO0_6
+ LPC_IOCON->PIO0_6 = 0x00000002; // SCK, disable pu/pd mos
+ break;
+ default: //default = MARY
+ LPC_IOCON->SCK_LOC = 0x00000002; // SCK is PIO0_6
+ LPC_IOCON->PIO0_6 = 0x00000002; // SCK, disable pu/pd mos
+ break;
+ }
+ */
+
+ //LPC_IOCON->PIO0_9 = 0x00000001; // MOSI, disable pu/pd mos
+ //LPC_IOCON->PIO0_8 = 0x00000011; // MISO, enable pu/pd mos
+
+ //
+ // Initialize SPI
+ //
+ LPC_SYSCON->PRESETCTRL |= (0x1<<2);
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);
+ //clockDivider
+ LPC_SYSCON->SSP1CLKDIV = 0x01; // Divided by 1
+ switch(divider)
+ {
+ case SPI_CLOCK_DIV1: //Special code
+ LPC_SYSCON->SSP1CLKDIV = 0x01;
+ break;
+ case SPI_CLOCK_DIV2:
+ LPC_SYSCON->SSP1CLKDIV = 0x02;
+ break;
+ case SPI_CLOCK_DIV4:
+ LPC_SYSCON->SSP1CLKDIV = 0x04;
+ break;
+ case SPI_CLOCK_DIV8:
+ LPC_SYSCON->SSP1CLKDIV = 0x08;
+ break;
+ case SPI_CLOCK_DIV16:
+ LPC_SYSCON->SSP1CLKDIV = 0x10;
+ break;
+ case SPI_CLOCK_DIV32:
+ LPC_SYSCON->SSP1CLKDIV = 0x20;
+ break;
+ case SPI_CLOCK_DIV64:
+ LPC_SYSCON->SSP1CLKDIV = 0x40;
+ break;
+ case SPI_CLOCK_DIV128:
+ LPC_SYSCON->SSP1CLKDIV = 0x80;
+ break;
+ default:
+ LPC_SYSCON->SSP1CLKDIV = 0x04; //default
+ break;
+ }
+ // dataMode(MODE0,1,2,3)
+ switch(dataMode)
+ {
+ // SSP0CR0::bit6 = CPOL, bit7 = CPHA
+ case SPI_MODE0: // CPOL=0, CPHA = 0
+ sspPhase = 0;
+ break;
+ case SPI_MODE1: // CPOL=0, CPHA = 1
+ sspPhase = 1;
+ break;
+ case SPI_MODE2: // CPOL=1, CPHA = 0
+ sspPhase = 2;
+ break;
+ case SPI_MODE3: // CPOL=1, CPHA = 1
+ sspPhase = 3;
+ break;
+ case TI_SERIAL_MODE:
+ default:
+ break;
+ }//end switch(dataMode)
+
+ // bitLength
+ LPC_SSP1->CR0 = (sspPhase << 6);
+ LPC_SSP1->CR0 |= (bitlength - 1);
+
+ //SCLKDivider
+ LPC_SSP1->CPSR = 2; //2 or more but even value
+
+
+ // Enable the SSP Interrupt
+ NVIC_EnableIRQ(SSP1_IRQn);
+ NVIC_SetPriority(SSP1_IRQn, 3);
+
+ // Device select as master, SSP Enabled (see also user.manual p.143)
+ LPC_SSP1->CR1 = (1U << 1);
+ return;
+}
+
+unsigned long ssp1_transfer(unsigned long txdata)
+{
+ volatile unsigned long rxdata;
+ // Tx
+ while ((LPC_SSP1->SR & ((1U<<1)|(1U<<4))) != 1U << 1);
+ // Send a byte
+ LPC_SSP1->DR = txdata;
+ // Wait until the Busy bit is cleared
+ while ( LPC_SSP1->SR & (1<<4) );
+
+ // Rx
+ while ((LPC_SSP1->SR & (1U<<2)) != 1U << 2 );
+ rxdata = LPC_SSP1->DR;
+
+ return rxdata;
+}
+
+
+
+
diff --git a/src/core/SPI1.h b/src/core/SPI1.h new file mode 100755 index 0000000..6863b8f --- /dev/null +++ b/src/core/SPI1.h @@ -0,0 +1,77 @@ +#ifndef SSP1_H_
+#define SSP1_H_
+
+
+/**************************************************************************//**
+ * @file SPI1.h
+ * @brief Arduino-like library for MARY
+ * @version V0.50
+ * @date 1. August 2011.
+ * @author @@lynxeyed_atsu
+ * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR>
+ * 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: <BR>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.<BR>
+ * 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 "LPC11xx.h"
+#include "gpio.h"
+#include "SPI.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/*! @class SSP1
+ @brief SPI1を制御するクラス
+*/
+class SSP1 {
+private:
+ SSP_PORT port; /*!< 使用するポート */
+ SSP_BIT_ORDER bitOrder;
+ SSP_CLK_DIVIDER divider;
+ SSP_DATA_MODE dataMode;
+ int bitlength;
+
+public:
+ SSP1(); // announce the constructor to initialize
+ ~SSP1();
+ void begin();
+ void begin(SSP_PORT port);
+ void end();
+ void setBitLength(int bitLength);
+ void setBitOrder(SSP_BIT_ORDER bitOrder) ;
+ void setClockDivider(SSP_CLK_DIVIDER divider);
+ void setDataMode(SSP_DATA_MODE mode);
+ unsigned long transfer(unsigned long txdata) ;
+};
+
+
+// lowlevel
+void ssp1_begin(SSP_PORT port,SSP_CLK_DIVIDER divider,SSP_DATA_MODE dataMode,int bitLength);
+unsigned long ssp1_transfer(unsigned long txdata);
+
+
+
+extern SSP1 SPI1;
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* SSP1_H_ */
diff --git a/src/core/core_cm0.h b/src/core/core_cm0.h new file mode 100755 index 0000000..f148b8f --- /dev/null +++ b/src/core/core_cm0.h @@ -0,0 +1,960 @@ +/**************************************************************************//**
+ * @file core_cm0.h
+ * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
+ * @version V1.30
+ * @date 30. October 2009
+ *
+ * @note
+ * Copyright (C) 2009 ARM Limited. All rights reserved.
+ *
+ * @par
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M
+ * processor based microcontrollers. This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * @par
+ * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+#ifndef __CM0_CORE_H__
+#define __CM0_CORE_H__
+
+/** @addtogroup CMSIS_CM0_core_LintCinfiguration CMSIS CM0 Core Lint Configuration
+ *
+ * List of Lint messages which will be suppressed and not shown:
+ * - not yet checked
+ * .
+ * Note: To re-enable a Message, insert a space before 'lint' *
+ *
+ */
+
+
+/** @addtogroup CMSIS_CM0_core_definitions CM0 Core Definitions
+ This file defines all structures and symbols for CMSIS core:
+ - CMSIS version number
+ - Cortex-M core registers and bitfields
+ - Cortex-M core peripheral base address
+ @{
+ */
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#define __CM0_CMSIS_VERSION_MAIN (0x01) /*!< [31:16] CMSIS HAL main version */
+#define __CM0_CMSIS_VERSION_SUB (0x30) /*!< [15:0] CMSIS HAL sub version */
+#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16) | __CM0_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */
+
+#define __CORTEX_M (0x00) /*!< Cortex core */
+
+#include <stdint.h> /* Include standard types */
+
+#if defined (__ICCARM__)
+ #include <intrinsics.h> /* IAR Intrinsics */
+#endif
+
+
+#ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2 /*!< standard definition for NVIC Priority Bits */
+#endif
+
+
+
+
+/**
+ * IO definitions
+ *
+ * define access restrictions to peripheral registers
+ */
+
+#ifdef __cplusplus
+ #define __I volatile /*!< defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< defines 'read only' permissions */
+#endif
+#define __O volatile /*!< defines 'write only' permissions */
+#define __IO volatile /*!< defines 'read / write' permissions */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ ******************************************************************************/
+/** @addtogroup CMSIS_CM0_core_register CMSIS CM0 Core Register
+ @{
+*/
+
+
+/** @addtogroup CMSIS_CM0_NVIC CMSIS CM0 NVIC
+ memory mapped structure for Nested Vectored Interrupt Controller (NVIC)
+ @{
+ */
+typedef struct
+{
+ __IO uint32_t ISER[1]; /*!< (Offset: 0x000) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31];
+ __IO uint32_t ICER[1]; /*!< (Offset: 0x080) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31];
+ __IO uint32_t ISPR[1]; /*!< (Offset: 0x100) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31];
+ __IO uint32_t ICPR[1]; /*!< (Offset: 0x180) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31];
+ uint32_t RESERVED4[64];
+ __IO uint32_t IPR[8]; /*!< (Offset: 0x3EC) Interrupt Priority Register */
+} NVIC_Type;
+/*@}*/ /* end of group CMSIS_CM0_NVIC */
+
+
+/** @addtogroup CMSIS_CM0_SCB CMSIS CM0 SCB
+ memory mapped structure for System Control Block (SCB)
+ @{
+ */
+typedef struct
+{
+ __I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */
+ __IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */
+ uint32_t RESERVED0;
+ __IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */
+ __IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */
+ __IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */
+ uint32_t RESERVED1;
+ __IO uint32_t SHP[2]; /*!< Offset: 0x1C System Handlers Priority Registers. [0] is RESERVED */
+ __IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */
+ uint32_t RESERVED2[2];
+ __IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFul << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFul << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFul << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFul << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFul << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1ul << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1ul << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1ul << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1ul << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1ul << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1ul << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1ul << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFul << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFul << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFul << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFul << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1ul << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1ul << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1ul << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1ul << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1ul << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1ul << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1ul << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1ul << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1ul << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1ul << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1ul << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1ul << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1ul << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */
+/*@}*/ /* end of group CMSIS_CM0_SCB */
+
+
+/** @addtogroup CMSIS_CM0_SysTick CMSIS CM0 SysTick
+ memory mapped structure for SysTick
+ @{
+ */
+typedef struct
+{
+ __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
+ __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
+ __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
+ __I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1ul << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1ul << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1ul << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1ul << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1ul << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1ul << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */
+/*@}*/ /* end of group CMSIS_CM0_SysTick */
+
+
+/** @addtogroup CMSIS_CM0_CoreDebug CMSIS CM0 Core Debug
+ memory mapped structure for Core Debug Register
+ @{
+ */
+typedef struct
+{
+ __IO uint32_t DHCSR; /*!< Offset: 0x00 Debug Halting Control and Status Register */
+ __O uint32_t DCRSR; /*!< Offset: 0x04 Debug Core Register Selector Register */
+ __IO uint32_t DCRDR; /*!< Offset: 0x08 Debug Core Register Data Register */
+ __IO uint32_t DEMCR; /*!< Offset: 0x0C Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFul << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1ul << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1ul << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1ul << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1ul << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1ul << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1ul << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1ul << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1ul << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1ul << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1ul << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register */
+#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1ul << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1Ful << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_DWTENA_Pos 24 /*!< CoreDebug DEMCR: DWTENA Position */
+#define CoreDebug_DEMCR_DWTENA_Msk (1ul << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1ul << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1ul << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+/*@}*/ /* end of group CMSIS_CM0_CoreDebug */
+
+
+/* Memory mapping of Cortex-M0 Hardware */
+#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */
+#define CoreDebug_BASE (0xE000EDF0) /*!< Core Debug Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */
+
+#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */
+#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
+
+/*@}*/ /* end of group CMSIS_CM0_core_register */
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ ******************************************************************************/
+
+#if defined ( __CC_ARM )
+ #define __ASM __asm /*!< asm keyword for ARM Compiler */
+ #define __INLINE __inline /*!< inline keyword for ARM Compiler */
+
+#elif defined ( __ICCARM__ )
+ #define __ASM __asm /*!< asm keyword for IAR Compiler */
+ #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
+
+#elif defined ( __GNUC__ )
+ #define __ASM __asm /*!< asm keyword for GNU Compiler */
+ #define __INLINE inline /*!< inline keyword for GNU Compiler */
+
+#elif defined ( __TASKING__ )
+ #define __ASM __asm /*!< asm keyword for TASKING Compiler */
+ #define __INLINE inline /*!< inline keyword for TASKING Compiler */
+
+#endif
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+
+#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
+/* ARM armcc specific functions */
+
+#define __enable_fault_irq __enable_fiq
+#define __disable_fault_irq __disable_fiq
+
+#define __NOP __nop
+#define __WFI __wfi
+#define __WFE __wfe
+#define __SEV __sev
+#define __ISB() __isb(0)
+#define __DSB() __dsb(0)
+#define __DMB() __dmb(0)
+#define __REV __rev
+
+
+/* intrinsic void __enable_irq(); */
+/* intrinsic void __disable_irq(); */
+
+
+/**
+ * @brief Return the Process Stack Pointer
+ *
+ * @return ProcessStackPointer
+ *
+ * Return the actual process stack pointer
+ */
+extern uint32_t __get_PSP(void);
+
+/**
+ * @brief Set the Process Stack Pointer
+ *
+ * @param topOfProcStack Process Stack Pointer
+ *
+ * Assign the value ProcessStackPointer to the MSP
+ * (process stack pointer) Cortex processor register
+ */
+extern void __set_PSP(uint32_t topOfProcStack);
+
+/**
+ * @brief Return the Main Stack Pointer
+ *
+ * @return Main Stack Pointer
+ *
+ * Return the current value of the MSP (main stack pointer)
+ * Cortex processor register
+ */
+extern uint32_t __get_MSP(void);
+
+/**
+ * @brief Set the Main Stack Pointer
+ *
+ * @param topOfMainStack Main Stack Pointer
+ *
+ * Assign the value mainStackPointer to the MSP
+ * (main stack pointer) Cortex processor register
+ */
+extern void __set_MSP(uint32_t topOfMainStack);
+
+/**
+ * @brief Reverse byte order in unsigned short value
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in unsigned short value
+ */
+extern uint32_t __REV16(uint16_t value);
+
+/**
+ * @brief Reverse byte order in signed short value with sign extension to integer
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in signed short value with sign extension to integer
+ */
+extern int32_t __REVSH(int16_t value);
+
+
+#if (__ARMCC_VERSION < 400000)
+
+/**
+ * @brief Return the Priority Mask value
+ *
+ * @return PriMask
+ *
+ * Return state of the priority mask bit from the priority mask register
+ */
+extern uint32_t __get_PRIMASK(void);
+
+/**
+ * @brief Set the Priority Mask value
+ *
+ * @param priMask PriMask
+ *
+ * Set the priority mask bit in the priority mask register
+ */
+extern void __set_PRIMASK(uint32_t priMask);
+
+/**
+ * @brief Return the Control Register value
+ *
+ * @return Control value
+ *
+ * Return the content of the control register
+ */
+extern uint32_t __get_CONTROL(void);
+
+/**
+ * @brief Set the Control Register value
+ *
+ * @param control Control value
+ *
+ * Set the control register
+ */
+extern void __set_CONTROL(uint32_t control);
+
+#else /* (__ARMCC_VERSION >= 400000) */
+
+
+/**
+ * @brief Return the Priority Mask value
+ *
+ * @return PriMask
+ *
+ * Return state of the priority mask bit from the priority mask register
+ */
+static __INLINE uint32_t __get_PRIMASK(void)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ return(__regPriMask);
+}
+
+/**
+ * @brief Set the Priority Mask value
+ *
+ * @param priMask PriMask
+ *
+ * Set the priority mask bit in the priority mask register
+ */
+static __INLINE void __set_PRIMASK(uint32_t priMask)
+{
+ register uint32_t __regPriMask __ASM("primask");
+ __regPriMask = (priMask);
+}
+
+/**
+ * @brief Return the Control Register value
+ *
+ * @return Control value
+ *
+ * Return the content of the control register
+ */
+static __INLINE uint32_t __get_CONTROL(void)
+{
+ register uint32_t __regControl __ASM("control");
+ return(__regControl);
+}
+
+/**
+ * @brief Set the Control Register value
+ *
+ * @param control Control value
+ *
+ * Set the control register
+ */
+static __INLINE void __set_CONTROL(uint32_t control)
+{
+ register uint32_t __regControl __ASM("control");
+ __regControl = control;
+}
+
+#endif /* __ARMCC_VERSION */
+
+
+
+#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
+/* IAR iccarm specific functions */
+
+#define __enable_irq __enable_interrupt /*!< global Interrupt enable */
+#define __disable_irq __disable_interrupt /*!< global Interrupt disable */
+
+static __INLINE void __enable_fault_irq() { __ASM ("cpsie f"); }
+static __INLINE void __disable_fault_irq() { __ASM ("cpsid f"); }
+
+#define __NOP __no_operation /*!< no operation intrinsic in IAR Compiler */
+static __INLINE void __WFI() { __ASM ("wfi"); }
+static __INLINE void __WFE() { __ASM ("wfe"); }
+static __INLINE void __SEV() { __ASM ("sev"); }
+
+/* intrinsic void __ISB(void) */
+/* intrinsic void __DSB(void) */
+/* intrinsic void __DMB(void) */
+/* intrinsic void __set_PRIMASK(); */
+/* intrinsic void __get_PRIMASK(); */
+
+
+/* intrinsic uint32_t __REV(uint32_t value); */
+/* intrinsic uint32_t __REVSH(uint32_t value); */
+
+
+/**
+ * @brief Return the Process Stack Pointer
+ *
+ * @return ProcessStackPointer
+ *
+ * Return the actual process stack pointer
+ */
+extern uint32_t __get_PSP(void);
+
+/**
+ * @brief Set the Process Stack Pointer
+ *
+ * @param topOfProcStack Process Stack Pointer
+ *
+ * Assign the value ProcessStackPointer to the MSP
+ * (process stack pointer) Cortex processor register
+ */
+extern void __set_PSP(uint32_t topOfProcStack);
+
+/**
+ * @brief Return the Main Stack Pointer
+ *
+ * @return Main Stack Pointer
+ *
+ * Return the current value of the MSP (main stack pointer)
+ * Cortex processor register
+ */
+extern uint32_t __get_MSP(void);
+
+/**
+ * @brief Set the Main Stack Pointer
+ *
+ * @param topOfMainStack Main Stack Pointer
+ *
+ * Assign the value mainStackPointer to the MSP
+ * (main stack pointer) Cortex processor register
+ */
+extern void __set_MSP(uint32_t topOfMainStack);
+
+/**
+ * @brief Reverse byte order in unsigned short value
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in unsigned short value
+ */
+extern uint32_t __REV16(uint16_t value);
+
+
+
+
+
+#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
+/* GNU gcc specific functions */
+
+static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); }
+static __INLINE void __disable_irq() { __ASM volatile ("cpsid i"); }
+
+static __INLINE void __enable_fault_irq() { __ASM volatile ("cpsie f"); }
+static __INLINE void __disable_fault_irq() { __ASM volatile ("cpsid f"); }
+
+static __INLINE void __NOP() { __ASM volatile ("nop"); }
+static __INLINE void __WFI() { __ASM volatile ("wfi"); }
+static __INLINE void __WFE() { __ASM volatile ("wfe"); }
+static __INLINE void __SEV() { __ASM volatile ("sev"); }
+static __INLINE void __ISB() { __ASM volatile ("isb"); }
+static __INLINE void __DSB() { __ASM volatile ("dsb"); }
+static __INLINE void __DMB() { __ASM volatile ("dmb"); }
+
+
+/**
+ * @brief Return the Process Stack Pointer
+ *
+ * @return ProcessStackPointer
+ *
+ * Return the actual process stack pointer
+ */
+extern uint32_t __get_PSP(void);
+
+/**
+ * @brief Set the Process Stack Pointer
+ *
+ * @param topOfProcStack Process Stack Pointer
+ *
+ * Assign the value ProcessStackPointer to the MSP
+ * (process stack pointer) Cortex processor register
+ */
+extern void __set_PSP(uint32_t topOfProcStack);
+
+/**
+ * @brief Return the Main Stack Pointer
+ *
+ * @return Main Stack Pointer
+ *
+ * Return the current value of the MSP (main stack pointer)
+ * Cortex processor register
+ */
+extern uint32_t __get_MSP(void);
+
+/**
+ * @brief Set the Main Stack Pointer
+ *
+ * @param topOfMainStack Main Stack Pointer
+ *
+ * Assign the value mainStackPointer to the MSP
+ * (main stack pointer) Cortex processor register
+ */
+extern void __set_MSP(uint32_t topOfMainStack);
+
+/**
+ * @brief Return the Priority Mask value
+ *
+ * @return PriMask
+ *
+ * Return state of the priority mask bit from the priority mask register
+ */
+extern uint32_t __get_PRIMASK(void);
+
+/**
+ * @brief Set the Priority Mask value
+ *
+ * @param priMask PriMask
+ *
+ * Set the priority mask bit in the priority mask register
+ */
+extern void __set_PRIMASK(uint32_t priMask);
+
+/**
+ * @brief Return the Control Register value
+*
+* @return Control value
+ *
+ * Return the content of the control register
+ */
+extern uint32_t __get_CONTROL(void);
+
+/**
+ * @brief Set the Control Register value
+ *
+ * @param control Control value
+ *
+ * Set the control register
+ */
+extern void __set_CONTROL(uint32_t control);
+
+/**
+ * @brief Reverse byte order in integer value
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in integer value
+ */
+extern uint32_t __REV(uint32_t value);
+
+/**
+ * @brief Reverse byte order in unsigned short value
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in unsigned short value
+ */
+extern uint32_t __REV16(uint16_t value);
+
+/**
+ * @brief Reverse byte order in signed short value with sign extension to integer
+ *
+ * @param value value to reverse
+ * @return reversed value
+ *
+ * Reverse byte order in signed short value with sign extension to integer
+ */
+extern int32_t __REVSH(int16_t value);
+
+
+#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
+/* TASKING carm specific functions */
+
+/*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all instrinsics,
+ * Including the CMSIS ones.
+ */
+
+#endif
+
+
+/** @addtogroup CMSIS_CM0_Core_FunctionInterface CMSIS CM0 Core Function Interface
+ Core Function Interface containing:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Reset Functions
+*/
+/*@{*/
+
+/* ########################## NVIC functions #################################### */
+
+/* Interrupt Priorities are WORD accessible only under ARMv6M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 )
+#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) )
+#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) )
+
+
+/**
+ * @brief Enable Interrupt in NVIC Interrupt Controller
+ *
+ * @param IRQn The positive number of the external interrupt to enable
+ *
+ * Enable a device specific interupt in the NVIC interrupt controller.
+ * The interrupt number cannot be a negative value.
+ */
+static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
+}
+
+/**
+ * @brief Disable the interrupt line for external interrupt specified
+ *
+ * @param IRQn The positive number of the external interrupt to disable
+ *
+ * Disable a device specific interupt in the NVIC interrupt controller.
+ * The interrupt number cannot be a negative value.
+ */
+static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */
+}
+
+/**
+ * @brief Read the interrupt pending bit for a device specific interrupt source
+ *
+ * @param IRQn The number of the device specifc interrupt
+ * @return 1 = interrupt pending, 0 = interrupt not pending
+ *
+ * Read the pending register in NVIC and return 1 if its status is pending,
+ * otherwise it returns 0
+ */
+static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */
+}
+
+/**
+ * @brief Set the pending bit for an external interrupt
+ *
+ * @param IRQn The number of the interrupt for set pending
+ *
+ * Set the pending bit for the specified interrupt.
+ * The interrupt number cannot be a negative value.
+ */
+static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
+}
+
+/**
+ * @brief Clear the pending bit for an external interrupt
+ *
+ * @param IRQn The number of the interrupt for clear pending
+ *
+ * Clear the pending bit for the specified interrupt.
+ * The interrupt number cannot be a negative value.
+ */
+static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
+}
+
+/**
+ * @brief Set the priority for an interrupt
+ *
+ * @param IRQn The number of the interrupt for set priority
+ * @param priority The priority to set
+ *
+ * Set the priority for the specified interrupt. The interrupt
+ * number can be positive to specify an external (device specific)
+ * interrupt, or negative to specify an internal (core) interrupt.
+ *
+ * Note: The priority cannot be set for every core interrupt.
+ */
+static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if(IRQn < 0) {
+ SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
+ (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
+ else {
+ NVIC->IPR[_IP_IDX(IRQn)] = (NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |
+ (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }
+}
+
+/**
+ * @brief Read the priority for an interrupt
+ *
+ * @param IRQn The number of the interrupt for get priority
+ * @return The priority for the interrupt
+ *
+ * Read the priority for the specified interrupt. The interrupt
+ * number can be positive to specify an external (device specific)
+ * interrupt, or negative to specify an internal (core) interrupt.
+ *
+ * The returned priority value is automatically aligned to the implemented
+ * priority bits of the microcontroller.
+ *
+ * Note: The priority cannot be set for every core interrupt.
+ */
+static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if(IRQn < 0) {
+ return((uint32_t)((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
+ else {
+ return((uint32_t)((NVIC->IPR[_IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
+}
+
+
+
+/* ################################## SysTick function ############################################ */
+
+#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0)
+
+/**
+ * @brief Initialize and start the SysTick counter and its interrupt.
+ *
+ * @param ticks number of ticks between two interrupts
+ * @return 1 = failed, 0 = successful
+ *
+ * Initialise the system tick timer and its interrupt and start the
+ * system tick timer / counter in free running mode to generate
+ * periodical interrupts.
+ */
+static __INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
+
+ SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
+ SysTick->VAL = 0; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0); /* Function successful */
+}
+
+#endif
+
+
+
+
+/* ################################## Reset function ############################################ */
+
+/**
+ * @brief Initiate a system reset request.
+ *
+ * Initiate a system reset request to reset the MCU
+ */
+static __INLINE void NVIC_SystemReset(void)
+{
+ SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+ while(1); /* wait until reset */
+}
+
+/*@}*/ /* end of group CMSIS_CM0_Core_FunctionInterface */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*@}*/ /* end of group CMSIS_CM0_core_definitions */
+
+#endif /* __CM0_CORE_H__ */
+
+/*lint -restore */
diff --git a/src/core/cr_cpp_config.cpp b/src/core/cr_cpp_config.cpp new file mode 100755 index 0000000..8577b2d --- /dev/null +++ b/src/core/cr_cpp_config.cpp @@ -0,0 +1,56 @@ +//*****************************************************************************
+// +--+
+// | ++----+
+// +-++ |
+// | |
+// +-+--+ |
+// | +--+--+
+// +----+ Copyright (c) 2009-10 Code Red Technologies Ltd.
+//
+// Microcontroller Startup code for use with Red Suite
+//
+// Version : 101026
+//
+// Software License Agreement
+//
+// The software is owned by Code Red Technologies and/or its suppliers, and is
+// protected under applicable copyright laws. All rights are reserved. Any
+// use in violation of the foregoing restrictions may subject the user to criminal
+// sanctions under applicable laws, as well as to civil liability for the breach
+// of the terms and conditions of this license.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
+// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
+// CODE RED TECHNOLOGIES LTD.
+//
+//*****************************************************************************
+
+#define $(CPPHeapFlag)
+
+#include <stdlib.h>
+
+void *operator new(size_t size) throw() {
+ return malloc(size);
+}
+void operator delete(void *p) throw() {
+ free(p);
+}
+
+extern "C" int __aeabi_atexit(void *object,
+ void (*destructor)(void *),
+ void *dso_handle)
+{
+ return 0;
+}
+
+#ifdef CPP_NO_HEAP
+extern "C" void *malloc(size_t) {
+ return (void *)0;
+}
+
+extern "C" void free(void *) {
+}
+#endif
diff --git a/src/core/cr_startup_lpc11.cpp b/src/core/cr_startup_lpc11.cpp new file mode 100755 index 0000000..e58e676 --- /dev/null +++ b/src/core/cr_startup_lpc11.cpp @@ -0,0 +1,383 @@ +//*****************************************************************************
+// +--+
+// | ++----+
+// +-++ |
+// | |
+// +-+--+ |
+// | +--+--+
+// +----+ Copyright (c) 2009-10 Code Red Technologies Ltd.
+//
+// Microcontroller Startup code for use with Red Suite
+//
+// Version : 101130
+//
+// Software License Agreement
+//
+// The software is owned by Code Red Technologies and/or its suppliers, and is
+// protected under applicable copyright laws. All rights are reserved. Any
+// use in violation of the foregoing restrictions may subject the user to criminal
+// sanctions under applicable laws, as well as to civil liability for the breach
+// of the terms and conditions of this license.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
+// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
+// CODE RED TECHNOLOGIES LTD.
+//
+//*****************************************************************************
+#if defined (__cplusplus)
+#ifdef __REDLIB__
+#error Redlib does not support C++
+#else
+//*****************************************************************************
+//
+// The entry point for the C++ library startup
+//
+//*****************************************************************************
+
+extern "C" void __cxa_pure_virtual() {
+ while (1);
+}
+
+
+extern "C" {
+ extern void __libc_init_array(void);
+}
+#endif
+#endif
+
+#define WEAK __attribute__ ((weak))
+#define ALIAS(f) __attribute__ ((weak, alias (#f)))
+
+// Code Red - if CMSIS is being used, then SystemInit() routine
+// will be called by startup code rather than in application's main()
+//#if defined (__USE_CMSIS)
+#include "system_LPC11xx.h"
+//#endif
+
+//*****************************************************************************
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+//*****************************************************************************
+//
+// Forward declaration of the default handlers. These are aliased.
+// When the application defines a handler (with the same name), this will
+// automatically take precedence over these weak definitions
+//
+//*****************************************************************************
+ void ResetISR(void);
+WEAK void NMI_Handler(void);
+WEAK void HardFault_Handler(void);
+WEAK void SVCall_Handler(void);
+WEAK void PendSV_Handler(void);
+WEAK void SysTick_Handler(void);
+WEAK void IntDefaultHandler(void);
+//*****************************************************************************
+//
+// Forward declaration of the specific IRQ handlers. These are aliased
+// to the IntDefaultHandler, which is a 'forever' loop. When the application
+// defines a handler (with the same name), this will automatically take
+// precedence over these weak definitions
+//
+//*****************************************************************************
+
+void CAN_IRQHandler (void) ALIAS(IntDefaultHandler);
+void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void I2C_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void UART_IRQHandler (void) ALIAS(IntDefaultHandler);
+void ADC_IRQHandler (void) ALIAS(IntDefaultHandler);
+void WDT_IRQHandler (void) ALIAS(IntDefaultHandler);
+void BOD_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIOINT3_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIOINT2_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIOINT1_IRQHandler (void) ALIAS(IntDefaultHandler);
+void PIOINT0_IRQHandler (void) ALIAS(IntDefaultHandler);
+void WAKEUP_IRQHandler (void) ALIAS(IntDefaultHandler);
+
+//*****************************************************************************
+//
+// The entry point for the application.
+// __main() is the entry point for redlib based applications
+// main() is the entry point for newlib based applications
+//
+//*****************************************************************************
+//
+// The entry point for the application.
+// __main() is the entry point for Redlib based applications
+// main() is the entry point for Newlib based applications
+//
+//*****************************************************************************
+#if defined (__REDLIB__)
+extern void __main(void);
+#endif
+extern int main(void);
+//*****************************************************************************
+//
+// External declaration for the pointer to the stack top from the Linker Script
+//
+//*****************************************************************************
+extern void _vStackTop(void);
+
+//*****************************************************************************
+#if defined (__cplusplus)
+} // extern "C"
+#endif
+//*****************************************************************************
+//
+// The vector table. Note that the proper constructs must be placed on this to
+// ensure that it ends up at physical address 0x0000.0000.
+//
+//*****************************************************************************
+extern void (* const g_pfnVectors[])(void);
+__attribute__ ((section(".isr_vector")))
+void (* const g_pfnVectors[])(void) = {
+ &_vStackTop, // The initial stack pointer
+ ResetISR, // The reset handler
+ NMI_Handler, // The NMI handler
+ HardFault_Handler, // The hard fault handler
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ SVCall_Handler, // SVCall handler
+ 0, // Reserved
+ 0, // Reserved
+ PendSV_Handler, // The PendSV handler
+ SysTick_Handler, // The SysTick handler
+
+ // Wakeup sources for the I/O pins:
+ // PIO0 (0:11)
+ // PIO1 (0)
+ WAKEUP_IRQHandler, // PIO0_0 Wakeup
+ WAKEUP_IRQHandler, // PIO0_1 Wakeup
+ WAKEUP_IRQHandler, // PIO0_2 Wakeup
+ WAKEUP_IRQHandler, // PIO0_3 Wakeup
+ WAKEUP_IRQHandler, // PIO0_4 Wakeup
+ WAKEUP_IRQHandler, // PIO0_5 Wakeup
+ WAKEUP_IRQHandler, // PIO0_6 Wakeup
+ WAKEUP_IRQHandler, // PIO0_7 Wakeup
+ WAKEUP_IRQHandler, // PIO0_8 Wakeup
+ WAKEUP_IRQHandler, // PIO0_9 Wakeup
+ WAKEUP_IRQHandler, // PIO0_10 Wakeup
+ WAKEUP_IRQHandler, // PIO0_11 Wakeup
+ WAKEUP_IRQHandler, // PIO1_0 Wakeup
+
+ CAN_IRQHandler, // C_CAN Interrupt
+ SSP1_IRQHandler, // SPI/SSP1 Interrupt
+ I2C_IRQHandler, // I2C0
+ TIMER16_0_IRQHandler, // CT16B0 (16-bit Timer 0)
+ TIMER16_1_IRQHandler, // CT16B1 (16-bit Timer 1)
+ TIMER32_0_IRQHandler, // CT32B0 (32-bit Timer 0)
+ TIMER32_1_IRQHandler, // CT32B1 (32-bit Timer 1)
+ SSP0_IRQHandler, // SPI/SSP0 Interrupt
+ UART_IRQHandler, // UART0
+
+ 0, // Reserved
+ 0, // Reserved
+
+ ADC_IRQHandler, // ADC (A/D Converter)
+ WDT_IRQHandler, // WDT (Watchdog Timer)
+ BOD_IRQHandler, // BOD (Brownout Detect)
+ 0, // Reserved
+ PIOINT3_IRQHandler, // PIO INT3
+ PIOINT2_IRQHandler, // PIO INT2
+ PIOINT1_IRQHandler, // PIO INT1
+ PIOINT0_IRQHandler, // PIO INT0
+};
+
+//*****************************************************************************
+// Functions to carry out the initialization of RW and BSS data sections. These
+// are written as separate functions rather than being inlined within the
+// ResetISR() function in order to cope with MCUs with multiple banks of
+// memory.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void data_init(unsigned int romstart, unsigned int start, unsigned int len) {
+ unsigned int *pulDest = (unsigned int*) start;
+ unsigned int *pulSrc = (unsigned int*) romstart;
+ unsigned int loop;
+ for (loop = 0; loop < len; loop = loop + 4)
+ *pulDest++ = *pulSrc++;
+}
+
+__attribute__ ((section(".after_vectors")))
+void bss_init(unsigned int start, unsigned int len) {
+ unsigned int *pulDest = (unsigned int*) start;
+ unsigned int loop;
+ for (loop = 0; loop < len; loop = loop + 4)
+ *pulDest++ = 0;
+}
+
+#ifndef USE_OLD_STYLE_DATA_BSS_INIT
+//*****************************************************************************
+// The following symbols are constructs generated by the linker, indicating
+// the location of various points in the "Global Section Table". This table is
+// created by the linker via the Code Red managed linker script mechanism. It
+// contains the load address, execution address and length of each RW data
+// section and the execution and length of each BSS (zero initialized) section.
+//*****************************************************************************
+extern unsigned int __data_section_table;
+extern unsigned int __data_section_table_end;
+extern unsigned int __bss_section_table;
+extern unsigned int __bss_section_table_end;
+#else
+//*****************************************************************************
+// The following symbols are constructs generated by the linker, indicating
+// the load address, execution address and length of the RW data section and
+// the execution and length of the BSS (zero initialized) section.
+// Note that these symbols are not normally used by the managed linker script
+// mechanism in Red Suite/LPCXpresso 3.6 (Windows) and LPCXpresso 3.8 (Linux).
+// They are provide here simply so this startup code can be used with earlier
+// versions of Red Suite which do not support the more advanced managed linker
+// script mechanism introduced in the above version. To enable their use,
+// define "USE_OLD_STYLE_DATA_BSS_INIT".
+//*****************************************************************************
+extern unsigned int _etext;
+extern unsigned int _data;
+extern unsigned int _edata;
+extern unsigned int _bss;
+extern unsigned int _ebss;
+#endif
+
+
+//*****************************************************************************
+// Reset entry point for your code.
+// Sets up a simple runtime environment and initializes the C/C++
+// library.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void
+ResetISR(void) {
+
+#ifndef USE_OLD_STYLE_DATA_BSS_INIT
+ //
+ // Copy the data sections from flash to SRAM.
+ //
+ unsigned int LoadAddr, ExeAddr, SectionLen;
+ unsigned int *SectionTableAddr;
+
+ // Load base address of Global Section Table
+ SectionTableAddr = &__data_section_table;
+
+ // Copy the data sections from flash to SRAM.
+ while (SectionTableAddr < &__data_section_table_end) {
+ LoadAddr = *SectionTableAddr++;
+ ExeAddr = *SectionTableAddr++;
+ SectionLen = *SectionTableAddr++;
+ data_init(LoadAddr, ExeAddr, SectionLen);
+ }
+ // At this point, SectionTableAddr = &__bss_section_table;
+ // Zero fill the bss segment
+ while (SectionTableAddr < &__bss_section_table_end) {
+ ExeAddr = *SectionTableAddr++;
+ SectionLen = *SectionTableAddr++;
+ bss_init(ExeAddr, SectionLen);
+ }
+#else
+ // Use Old Style Data and BSS section initialization.
+ // This will only initialize a single RAM bank.
+ unsigned int * LoadAddr, *ExeAddr, *EndAddr, SectionLen;
+
+ // Copy the data segment from flash to SRAM.
+ LoadAddr = &_etext;
+ ExeAddr = &_data;
+ EndAddr = &_edata;
+ SectionLen = (void*)EndAddr - (void*)ExeAddr;
+ data_init((unsigned int)LoadAddr, (unsigned int)ExeAddr, SectionLen);
+ // Zero fill the bss segment
+ ExeAddr = &_bss;
+ EndAddr = &_ebss;
+ SectionLen = (void*)EndAddr - (void*)ExeAddr;
+ bss_init ((unsigned int)ExeAddr, SectionLen);
+#endif
+
+//#ifdef __USE_CMSIS
+ SystemInit();
+//#endif
+
+#if defined (__cplusplus)
+ //
+ // Call C++ library initialisation
+ //
+ __libc_init_array();
+#endif
+
+#if defined (__REDLIB__)
+ // Call the Redlib library, which in turn calls main()
+ __main() ;
+#else
+ main();
+#endif
+ //
+ // main() shouldn't return, but if it does, we'll just enter an infinite loop
+ //
+ while (1) {
+ ;
+ }
+}
+//*****************************************************************************
+// Default exception handlers. Override the ones here by defining your own
+// handler routines in your application code.
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void NMI_Handler(void)
+{
+ while(1)
+ {
+ }
+}
+__attribute__ ((section(".after_vectors")))
+void HardFault_Handler(void)
+{
+ while(1)
+ {
+ }
+}
+__attribute__ ((section(".after_vectors")))
+void SVCall_Handler(void)
+{
+ while(1)
+ {
+ }
+}
+__attribute__ ((section(".after_vectors")))
+void PendSV_Handler(void)
+{
+ while(1)
+ {
+ }
+}
+__attribute__ ((section(".after_vectors")))
+void SysTick_Handler(void)
+{
+ while(1)
+ {
+ }
+}
+
+//*****************************************************************************
+//
+// Processor ends up here if an unexpected interrupt occurs or a specific
+// handler is not present in the application code.
+//
+//*****************************************************************************
+__attribute__ ((section(".after_vectors")))
+void IntDefaultHandler(void)
+{
+ while(1)
+ {
+ }
+}
+
diff --git a/src/core/delay.cpp b/src/core/delay.cpp new file mode 100755 index 0000000..9d46a23 --- /dev/null +++ b/src/core/delay.cpp @@ -0,0 +1,123 @@ +/*
+ * systick.cpp
+ *
+ * Created on: 2011/08/11
+ * Author: atsu
+ */
+
+#include "delay.h"
+
+volatile static unsigned long msTicks; /* counts 1ms timeTicks */
+volatile USER_TIMER_FUNC userfunc; //user function's pointer
+
+/*------------------------------------------------------------------------------
+ delays number of tick Systicks (happens every 1 ms)
+ *------------------------------------------------------------------------------*/
+void delay (unsigned long dlyTicks) {
+ volatile unsigned long curTicks;
+
+ curTicks = msTicks;
+ while ((msTicks - curTicks) < dlyTicks);
+}
+
+
+unsigned long millis(void)
+{
+ return msTicks;
+}
+
+void delayMicroseconds (unsigned long us)
+{
+ volatile unsigned long usTicks;
+
+ //LPC_TMR16B0->TC = 0; //reset timer counter
+ usTicks = LPC_TMR32B1->TC; //usTicks = micros();
+ while ((LPC_TMR32B1->TC - usTicks) < us); //while ((micros() - usTicks) < us);
+
+}
+
+unsigned long micros(void)
+{
+ return LPC_TMR32B1->TC;
+}
+
+//for micros() and delayMicroseconds()
+void setup_TIMER32_1(void)
+{
+ attachMicroseconds(0,0xffffffff);
+ NVIC_DisableIRQ(TIMER_32_1_IRQn);
+}
+
+unsigned long attachMicroseconds(USER_TIMER_FUNC func,int us)
+{
+ LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 10); // Enable clock for CT32B1 module
+ if(us <= 1)return 0;
+
+ LPC_TMR32B1->PR = 48; //48MHz/48=1MHzに分周する
+ LPC_TMR32B1->MR2 = us - 1; //us
+
+ LPC_TMR32B1->MCR = (0x3 << 6); // clear at MR2 and Interrupt
+
+ NVIC_EnableIRQ(TIMER_32_1_IRQn);
+ NVIC_SetPriority(TIMER_32_1_IRQn,0);//割り込みレベル
+ LPC_TMR32B1->TCR = 1; //タイマスタート
+
+ userfunc = func;
+
+ return 0;
+}
+
+void detachMicroseconds(void)
+{
+ LPC_TMR32B1->MR2 = 0xffffffff; //us
+ NVIC_DisableIRQ(TIMER_32_1_IRQn);
+
+}
+
+/*----------------------------------------------------------------------------
+ Timer32_0_Handler
+ *----------------------------------------------------------------------------*/
+void TIMER32_1_IRQHandler (void)
+{
+ if (LPC_TMR32B1->IR & (1 << 2)) // MR2 Interrupt
+ {
+ if(userfunc)userfunc();
+
+ // Clear Flag
+ LPC_TMR32B1->IR = (1 << 2);
+ }
+}
+
+/*----------------------------------------------------------------------------
+ SysTick_Handler
+ *----------------------------------------------------------------------------*/
+void SysTick_Handler(void) {
+ msTicks++; /* increment counter necessary in Delay() */
+}
+
+void setup_systick (void) {
+
+ //LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
+
+ // Setup SysTick Timer for 1 msec interrupts
+ // Configure System tick timer in 10msec period
+ volatile unsigned long period = SystemCoreClock / 1000; // Period for 1msec SYSTICK
+ SysTick_Config(period); // Configuration
+
+#if 1
+ if ( !(SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk) )
+ {
+ /* When external reference clock is used(CLKSOURCE in
+ Systick Control and register bit 2 is set to 0), the
+ SYSTICKCLKDIV must be a non-zero value and 2.5 times
+ faster than the reference clock.
+ When core clock, or system AHB clock, is used(CLKSOURCE
+ in Systick Control and register bit 2 is set to 1), the
+ SYSTICKCLKDIV has no effect to the SYSTICK frequency. See
+ more on Systick clock and status register in Cortex-M3
+ technical Reference Manual. */
+ LPC_SYSCON->SYSTICKCLKDIV = 0x08;
+ }
+#endif
+}
+
diff --git a/src/core/delay.h b/src/core/delay.h new file mode 100755 index 0000000..f72d31f --- /dev/null +++ b/src/core/delay.h @@ -0,0 +1,64 @@ +/*
+ * systick.h
+ *
+ * Created on: 2011/08/11
+ * Author: atsu
+ */
+
+#ifndef SYSTICK_H_
+#define SYSTICK_H_
+
+/**************************************************************************//**
+ * @file systick.h
+ * @brief Arduino-like library for MARY(LPC1114)
+ * @version v.0.50
+ * @date 1. August 2011.
+ * @author this library's assembled by @@dw256 and rebuild by @@lynxeyed_atsu
+ * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR>
+ * 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: <BR>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.<BR>
+ * 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 "LPC11xx.h"
+#include "system_LPC11xx.h"
+#include "uart.h"
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+typedef void (* USER_TIMER_FUNC)(void);
+
+void delay(unsigned long dlyTicks);
+void delayMicroseconds(unsigned long us);
+unsigned long millis(void);
+//low level
+void SysTick_Handler(void);
+void setup_systick (void);
+unsigned long micros(void);
+unsigned long attachMicroseconds(USER_TIMER_FUNC func,int us);
+void detachMicroseconds(void);
+
+void setup_TIMER32_1(void);
+void TIMER32_1_IRQHandler (void);
+
+#endif /* SYSTICK_H_ */
+
+#ifdef __cplusplus
+ }
+#endif
diff --git a/src/core/gpio.cpp b/src/core/gpio.cpp new file mode 100755 index 0000000..1a7b18e --- /dev/null +++ b/src/core/gpio.cpp @@ -0,0 +1,102 @@ +#include "gpio.h" + + +/* ======================================= +* Macros and functions for Defining MARY's GPIO Assign +* +* CN1_7,8 : (PIO1_2,PIO1_1) +* should be C17,C18 +* +* CN2_1...8 : (PIO1_4,PIO1_11,PIO1_7,PIO1_5,PIO3_2,PIO2_0,PIO1_6,PIO0_1) +* should be C21,C22,C23,C24,C25,C26,C27,C28 +* +* CN3_1...8 : (PIO1_8,PIO0_3,PIO0_2,PIO3_4,PIO0_4,PIO3_5,PIO0_5,PIO1_7) +* should be C31,C32,C33,C34,C35,C36,C37,C38 +* +* CN4_1...7 : (PIO1_9,PIO1_10,PIO0_6,PIO0_11,PIO0_8,PIO1_0,PIO0_9) +* should be C41,C42,C43,C44,C45,C46,C47 +* +* see also mary_pinAssign[...] in "gpio.h" +* ======================================= +*/ +void pinMode(int pin,pinModeState state) +{ + if(pin < 20) //arduinoPinAssign(0~19) + { + if(state == OUTPUT) //OUTPUT + { + LPC_GPIO[ arduino_pinAssign[pin * 2] ]->DIR |= arduino_pinAssign[pin * 2 + 1]; + }else //INPUT + { + LPC_GPIO[ arduino_pinAssign[pin * 2] ]->DIR &= ~(arduino_pinAssign[pin * 2 + 1]); + } + return; + } + + if(pin < 100) return; //(20~99:reserved) + + if(pin < 200) //maryPinAssign(100~119?) + { + pin = pin - 100; + if(state == OUTPUT) //OUTPUT + { + LPC_GPIO[ mary_pinAssign[pin * 2] ]->DIR |= mary_pinAssign[pin * 2 + 1]; + }else //INPUT + { + LPC_GPIO[ mary_pinAssign[pin * 2] ]->DIR &= ~(mary_pinAssign[pin * 2 + 1]); + } + } + return; + } + +void digitalWrite(int pin,digitalWriteState state) +{ + if(pin < 20) //arduinoPinAssign(0~19) + { + if(state == HIGH) //HIGH + { + LPC_GPIO[ arduino_pinAssign[pin * 2] ]->MASKED_ACCESS[ arduino_pinAssign[pin * 2 + 1] ] = arduino_pinAssign[pin * 2 + 1]; + }else //LOW + { + LPC_GPIO[ arduino_pinAssign[pin * 2] ]->MASKED_ACCESS[ arduino_pinAssign[pin * 2 + 1] ] &= ~(arduino_pinAssign[pin * 2 + 1]); + } + return; + } + + if(pin < 100) return; //arduinoPinAssign(20~99:reserved) + + if(pin < 200) //maryPinAssign(100~119?) + { + pin = pin - 100; + if(state == HIGH) //HIGH + { + LPC_GPIO[ mary_pinAssign[pin * 2] ]->MASKED_ACCESS[ mary_pinAssign[pin * 2 + 1] ] = mary_pinAssign[pin * 2 + 1]; + }else //LOW + { + LPC_GPIO[ mary_pinAssign[pin * 2] ]->MASKED_ACCESS[ mary_pinAssign[pin * 2 + 1] ] &= ~(mary_pinAssign[pin * 2 + 1]); + } + } + return; + } + +int digitalRead(int pin) +{ + volatile int readValue; + if(pin < 20) //arduinoPinAssign(0~19) + { + readValue = (LPC_GPIO[ arduino_pinAssign[pin * 2] ]->MASKED_ACCESS[ arduino_pinAssign[pin * 2 + 1] ])? 1 : 0; + return readValue; + } + + if(pin < 100) return 0; //(20~99:reserved) + + if(pin < 200) //maryPinAssign(100~199?) + { + pin = pin - 100; + readValue = (LPC_GPIO[ mary_pinAssign[pin * 2] ]->MASKED_ACCESS[ mary_pinAssign[pin * 2 + 1] ])? 1 : 0; + return readValue; + } + return 0; +} + + diff --git a/src/core/gpio.h b/src/core/gpio.h new file mode 100755 index 0000000..5b7c05c --- /dev/null +++ b/src/core/gpio.h @@ -0,0 +1,194 @@ +/* + * gpio.h + * + * Created on: 2011/07/27 + * Author: lynxeyed + */ +#ifndef GPIO_H_ +#define GPIO_H_ + +//#if defined (__USE_CMSIS) +#include "LPC11xx.h" +//#endif +//======================================= +// Define LPC_GPIO[4] (each top address) +//======================================= +static LPC_GPIO_TypeDef (* const LPC_GPIO[4]) = { LPC_GPIO0, LPC_GPIO1, LPC_GPIO2, LPC_GPIO3 }; + +/* ======================================= +* Macros and functions for Defining MARY's GPIO Assign +* +* CN1_7,8 : (PIO1_2,PIO1_1) +* should be C17,C18 +* +* CN2_1...8 : (PIO1_4,PIO1_11,PIO1_7,PIO1_5,PIO3_2,PIO2_0,PIO1_6,PIO0_1) +* should be C21,C22,C23,C24,C25,C26,C27,C28 +* +* CN3_1...8 : (PIO1_8,PIO0_3,PIO0_2,PIO3_4,PIO0_4,PIO3_5,PIO0_5,PIO1_7) +* should be C31,C32,C33,C34,C35,C36,C37,C38 +* +* CN4_1...7 : (PIO1_9,PIO1_10,PIO0_6,PIO0_11,PIO0_8,PIO1_0,PIO0_9) +* should be C41,C42,C43,C44,C45,C46,C47 +* ======================================= +*/ +#define C17 (100) +#define C18 (101) + +#define C21 (102) +#define C22 (103) +#define C23 (104) +#define C24 (105) +#define C25 (106) +#define C26 (107) +#define C27 (108) +#define C28 (109) + +#define C31 (110) +#define C32 (111) +#define C33 (112) +#define C34 (113) +#define C35 (114) +#define C36 (115) +#define C37 (116) +#define C38 (117) + +#define C41 (118) +#define C42 (119) +#define C43 (120) +#define C44 (121) +#define C45 (122) +#define C46 (123) +#define C47 (124) +#define GLED (125) +#define BLED (126) +#define RLED (127) + +// For LPCXpresso LPC1114 +#define P1_2 (100) +#define P1_1 (101) +#define P1_4 (102) +#define P1_11 (103) +#define P1_7 (104) +#define P1_5 (105) +#define P3_2 (106) +#define P2_0 (107) +#define P1_6 (108) +#define P0_1 (109) +#define P1_8 (110) +#define P0_3 (111) +#define P0_2 (112) +#define P3_4 (113) +#define P0_4 (114) +#define P3_5 (115) +#define P0_5 (116) +//#define P1_7 (117) +#define P1_9 (118) +#define P1_10 (119) +#define P0_6 (120) +#define P0_11 (121) +#define P0_8 (122) +#define P1_0 (123) +#define P0_9 (124) +#define P0_7 (125) +//#define P1_5 (126) +//#define P2_0 (127) + +#define _BIT0 (1U << 0) +#define _BIT1 (1U << 1) +#define _BIT2 (1U << 2) +#define _BIT3 (1U << 3) +#define _BIT4 (1U << 4) +#define _BIT5 (1U << 5) +#define _BIT6 (1U << 6) +#define _BIT7 (1U << 7) +#define _BIT8 (1U << 8) +#define _BIT9 (1U << 9) +#define _BIT10 (1U << 10) +#define _BIT11 (1U << 11) + +const unsigned int mary_pinAssign[] = +{ + 1, _BIT2, //CN1_7 + 1, _BIT1, //CN1_8 + + 1, _BIT4, //CN2_1 + 1, _BIT11, //CN2_2 + 1, _BIT7, //CN2_3 + 1, _BIT5, //CN2_4 + 3, _BIT2, //CN2_5 + 2, _BIT0, //CN2_6 + 1, _BIT6, //CN2_7 + 0, _BIT1, //CN2_8 + + 1, _BIT8, //CN3_1 + 0, _BIT3, //CN3_2 + 0, _BIT2, //CN3_3 + 3, _BIT4, //CN3_4 + 0, _BIT4, //CN3_5 + 3, _BIT5, //CN3_6 + 0, _BIT5, //CN3_7 + 1, _BIT7, //CN3_8 + + 1, _BIT9, //CN4_1 + 1, _BIT10, //CN4_2 + 0, _BIT6, //CN4_3 + 0, _BIT11, //CN4_4 + 0, _BIT8, //CN4_5 + 1, _BIT0, //CN4_6 + 0, _BIT9, //CN4_7 + 0, _BIT7, //GLED + 1, _BIT5, //BLED + 2, _BIT0 //RLED +}; + + +// Arduino's pins assign +const unsigned int arduino_pinAssign[] = +{ + 1, _BIT6, //P1_6:D0/RX + 1, _BIT7, //P1_7:D1/TX + 0, _BIT3, //P0_3:D2 + 1, _BIT9, //P1_9:D3 + 3, _BIT4, //P3_4:D4 + 2, _BIT4, //P2_4:D5 + 2, _BIT0, //P2_0:D6 + 2, _BIT3, //P2_3:D7 + 2, _BIT2, //P2_2:D8 + 2, _BIT1, //P2_1:D9 + 0, _BIT2, //P0_2:D10 + + 0, _BIT9, //P0_9:D11 + 0, _BIT8, //P0_8:D12 + 0, _BIT6, //P0_6:D13 + + +/* 0, _BIT4, //P + 3, _BIT5, //CN3_6 + 0, _BIT5, //CN3_7 + 1, _BIT7, //CN3_8 + + 1, _BIT9, //CN4_1 + 1, _BIT10, //CN4_2 + 0, _BIT6, //CN4_3 + 0, _BIT11, //CN4_4 + 0, _BIT8, //CN4_5 + 1, _BIT0, //CN4_6 + 0, _BIT9, //CN4_7 + 0, _BIT7, //GLED + 1, _BIT5, //BLED + 2, _BIT0 //RLED +*/ +}; + + +typedef enum {INPUT, OUTPUT}pinModeState; +typedef enum {LOW, HIGH}digitalWriteState; + +void pinMode(int pin,pinModeState state); +void digitalWrite(int pin,digitalWriteState state); +int digitalRead(int pin); + + + + +#endif /* GPIO_H_ */ diff --git a/src/core/libmary.h b/src/core/libmary.h new file mode 100755 index 0000000..eedd3ab --- /dev/null +++ b/src/core/libmary.h @@ -0,0 +1,60 @@ +#ifndef LIBMARY_H_ +#define LIBMARY_H_ + +/** + @mainpage MARY-DUINO (Beta) + @section abstruct 概要 + MARY-DUINOはNXP製LPC1114を搭載したMARY基板でArduinoライクな開発が出来ることを目指すC++ライブラリです + @section intro 始めに + CQ出版発行・圓山宗智氏によるトランジスタ技術増刊「2枚入り!組み合わせ自在!超小型ARMマイコン基板」に付属している基板をArduinoライクな環境で開発する為の + ライブラリです。 + @section motivation 背景 + 「2枚入り!組み合わせ自在!超小型ARMマイコン基板」に付属している基板の開発において、よく整備されているライブラリが圓山氏により準備されており、 + とても使いやすい環境が提供されています。このライブラリではよりお手軽に開発する事を目的としてC++ライブラリをフルスクラッチで作成しており、Arduinoライクな + 開発環境を提供しています。今後ここに新たなライブラリを追加し、より使いやすい環境を随時追加してゆきます + @section environmen 環境 + arm-none-eabi-gcc-4.5.0以上またはarm-elf-gcc-4.5.0以上 + - WindowsではCodesourcery G++かLPCXpresso IDEが動く環境 + - Mac OSXではSnow Leopard(10.6.1以上)ではXcode 3.4以上がインストール、Lion(10.7)ではXCode 4.1以上がインストールされており、arm-elf-gcc-4.5.0以上がインストールされている事 + @section history 履歴 + - 2011/07/15 初版作成 + */ + +/**************************************************************************//** + * @file libmary.h + * @brief Arduino-like library for MARY(LPC1114) + * @version v.0.50 + * @date 1. August 2011. + * @author @@lynxeyed_atsu + * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR> + * 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: <BR> + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.<BR> + * 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 "LPC11xx.h" +#include "system_LPC11xx.h" +#include "delay.h" +#include "gpio.h" +#include "uart.h" + + + +// init for arduino-like settings + + + +#endif /* LIBMARY_H_ */ diff --git a/src/core/maryoled.cpp b/src/core/maryoled.cpp new file mode 100755 index 0000000..8df935c --- /dev/null +++ b/src/core/maryoled.cpp @@ -0,0 +1,484 @@ +/* mbed Nokia LCD Library + * Atsu + */ + +#include "delay.h" +#include "maryoled.h" +#include <math.h> + +/** General parameters for MARMEX_OB_oled */ + +#define MARYOLED_ROWS 15 +#define MARYOLED_COLS 16 +#define MARYOLED_WIDTH 128 +#define MARYOLED_HEIGHT 128 +#define MARYOLED_FREQUENCY 20000000 + +//MARY Pin Assign +//#define OLED_VCC_ON C21 +//#define OLED_CS C33 +//#define OLED_RES C31 + +//LPCXpresso pin Assign (MARMEX-SLOT1) +//#define OLED_VCC_ON P0_7 +//#define OLED_CS P0_2 +//#define OLED_RES P0_1 + +MARYOLED oled; + +MARYOLED::MARYOLED() //default : MARY +{ + this->OLED_VCC_ON = C21; + this->OLED_CS = C33; + this->OLED_RES = C31; + this->device = OLED; + port = marySSP0; + _row = 0; + _column = 0; + _foreground = 0x00FFFFFF; + _background = 0x00000000; + +} + +MARYOLED::~MARYOLED() +{ +} +void MARYOLED::reset(SSP_PORT port) +{ + this->port = port; + if(port==LPCXSSP0) //LPCXpresso 1114 + MAPLE + { + this->OLED_VCC_ON = P0_7; + this->OLED_CS = P0_2; + this->OLED_RES = P0_1; + } + pinMode(OLED_VCC_ON,OUTPUT); + pinMode(OLED_RES,OUTPUT); + pinMode(OLED_CS,OUTPUT); + + digitalWrite(OLED_RES,HIGH); + digitalWrite(OLED_VCC_ON,LOW); + + reset(); + return; +} +void MARYOLED::reset() { + #define GAMMA_LUT_SIZE 63 + //unsigned char gamma_LUT[ GAMMA_LUT_SIZE ]; + + //for ( int i = 0; i < GAMMA_LUT_SIZE; i++ ) + //gamma_LUT[ i ] = (unsigned char)(powf( ((float)i / 62.0), (1.0 / 0.58) ) * 178.0 + 2.0); + unsigned char gamma_LUT[63] = + { + 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, + // + 0x12, 0x13, 0x15, 0x17, + 0x19, 0x1b, 0x1d, 0x1f, + 0x21, 0x23, 0x25, 0x27, + 0x2a, 0x2d, 0x30, 0x33, + // + 0x36, 0x39, 0x3c, 0x3f, + 0x42, 0x45, 0x48, 0x4c, + 0x50, 0x54, 0x58, 0x5c, + 0x60, 0x64, 0x68, 0x6c, + // + 0x70, 0x74, 0x78, 0x7d, + 0x82, 0x87, 0x8c, 0x91, + 0x96, 0x9b, 0xa0, 0xa5, + 0xaa, 0xaf, 0xb4 + }; + + // setup the _spi interface and bring display out of reset + digitalWrite( OLED_CS, HIGH ); + digitalWrite( OLED_RES, LOW ); + + + SPI.setBitLength( 9 ); //9bit mode + SPI.setDataMode(SPI_MODE3); + SPI.setClockDivider( SPI_CLOCK_DIV2 ); + SPI.begin(port); + //ssp_begin(SPI_CLOCK_DIV1, SPI_MODE0, 9); + + delay( 100 ); //wait 100ms + digitalWrite( OLED_RES, LOW ); + delay( 100 ); + digitalWrite( OLED_RES, HIGH ); //RESET + + command( SET_DISPLAY_MODE_ALL_OFF ); + + command( SET_COMMAND_LOCK ); + data( 0x12 ); + + command( SET_COMMAND_LOCK ); + data( 0xb1 ); + + command( SET_SLEEP_MODE_ON ); + + command( FRONT_CLOCK_DRIVER_OSC_FREQ ); + data( 0xF1 ); + + command( SET_MUX_RATIO ); + data( 0x7F ); + + command( SET_DISPAY_OFFSET ); + data( 0x00 ); + + command( SET_DISPAY_START_LINE ); + data( 0x00 ); + + command( SET_REMAP_COLOR_DEPTH ); + data( 0x74 ); + + command( SET_GPIO ); + data( 0x00); + + command( FUNCTION_SELECTION ); + data( 0x01 ); + + command( SET_SEGMENT_LOW_VOLTAGE ); + data( 0xA0 ); + data( 0xB5 ); + data( 0x55 ); + + command( SET_CONTRAST_CURRENT_FOR_COLOR_ABC ); + data( 0xC8 ); + data( 0x80 ); + data( 0xC8 ); + + command( MASTER_CONTRAST_CURRENT_CONTROL ); + data( 0x0F ); + + command( LOOKUP_TABLE_FOR_GRAYSCALE_PULSE_WIDTH ); + for ( int i = 0; i < GAMMA_LUT_SIZE; i++ ) + data( gamma_LUT[ i ] ); + + //command( USE_BUILT_IN_LINEAR_LUT ); + + command( SET_RESET_PRECHARGE_PERIOD ); + data( 0x32 ); + + command( ENHANCE_DRIVING_SCHEME_CAPABILITY ); + data( 0xA4 );//data( 0x04 ); + data( 0x00 ); + data( 0x00 ); + + command( SET_PRECHARGE_VOLTAGE ); + data( 0x17 ); + + command( SET_SECOND_PRECHARGE_VOLTAGE ); + data( 0x01 ); + + command( SET_VCOMH_VOLTAGE ); + data( 0x05 ); + command( SET_DISPLAY_MODE_RESET ); + + command( SET_COLUMN_ADDRESS ); + data( 0x00 ); + data( 0x7f ); + + command( SET_ROW_ADDRESS ); + data( 0x00 ); + data( 0x7f ); + + cls(); + //WindowReset(); + + digitalWrite(OLED_VCC_ON,HIGH); + + delay( 200 ); //wait 200ms + + command( SET_SLEEP_MODE_OFF ); + return; +} + +void MARYOLED::command(int value) { + + digitalWrite(OLED_CS,LOW); + SPI.transfer(value & 0xff); + //ssp_transfer(value & 0xFF); + digitalWrite(OLED_CS,HIGH); +} + +void MARYOLED::data(int value) { + digitalWrite(OLED_CS,LOW); + SPI.transfer(value | 0x100); + //ssp_transfer(value | 0x100); + digitalWrite(OLED_CS,HIGH); +} + +void MARYOLED::_window( int x, int y, int width, int height ) +{ + int x1 = x + 0; + int y1 = y + 0; + int x2 = x1 + width - 1; + int y2 = y1 + height - 1; + + command( SET_COLUMN_ADDRESS ); + data( x1 ); + data( x2 ); + command( SET_ROW_ADDRESS ); + data( y1 ); + data( y2 ); + command( WRITE_RAM_COMMAND ); + +} + +void MARYOLED::WindowReset(void) +{ + command( SET_COLUMN_ADDRESS ); + data( 0 ); + data( 127 ); + command( SET_ROW_ADDRESS ); + data( 0 ); + data( 127 ); + command( WRITE_RAM_COMMAND ); +} + + + + +const unsigned char FONT8x8[97][8] = { + {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, num_bytes_per_char + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space 0x20 + {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // ! + {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // " + {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # + {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $ + {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // % + {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // & + {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // ' + {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( + {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) + {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * + {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , + {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . + {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / (forward slash) + {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 0x30 + {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1 + {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2 + {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 + {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4 + {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5 + {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6 + {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7 + {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 + {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9 + {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : + {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; + {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // < + {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = + {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // > + {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? + {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ 0x40 + {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A + {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B + {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C + {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D + {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E + {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F + {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G + {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H + {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I + {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J + {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K + {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L + {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M + {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N + {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O + {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P 0x50 + {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q + {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R + {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S + {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T + {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U + {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V + {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W + {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X + {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y + {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z + {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ + {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // \ (back slash) + {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] + {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ + {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` 0x60 + {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a + {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b + {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c + {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d + {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e + {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f + {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g + {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h + {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i + {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j + {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k + {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l + {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m + {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n + {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o + {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p + {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q + {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r + {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s + {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t + {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u + {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v + {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w + {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x + {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y + {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z + {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { + {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | + {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } + {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ + {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} +}; // DEL + +void MARYOLED::locate(int column, int row) { + _column = column; + _row = row; +} + +void MARYOLED::newline() { + _column = 0; + _row++; + if (_row >= rows() ) { + _row = 0; + } +} + +void MARYOLED::_putp( int colour ) { + /*int cnv = 0; + + cnv = (colour >> 8) & 0xf800; + cnv |= (colour >> 5) & 0x07e0; + cnv |= (colour >> 3) & 0x001f; + + data( cnv >> 8); + data( cnv ); + */ + unsigned long data1, data2; + data1 = ((colour >> 8) & 0xff) | 0x100; + data2 = (colour & 0x0ff) | 0x100; + data(data1); + data(data2); + } +int MARYOLED::_putc(int value) { + int x = _column * 8; // FIXME: Char sizes + int y = _row * 8; + bitblit(x + 1, y + 1, 8, 8, (char*)&(FONT8x8[value - 0x1F][0])); + + _column++; + + if (_column >= MARYOLED_COLS) { + _row++; + _column = 0; + } + + if (_row >= MARYOLED_ROWS) { + _row = 0; + } + + return value; +} + +void MARYOLED::cls( void ) { + fill( 0, 0, MARYOLED_WIDTH , MARYOLED_HEIGHT, _background ); + _row = 0; + _column = 0; +} + + +void MARYOLED::window(int x, int y, int width, int height) { + // digitalWrite( OLED_CS, LOW ); + _window(x, y, width, height); + //digitalWrite( OLED_CS, HIGH ); +} + +void MARYOLED::putp(int colour) { + //digitalWrite( OLED_CS, LOW ); + _putp(colour); + //digitalWrite( OLED_CS, HIGH ); +} + + +void MARYOLED::pixel(int x, int y, int colour) { + //digitalWrite( OLED_CS, LOW ); + _window(x, y, 1, 1); + _putp(colour); + //digitalWrite( OLED_CS, HIGH ); +} + +void MARYOLED::fill( int x, int y, int width, int height, int colour ) +{ + digitalWrite( OLED_CS, LOW ); + _window( x, y, width, height ); + + for (int i = 0; i < width * height; i++ ) { + _putp( colour ); + } + + _window( 0, 0, MARYOLED_WIDTH, MARYOLED_HEIGHT ); + digitalWrite( OLED_CS, HIGH ); +} + + +void MARYOLED::blit( int x, int y, int width, int height, const int* colour ) { + digitalWrite( OLED_CS, LOW ); + _window( x, y, width, height ); + + for (int i = 0; i < width * height; i++ ) { + _putp( colour[i] ); + } + _window( 0, 0, MARYOLED_WIDTH, MARYOLED_HEIGHT ); + digitalWrite( OLED_CS, HIGH ); +} + + +void MARYOLED::bitblit( int x, int y, int width, int height, const char* bitstream ) { + digitalWrite( OLED_CS, LOW ); + _window( x, y, width, height ); + + for (int i = 0; i < height * width; i++ ) { + int byte = i / 8; + int bit = i % 8; + int colour = ((bitstream[ byte ] << bit) & 0x80) ? _foreground : _background; + _putp( colour ); + } + _window( 0, 0, _width, _height ); + digitalWrite( OLED_CS, HIGH ); +} + +void MARYOLED::foreground(int c) { + _foreground = c; + return; +} + +void MARYOLED::background(int c) { + _background = c; + return; +} + +int MARYOLED::width() { + return MARYOLED_WIDTH; +} + +int MARYOLED::height() { + return MARYOLED_HEIGHT; +} + +int MARYOLED::columns() { + return MARYOLED_COLS; +} + +int MARYOLED::rows() { + return MARYOLED_ROWS; +} + + diff --git a/src/core/maryoled.h b/src/core/maryoled.h new file mode 100755 index 0000000..3998f8d --- /dev/null +++ b/src/core/maryoled.h @@ -0,0 +1,127 @@ +/* + * MARYOLED.h + * + * Created on: 2011/08/01 + * Author: lynxeyed + */ + +#ifndef MARYOLED_H_ +#define MARYOLED_H_ + +/**************************************************************************//** + * @file maryoled.h + * @brief Arduino-like library for MARY(LPC1114) + * @version v.0.50 + * @date 1. August 2011. + * @author this library's assembled by @@dw256 and @@tedd_okano rebuild by @@lynxeyed_atsu + * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR> + * 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: <BR> + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.<BR> + * 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 "SPI.h" +#include "gpio.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef enum {OLED,Nokia6610,Nokia6100,PCF8833} LCD_DEVICES; // Defaults:OLED + +class MARYOLED { +private: + SSP_PORT port; + LCD_DEVICES device; + int OLED_VCC_ON; + int OLED_CS; + int OLED_RES; + int _row; + int _column; + int _foreground; + int _background; + int _width; + int _height; + + /** Command list for the OLED controller */ + enum { + SET_DISPLAY_MODE_ALL_OFF = 0xA4, + SET_COMMAND_LOCK = 0xFD, + SET_SLEEP_MODE_ON = 0xAE, + FRONT_CLOCK_DRIVER_OSC_FREQ = 0xB3, + SET_MUX_RATIO = 0xCA, + SET_DISPAY_OFFSET = 0xA2, + SET_DISPAY_START_LINE = 0xA1, + SET_REMAP_COLOR_DEPTH = 0xA0, + SET_GPIO = 0xB5, + FUNCTION_SELECTION = 0xAB, + SET_SEGMENT_LOW_VOLTAGE = 0xB4, + SET_CONTRAST_CURRENT_FOR_COLOR_ABC = 0xC1, + MASTER_CONTRAST_CURRENT_CONTROL = 0xC7, + LOOKUP_TABLE_FOR_GRAYSCALE_PULSE_WIDTH = 0xB8, + USE_BUILT_IN_LINEAR_LUT = 0xB9, + SET_RESET_PRECHARGE_PERIOD = 0xB1, + ENHANCE_DRIVING_SCHEME_CAPABILITY = 0xB2, + SET_PRECHARGE_VOLTAGE = 0xBB, + SET_SECOND_PRECHARGE_VOLTAGE = 0xB6, + SET_VCOMH_VOLTAGE = 0xBE, + SET_DISPLAY_MODE_RESET = 0xA6, + SET_COLUMN_ADDRESS = 0x15, + SET_ROW_ADDRESS = 0x75, + WRITE_RAM_COMMAND = 0x5C, + SET_SLEEP_MODE_OFF = 0xAF + }; + /** Constants for power() function */ + enum { + OFF = 0, /**< : to turning-OFF */ + ON /**< : to turning-ON */ + }; + + +public: + MARYOLED(); // announce the constructor to initialize + ~MARYOLED(); + + void reset(); + void reset(SSP_PORT port); + void command( int value ); + void data( int value ); + void _window( int x, int y, int width, int height ); + void locate(int column, int row); + void newline(); + void _putp( int colour ); + int _putc( int value ); + void cls( void ); + void window( int x, int y, int width, int height ); + void WindowReset(void); + void putp( int colour ); + void pixel( int x, int y, int colour ); + void fill( int x, int y, int width, int height, int colour ); + void blit( int x, int y, int width, int height, const int* colour ); + void bitblit( int x, int y, int width, int height, const char* bitstream ); + void foreground(int c); + void background(int c); + int width(); + int height(); + int columns(); + int rows(); +}; + +extern MARYOLED oled; + +#ifdef __cplusplus + } +#endif +#endif /* MARYOLED_H_ */ diff --git a/src/core/startup_mary.cpp b/src/core/startup_mary.cpp new file mode 100755 index 0000000..8ce5c39 --- /dev/null +++ b/src/core/startup_mary.cpp @@ -0,0 +1,26 @@ +/* + * startup_mary.cpp + * + * Created on: 2011/08/04 + * Author: lynxeyed + */ + +#include "libmary.h" + +void setup(void); +void loop(void); + +int main(void) +{ + + setup_systick(); + setup_TIMER32_1(); + + setup(); + + while(1) + { + loop(); + } + +} diff --git a/src/core/system_LPC11xx.cpp b/src/core/system_LPC11xx.cpp new file mode 100755 index 0000000..4d8d275 --- /dev/null +++ b/src/core/system_LPC11xx.cpp @@ -0,0 +1,452 @@ +/**************************************************************************//**
+ * @file system_LPC11xx.c
+ * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Source File
+ * for the NXP LPC11xx Device Series
+ * @version V1.00
+ * @date 17. November 2009
+ *
+ * @note
+ * Copyright (C) 2009 ARM Limited. All rights reserved.
+ *
+ * @par
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M
+ * processor based microcontrollers. This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * @par
+ * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+
+#include <stdint.h>
+#include "LPC11xx.h"
+
+/*
+//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
+*/
+
+/*--------------------- Clock Configuration ----------------------------------
+//
+// <e> Clock Configuration
+// <e1> System Clock Setup
+// <e2> System Oscillator Enable
+// <o3.1> Select System Oscillator Frequency Range
+// <0=> 1 - 20 MHz
+// <1=> 15 - 25 MHz
+// </e2>
+// <e4> Watchdog Oscillator Enable
+// <o5.0..4> Select Divider for Fclkana
+// <0=> 2 <1=> 4 <2=> 6 <3=> 8
+// <4=> 10 <5=> 12 <6=> 14 <7=> 16
+// <8=> 18 <9=> 20 <10=> 22 <11=> 24
+// <12=> 26 <13=> 28 <14=> 30 <15=> 32
+// <16=> 34 <17=> 36 <18=> 38 <19=> 40
+// <20=> 42 <21=> 44 <22=> 46 <23=> 48
+// <24=> 50 <25=> 52 <26=> 54 <27=> 56
+// <28=> 58 <29=> 60 <30=> 62 <31=> 64
+// <o5.5..8> Select Watchdog Oscillator Analog Frequency (Fclkana)
+// <0=> Disabled
+// <1=> 0.5 MHz
+// <2=> 0.8 MHz
+// <3=> 1.1 MHz
+// <4=> 1.4 MHz
+// <5=> 1.6 MHz
+// <6=> 1.8 MHz
+// <7=> 2.0 MHz
+// <8=> 2.2 MHz
+// <9=> 2.4 MHz
+// <10=> 2.6 MHz
+// <11=> 2.7 MHz
+// <12=> 2.9 MHz
+// <13=> 3.1 MHz
+// <14=> 3.2 MHz
+// <15=> 3.4 MHz
+// </e4>
+// <o6> Select Input Clock for sys_pllclkin (Register: SYSPLLCLKSEL)
+// <0=> IRC Oscillator
+// <1=> System Oscillator
+// <2=> WDT Oscillator
+// <3=> Invalid
+// <e7> Use System PLL
+// <i> F_pll = M * F_in
+// <i> F_in must be in the range of 10 MHz to 25 MHz
+// <o8.0..4> M: PLL Multiplier Selection
+// <1-32><#-1>
+// <o8.5..6> P: PLL Divider Selection
+// <0=> 2
+// <1=> 4
+// <2=> 8
+// <3=> 16
+// <o8.7> DIRECT: Direct CCO Clock Output Enable
+// <o8.8> BYPASS: PLL Bypass Enable
+// </e7>
+// <o9> Select Input Clock for Main clock (Register: MAINCLKSEL)
+// <0=> IRC Oscillator
+// <1=> Input Clock to System PLL
+// <2=> WDT Oscillator
+// <3=> System PLL Clock Out
+// </e1>
+// <o10.0..7> System AHB Divider <0-255>
+// <i> 0 = is disabled
+// <o11.0> SYS Clock Enable
+// <o11.1> ROM Clock Enable
+// <o11.2> RAM Clock Enable
+// <o11.3> FLASHREG Flash Register Interface Clock Enable
+// <o11.4> FLASHARRAY Flash Array Access Clock Enable
+// <o11.5> I2C Clock Enable
+// <o11.6> GPIO Clock Enable
+// <o11.7> CT16B0 Clock Enable
+// <o11.8> CT16B1 Clock Enable
+// <o11.9> CT32B0 Clock Enable
+// <o11.10> CT32B1 Clock Enable
+// <o11.11> SSP0 Clock Enable
+// <o11.12> UART Clock Enable
+// <o11.13> ADC Clock Enable
+// <o11.15> WDT Clock Enable
+// <o11.16> IOCON Clock Enable
+// <o11.18> SSP1 Clock Enable
+//
+// <o12.0..7> SSP0 Clock Divider <0-255>
+// <i> 0 = is disabled
+// <o13.0..7> UART Clock Divider <0-255>
+// <i> 0 = is disabled
+// <o14.0..7> SSP1 Clock Divider <0-255>
+// <i> 0 = is disabled
+// </e>
+*/
+#define CLOCK_SETUP 1
+#define SYSCLK_SETUP 1
+#define SYSOSC_SETUP 1
+#define SYSOSCCTRL_Val 0x00000000
+#define WDTOSC_SETUP 0
+#define WDTOSCCTRL_Val 0x000000A0
+//#define SYSPLLCLKSEL_Val 0x00000001
+#define SYSPLLCLKSEL_Val 0x00000000 // for Mary-MB
+#define SYSPLL_SETUP 1
+#define SYSPLLCTRL_Val 0x00000023
+#define MAINCLKSEL_Val 0x00000003
+#define SYSAHBCLKDIV_Val 0x00000001
+//#define AHBCLKCTRL_Val 0x0001005F
+#define AHBCLKCTRL_Val 0x0001FFFF // for Mary-MB
+#define SSP0CLKDIV_Val 0x00000001
+#define UARTCLKDIV_Val 0x00000001
+#define SSP1CLKDIV_Val 0x00000001
+
+/*--------------------- Memory Mapping Configuration -------------------------
+//
+// <e> Memory Mapping
+// <o1.0..1> System Memory Remap (Register: SYSMEMREMAP)
+// <0=> Bootloader mapped to address 0
+// <1=> RAM mapped to address 0
+// <2=> Flash mapped to address 0
+// <3=> Flash mapped to address 0
+// </e>
+*/
+#define MEMMAP_SETUP 0
+#define SYSMEMREMAP_Val 0x00000001
+
+/*
+//-------- <<< end of configuration section >>> ------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+ Check the register settings
+ *----------------------------------------------------------------------------*/
+#define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
+#define CHECK_RSVD(val, mask) (val & mask)
+
+/* Clock Configuration -------------------------------------------------------*/
+#if (CHECK_RSVD((SYSOSCCTRL_Val), ~0x00000003))
+ #error "SYSOSCCTRL: Invalid values of reserved bits!"
+#endif
+
+#if (CHECK_RSVD((WDTOSCCTRL_Val), ~0x000001FF))
+ #error "WDTOSCCTRL: Invalid values of reserved bits!"
+#endif
+
+#if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
+ #error "SYSPLLCLKSEL: Value out of range!"
+#endif
+
+#if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000001FF))
+ #error "SYSPLLCTRL: Invalid values of reserved bits!"
+#endif
+
+#if (CHECK_RSVD((MAINCLKSEL_Val), ~0x00000003))
+ #error "MAINCLKSEL: Invalid values of reserved bits!"
+#endif
+
+#if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
+ #error "SYSAHBCLKDIV: Value out of range!"
+#endif
+
+#if (CHECK_RSVD((AHBCLKCTRL_Val), ~0x0001FFFF))
+ #error "AHBCLKCTRL: Invalid values of reserved bits!"
+#endif
+
+#if (CHECK_RANGE((SSP0CLKDIV_Val), 0, 255))
+ #error "SSP0CLKDIV: Value out of range!"
+#endif
+
+#if (CHECK_RANGE((UARTCLKDIV_Val), 0, 255))
+ #error "UARTCLKDIV: Value out of range!"
+#endif
+
+#if (CHECK_RANGE((SSP1CLKDIV_Val), 0, 255))
+ #error "SSP1CLKDIV: Value out of range!"
+#endif
+
+#if (CHECK_RSVD((SYSMEMREMAP_Val), ~0x00000003))
+ #error "SYSMEMREMAP: Invalid values of reserved bits!"
+#endif
+
+
+/*----------------------------------------------------------------------------
+ DEFINES
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ Define clocks
+ *----------------------------------------------------------------------------*/
+#define __XTAL (12000000UL) /* Oscillator frequency */
+#define __SYS_OSC_CLK ( __XTAL) /* Main oscillator frequency */
+#define __IRC_OSC_CLK (12000000UL) /* Internal RC oscillator frequency */
+
+
+#define __FREQSEL ((WDTOSCCTRL_Val >> 5) & 0x0F)
+#define __DIVSEL (((WDTOSCCTRL_Val & 0x1F) << 1) + 2)
+
+#if (CLOCK_SETUP) /* Clock Setup */
+ #if (SYSCLK_SETUP) /* System Clock Setup */
+ #if (WDTOSC_SETUP) /* Watchdog Oscillator Setup*/
+ #if (__FREQSEL == 0)
+ #define __WDT_OSC_CLK ( 400000 / __DIVSEL)
+ #elif (__FREQSEL == 1)
+ #define __WDT_OSC_CLK ( 500000 / __DIVSEL)
+ #elif (__FREQSEL == 2)
+ #define __WDT_OSC_CLK ( 800000 / __DIVSEL)
+ #elif (__FREQSEL == 3)
+ #define __WDT_OSC_CLK (1100000 / __DIVSEL)
+ #elif (__FREQSEL == 4)
+ #define __WDT_OSC_CLK (1400000 / __DIVSEL)
+ #elif (__FREQSEL == 5)
+ #define __WDT_OSC_CLK (1600000 / __DIVSEL)
+ #elif (__FREQSEL == 6)
+ #define __WDT_OSC_CLK (1800000 / __DIVSEL)
+ #elif (__FREQSEL == 7)
+ #define __WDT_OSC_CLK (2000000 / __DIVSEL)
+ #elif (__FREQSEL == 8)
+ #define __WDT_OSC_CLK (2200000 / __DIVSEL)
+ #elif (__FREQSEL == 9)
+ #define __WDT_OSC_CLK (2400000 / __DIVSEL)
+ #elif (__FREQSEL == 10)
+ #define __WDT_OSC_CLK (2600000 / __DIVSEL)
+ #elif (__FREQSEL == 11)
+ #define __WDT_OSC_CLK (2700000 / __DIVSEL)
+ #elif (__FREQSEL == 12)
+ #define __WDT_OSC_CLK (2900000 / __DIVSEL)
+ #elif (__FREQSEL == 13)
+ #define __WDT_OSC_CLK (3100000 / __DIVSEL)
+ #elif (__FREQSEL == 14)
+ #define __WDT_OSC_CLK (3200000 / __DIVSEL)
+ #else
+ #define __WDT_OSC_CLK (3400000 / __DIVSEL)
+ #endif
+ #else
+ #define __WDT_OSC_CLK (1600000 / 2)
+ #endif // WDTOSC_SETUP
+
+ /* sys_pllclkin calculation */
+ #if ((SYSPLLCLKSEL_Val & 0x03) == 0)
+ #define __SYS_PLLCLKIN (__IRC_OSC_CLK)
+ #elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
+ #define __SYS_PLLCLKIN (__SYS_OSC_CLK)
+ #elif ((SYSPLLCLKSEL_Val & 0x03) == 2)
+ #define __SYS_PLLCLKIN (__WDT_OSC_CLK)
+ #else
+ #define __SYS_PLLCLKIN (0)
+ #endif
+
+ #if (SYSPLL_SETUP) /* System PLL Setup */
+ #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
+ #else
+ #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * (1))
+ #endif // SYSPLL_SETUP
+
+ /* main clock calculation */
+ #if ((MAINCLKSEL_Val & 0x03) == 0)
+ #define __MAIN_CLOCK (__IRC_OSC_CLK)
+ #elif ((MAINCLKSEL_Val & 0x03) == 1)
+ #define __MAIN_CLOCK (__SYS_PLLCLKIN)
+ #elif ((MAINCLKSEL_Val & 0x03) == 2)
+ #define __MAIN_CLOCK (__WDT_OSC_CLK)
+ #elif ((MAINCLKSEL_Val & 0x03) == 3)
+ #define __MAIN_CLOCK (__SYS_PLLCLKOUT)
+ #else
+ #define __MAIN_CLOCK (0)
+ #endif
+
+ #define __SYSTEM_CLOCK (__MAIN_CLOCK / SYSAHBCLKDIV_Val)
+
+ #else // SYSCLK_SETUP
+ #if (SYSAHBCLKDIV_Val == 0)
+ #define __SYSTEM_CLOCK (0)
+ #else
+ #define __SYSTEM_CLOCK (__XTAL / SYSAHBCLKDIV_Val)
+ #endif
+ #endif // SYSCLK_SETUP
+
+#else
+ #define __SYSTEM_CLOCK (__XTAL)
+#endif // CLOCK_SETUP
+
+
+/*----------------------------------------------------------------------------
+ Clock Variable definitions
+ *----------------------------------------------------------------------------*/
+uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
+
+
+/*----------------------------------------------------------------------------
+ Clock functions
+ *----------------------------------------------------------------------------*/
+void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
+{
+ uint32_t wdt_osc = 0;
+
+ /* Determine clock frequency according to clock register values */
+ switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
+ case 0: wdt_osc = 400000; break;
+ case 1: wdt_osc = 500000; break;
+ case 2: wdt_osc = 800000; break;
+ case 3: wdt_osc = 1100000; break;
+ case 4: wdt_osc = 1400000; break;
+ case 5: wdt_osc = 1600000; break;
+ case 6: wdt_osc = 1800000; break;
+ case 7: wdt_osc = 2000000; break;
+ case 8: wdt_osc = 2200000; break;
+ case 9: wdt_osc = 2400000; break;
+ case 10: wdt_osc = 2600000; break;
+ case 11: wdt_osc = 2700000; break;
+ case 12: wdt_osc = 2900000; break;
+ case 13: wdt_osc = 3100000; break;
+ case 14: wdt_osc = 3200000; break;
+ case 15: wdt_osc = 3400000; break;
+ }
+ wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
+
+ switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
+ case 0: /* Internal RC oscillator */
+ SystemCoreClock = __IRC_OSC_CLK;
+ break;
+ case 1: /* Input Clock to System PLL */
+ switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
+ case 0: /* Internal RC oscillator */
+ SystemCoreClock = __IRC_OSC_CLK;
+ break;
+ case 1: /* System oscillator */
+ SystemCoreClock = __SYS_OSC_CLK;
+ break;
+ case 2: /* WDT Oscillator */
+ SystemCoreClock = wdt_osc;
+ break;
+ case 3: /* Reserved */
+ SystemCoreClock = 0;
+ break;
+ }
+ break;
+ case 2: /* WDT Oscillator */
+ SystemCoreClock = wdt_osc;
+ break;
+ case 3: /* System PLL Clock Out */
+ switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
+ case 0: /* Internal RC oscillator */
+ if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
+ SystemCoreClock = __IRC_OSC_CLK;
+ } else {
+ SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+ }
+ break;
+ case 1: /* System oscillator */
+ if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
+ SystemCoreClock = __SYS_OSC_CLK;
+ } else {
+ SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+ }
+ break;
+ case 2: /* WDT Oscillator */
+ if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
+ SystemCoreClock = wdt_osc;
+ } else {
+ SystemCoreClock = wdt_osc * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
+ }
+ break;
+ case 3: /* Reserved */
+ SystemCoreClock = 0;
+ break;
+ }
+ break;
+ }
+
+ SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;
+
+}
+
+/**
+ * Initialize the system
+ *
+ * @param none
+ * @return none
+ *
+ * @brief Setup the microcontroller system.
+ * Initialize the System.
+ */
+void SystemInit (void)
+{
+#if (CLOCK_SETUP) /* Clock Setup */
+#if (SYSCLK_SETUP) /* System Clock Setup */
+#if (SYSOSC_SETUP) /* System Oscillator Setup */
+ uint32_t i;
+
+ LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */
+ LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val;
+ for (i = 0; i < 200; i++) __NOP();
+ LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */
+ LPC_SYSCON->SYSPLLCLKUEN = 0x01; /* Update Clock Source */
+ LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */
+ LPC_SYSCON->SYSPLLCLKUEN = 0x01;
+ while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */
+#if (SYSPLL_SETUP) /* System PLL Setup */
+ LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val;
+ LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */
+ while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */
+#endif
+#endif
+#if (WDTOSC_SETUP) /* Watchdog Oscillator Setup*/
+ LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val;
+ LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */
+#endif
+ LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */
+ LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */
+ LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
+ LPC_SYSCON->MAINCLKUEN = 0x01;
+ while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */
+#endif
+
+ LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val;
+ LPC_SYSCON->SYSAHBCLKCTRL = AHBCLKCTRL_Val;
+ LPC_SYSCON->SSP0CLKDIV = SSP0CLKDIV_Val;
+ LPC_SYSCON->UARTCLKDIV = UARTCLKDIV_Val;
+ LPC_SYSCON->SSP1CLKDIV = SSP1CLKDIV_Val;
+#endif
+
+
+#if (MEMMAP_SETUP || MEMMAP_INIT) /* Memory Mapping Setup */
+ LPC_SYSCON->SYSMEMREMAP = SYSMEMREMAP_Val;
+#endif
+}
diff --git a/src/core/system_LPC11xx.h b/src/core/system_LPC11xx.h new file mode 100755 index 0000000..385fe38 --- /dev/null +++ b/src/core/system_LPC11xx.h @@ -0,0 +1,64 @@ +/**************************************************************************//**
+ * @file system_LPC11xx.h
+ * @brief CMSIS Cortex-M0 Device Peripheral Access Layer Header File
+ * for the NXP LPC11xx Device Series
+ * @version V1.00
+ * @date 17. November 2009
+ *
+ * @note
+ * Copyright (C) 2009 ARM Limited. All rights reserved.
+ *
+ * @par
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M
+ * processor based microcontrollers. This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * @par
+ * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+
+#ifndef __SYSTEM_LPC11xx_H
+#define __SYSTEM_LPC11xx_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
+
+
+/**
+ * Initialize the system
+ *
+ * @param none
+ * @return none
+ *
+ * @brief Setup the microcontroller system.
+ * Initialize the System and update the SystemCoreClock variable.
+ */
+extern void SystemInit (void);
+
+/**
+ * Update SystemCoreClock variable
+ *
+ * @param none
+ * @return none
+ *
+ * @brief Updates the SystemCoreClock with current core Clock
+ * retrieved from cpu registers.
+ */
+extern void SystemCoreClockUpdate (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYSTEM_LPC11x_H */
diff --git a/src/core/uart.cpp b/src/core/uart.cpp new file mode 100755 index 0000000..ea61c3c --- /dev/null +++ b/src/core/uart.cpp @@ -0,0 +1,206 @@ +/* + * uart.cpp + * + * Created on: 2011/07/30 + * Author: lynxeyed + */ + +#include <string.h> +#include "LPC11xx.h" +#include "uart.h" + +#ifdef __cplusplus + extern "C" { +#endif + + // Flag mask for UART_LSR register. +const unsigned long LSR_TEMT = 0x40; +const unsigned long LSR_THRE = 0x20; +const unsigned long LSR_RDR = 0x01; +const unsigned long ACR_START = 0x01; +const unsigned long IER_RLS = 0x04; +const unsigned long IER_RBR = 0x01; + +USerial Serial; + +USerial::USerial()//USerial(SERIAL_PORT port) //define constructor +{ + this->port = marySerial1; //default = marySerial1 + format = OCT; + speed = 9600; //baudrate + //begin(speed); +} + +USerial::~USerial() +{ + +} + +void USerial::begin(int speed) +{ + this->speed = speed; + // Divisor ratio + unsigned long Fdiv; + + // Configure P1[7] as TXD output. + LPC_IOCON->PIO1_7 &= ~0x07; // FUNC=000 (GPIO) + LPC_IOCON->PIO1_7 |= 0x01; // FUNC=001 (TXD) + + // Configure P1[6] as RXD input. + LPC_IOCON->PIO1_6 &= ~0x07; // FUNC=000 (GPIO) + LPC_IOCON->PIO1_6 |= 0x01; // FUNC=001 (RXD) + + // Enable UART clock + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); // UART=1 + + // Enable UART peripheral clock + LPC_SYSCON->UARTCLKDIV = 0x01; // DIV=1 + + // fix baud-rate + Fdiv = (SystemCoreClock * LPC_SYSCON->SYSAHBCLKDIV) / (LPC_SYSCON->UARTCLKDIV * 16 * speed); + + // Set the baud rate divisor value + LPC_UART->LCR |= 0x80; + LPC_UART->DLM = Fdiv / 256; + LPC_UART->DLL = Fdiv % 256; + LPC_UART->LCR &= ~0x80; + + // Configure UART module as + // 8 bit, 1 stop bit, no parity + // Enable and reset TX and RX FIFO. + LPC_UART->LCR = 0x03; + LPC_UART->FCR = 0x07; + +} + +void USerial::end() +{ + return; +} + +void USerial::write(const char c) //uart_putc +{ + // Wait for TX buffer empty + while (!(LPC_UART->LSR & LSR_THRE)); + // Put a character + LPC_UART->THR = c; + return; +} + +void USerial::print(const char *s) //uart_puts +{ + int n; + for (n = 0; *s; s++, n++) { + write(*s); + } + //return n; + return; +} + +void USerial::print(int val, RADIX_FORMAT format) +{ + if(format == BYTE) + { + write((char)(val & 0xff)); + return; + } + char s[32]; + int i,j; + i=j=0; // header of strings + if (val<0) + { //minus value + s[i]='-'; + val=~val+1; + i++; + j++; + } + switch(format) + { + case BIN: + while (val>0) + { // do until zero + s[i++]=radix_bin[val%format]; + val/=format; + } + break; + + case OCT: + while (val>0) + { // do until zero + s[i++]=radix_oct[val%format]; + val/=format; + } + break; + + case DEC: //RADIX = Decimal + while (val>0) + { // do until zero + s[i++]=radix_dec[val%format]; + val/=format; + } + break; + + case HEX: //RADIX = Hexadecimal + while (val>0) + { // do until zero + s[i++]=radix_hex[val%format]; + val/=format; + } + break; + default: + break; + } + s[i--]='\0'; // EOF + while (j<i) + { // reverse strings array + char t; + t=s[j]; s[j]=s[i]; s[i]=t; + j++; i--; + } + print(s); + + return ; +} + +void USerial::write(const char *s, int length) +{ + int n; + for(n=0;n<length;s++,n++) + { + write(*s); + } + return; +} + +void USerial::println(const char *s) +{ + print(s); + write ('\r'); + write ('\n'); + return; +} + + +void USerial::println(int val, RADIX_FORMAT format) +{ + print(val,format); + write ('\r'); + write ('\n'); + return; +} + +int USerial::available(void) +{ + return (LPC_UART->LSR & LSR_RDR); +} + +int USerial::read(void) +{ + // Wait for RX buffer valid + //while (!(LPC_UART->LSR & LSR_RDR)); + return LPC_UART->RBR; +} + +#ifdef __cplusplus +} //extern "C" +#endif diff --git a/src/core/uart.h b/src/core/uart.h new file mode 100755 index 0000000..c7e5125 --- /dev/null +++ b/src/core/uart.h @@ -0,0 +1,90 @@ +#ifndef UART_H_ +#define UART_H_ + +/**************************************************************************//** + * @file uart.h + * @brief Arduino-like library for MARY(LPC1114) + * @version v.0.50 + * @date 1. August 2011. + * @author @@lynxeyed_atsu + * @note Copyright (c) 2011 Lynx-EyED's Klavier and Craft-works. <BR> + * 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: <BR> + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software.<BR> + * 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 "LPC11xx.h" +#ifdef __cplusplus + extern "C" { +#endif +const char radix_bin[]="01"; +const char radix_oct[]="01234567"; +const char radix_dec[]="0123456789"; +const char radix_hex[]="0123456789ABCDEF"; + +/*! @enum SERIAL_PORT + @brief COMポート(UART)のチャンネル選択。 + @note UARTが1ポートしかないMARYでは使用していないので特に影響はないが、2ポート以上UARTが存在するLPCXpressoシリーズや + mbedシリーズとの後方互換性を考慮し用意している +*/ +typedef enum { + marySerial1, /*!< MARYのUARTポート(デフォルト) */ + mbedSerial1, /*!< mbed(LPC1768/9)のUART1ポート(将来的に対応予定) */ + mbedSerial2 /*!< mbed(LPC1768/9)のUART2ポート(将来的に対応予定) */ +} SERIAL_PORT; // Defaults:marySerial1 + +/*! @enum SERIAL_FORMAT + @brief Arduinoのprint(data, format)の第二パラメータ(format)の基数。 +*/ +typedef enum { + BYTE = 0x01, /*!< 1バイトのアスキーコードが表示される */ + BIN = 0x02, /*!< dataで与えられた数値を2進数で表示する */ + OCT = 0x08, /*!< dataで与えられた数値を8進数で表示する */ + DEC = 0x0A, /*!< dataで与えられた数値を10進数で表示する */ + HEX = 0x10 /*!< dataで与えられた数値を16進数で表示する */ +} RADIX_FORMAT; + + +class USerial { +private: + SERIAL_PORT port; + RADIX_FORMAT format; + int speed; + +public: + USerial();//USerial(SERIAL_PORT port); // announce the constructor to initialize + ~USerial(); + + void begin(int speed); + void end() ; + void print(const char *s); + void print(int val, RADIX_FORMAT format); + void println(const char *s); + void println(int val, RADIX_FORMAT format) ; + int read(void); + int available(void); + void write(const char c); + void write(const char *s,int length); +}; + + +extern USerial Serial; + +#ifdef __cplusplus + } +#endif + + +#endif /* UART_H_ */ diff --git a/src/user_application.cpp b/src/user_application.cpp new file mode 100755 index 0000000..c8656fd --- /dev/null +++ b/src/user_application.cpp @@ -0,0 +1,52 @@ +#include <libmary.h>
+#include <stdlib.h>
+#include <SPI1.h>
+
+#define S9706_GATE 6 //Low->High:光量の積算。S9706の6番->(D6に接続)
+#define S9706_RANGE P0_1 //受光感度調整。S9706の4番->(P0_1)に接続。
+
+// PIO2_1 : SCLK -> S9706の5番(CK)
+// PIO2_2 : MISO -> S9706の1番(Dout)
+
+void setup()
+{
+ pinMode(S9706_GATE,OUTPUT);
+ pinMode(S9706_RANGE,OUTPUT);
+ Serial.begin(9600);
+ SPI1.setBitLength(12); //12bit ADC
+ SPI1.setDataMode(SPI_MODE2);
+ SPI1.begin();
+ Serial.println("Start");
+}
+
+int r,g,b;
+
+void loop()
+{
+ digitalWrite(S9706_GATE,LOW);
+ digitalWrite(S9706_RANGE,HIGH);
+
+ Serial.println("積算を開始");
+ digitalWrite(S9706_GATE,HIGH);
+ delay(4);
+
+
+ Serial.println("積算を終了");
+ Serial.println("データリード開始");
+
+ digitalWrite(S9706_GATE,LOW);
+
+ r = SPI1.transfer(0xfff);
+ g = SPI1.transfer(0xfff);
+ b = SPI1.transfer(0xfff);
+
+ Serial.print("r = ");
+ Serial.println(r,DEC);
+ Serial.print("g = ");
+ Serial.println(g,DEC);
+ Serial.print("b = ");
+ Serial.println(b,DEC);
+
+ delay(1000);
+
+}
|
