Initial checkin of spinix (original version 1.33)

This commit is contained in:
Jörg Deckert 2014-03-25 10:40:35 +01:00
commit 99bd77d966
250 changed files with 43169 additions and 0 deletions

5
build_bin Normal file
View File

@ -0,0 +1,5 @@
cd src
bstc -b -O cgru $1.spin
cp $1.binary ../root/bin/$1
rm $1.binary
cd ..

6
build_boot Normal file
View File

@ -0,0 +1,6 @@
# Build the the boot program
cd src
bstc -b -O cgru boot.spin
cp boot.binary ..
rm boot.binary
cd ..

37
build_c Normal file
View File

@ -0,0 +1,37 @@
# Build filetest
cd filetest
cp ../src/spinix.* .
make clean
make
make binary
cd ..
# Build fibo
cd cdemos
cd fibo
cp ../../src/spinix.* .
make clean
./buildit
cd ../..
# Build the dhrystone benchmark
cd cdemos
cd dry
cp ../../src/spinix.* .
make clean
./buildit
cd ../..
# Build a simple hello world program
cd cdemos
cd hello
cp ../../src/spinix.* .
make clean
./buildit
cd ../..
# Build the chess program
cd chess
./buildit
cd ..

81
build_spinix Normal file
View File

@ -0,0 +1,81 @@
# Clean directories and remake them
rm -rf root
mkdir root
mkdir root/bin
mkdir root/tmp
mkdir root/manpages
mkdir root/devel
mkdir root/demos
mkdir root/forth
mkdir root/scripts
# Build the boot program
./build_boot
# Copy license and startup script to root
cp license.txt root
cp src/_shellrc root/bin
# Generate _sysparm and copy to root
cd src
date +%s >_sysparm
echo -6 3 0 >>_sysparm
echo 0 0 0 >>_sysparm
echo "GPWD /" >>_sysparm
echo "LSCRIPT_FILE /bin/_shellrc" >>_sysparm
echo "P# 0" >>_sysparm
cd ..
cp src/_sysparm root
# Build the bin apps
./build_src
# Copy the devel files
cp devel/* root/devel
# Copy the man pages
cp manpages/* root/manpages
# Build lerner
cd lerner
cp ../src/sysdefs.spin .
cp ../src/exit.spin .
bstc -b -O cgru lerner.spin
cp lerner.binary ../root/demos/lerner
rm *.binary
cd ..
# Build vga512
cd vga512
cp ../src/sysdefs.spin .
cp ../src/exit.spin .
bstc -b VGA_512x384_Bitmap_Demo.spin
cp VGA_512x384_Bitmap_Demo.binary ../root/demos/vga512
rm *.binary
cd ..
# Move vgatdemo from bin to demos
mv root/bin/vgatdemo root/demos
# Copy the C demos
cp cdemos/dry/dry.binary root/demos/dry
cp cdemos/fibo/fibo.binary root/demos/fibo
cp cdemos/hello/hello.binary root/demos/hello
# Copy C filetest program
cp filetest/filetest.binary root/demos/filetest
# Copy C chess program
cp chess/chess.binary root/demos/chess
# Build pfth and copy the Forth files
cd pfth
bstc -b ospfth.spin
cp ospfth.binary ../root/bin/pfth
cp *.fth ../root/forth
cp *.txt ../root/forth
mv ../root/forth/_startup.fth ../root
cd ..
# Copy the script files
cp scripts/* root/scripts

61
build_src Normal file
View File

@ -0,0 +1,61 @@
# Build the bin apps
./build_bin alias
./build_bin cat
./build_bin chmod
./build_bin config
./build_bin cp
./build_bin date
./build_bin declare
./build_bin diag
./build_bin diff
./build_bin dos2unix
./build_bin ed
./build_bin export
./build_bin ted
./build_bin grep
./build_bin halt
./build_bin head
./build_bin history
./build_bin let
./build_bin linefeed
./build_bin ls
./build_bin man
./build_bin mkdir
./build_bin more
./build_bin mv
./build_bin od
./build_bin printenv
./build_bin rb
./build_bin reboot
./build_bin rm
./build_bin sb
./build_bin set
./build_bin shell
./build_bin spasm
./build_bin spinit
./build_bin splink
./build_bin tail
./build_bin tar
./build_bin test
./build_bin touch
./build_bin unalias
./build_bin unix2dos
./build_bin unset
./build_bin vi
./build_bin vgatdemo
./build_bin wc
# Copy the shell scripts
cp src/spc root/bin
# Copy text files
cp src/*.txt root/bin
# Build files for spasm
cd src
grep PUB clibsd.spin >../root/devel/clibsd.spn
cp ../root/devel/clibsd.spn ../root/devel/clibsd.spa
bstc -b clibsd.spin
cp clibsd.binary ../root/devel/clibsd.bin
rm clibsd.binary
cd ..

128
cdemos/common/common.mk Normal file
View File

@ -0,0 +1,128 @@
# #########################################################
# This makefile fragment builds LMM/XMM/XMMC demo programs
#
# To use it, define:
# PROPLIB to be the path to this directory
# NAME to be the name of project
# - this is used to create the final program $(NAME).elf
# OBJS to be the object files needed for the project
# MODEL to lmm, xmm, or xmmc
# CFLAGS to be desired CFLAGS
#
# Then set up a default "all" target (normally this will be
# all: $(NAME).elf
# and finally
# include $(PROPLIB)/demo.mk
#
# Copyright (c) 2011 Parallax Inc.
# All rights MIT licensed
# #########################################################
# where we installed the propeller binaries and libraries
PREFIX = /opt/parallax
ifndef MODEL
MODEL=lmm
endif
ifndef BOARD
BOARD=$(PROPELLER_LOAD_BOARD)
endif
ifneq ($(BOARD),)
BOARDFLAG=-b$(BOARD)
endif
ifneq ($(CHIP),)
CHIPFLAG = -m$(CHIP)
endif
CFLAGS_NO_MODEL := $(CFLAGS) $(CHIPFLAG)
CFLAGS += -m$(MODEL) $(CHIPFLAG)
CXXFLAGS += $(CFLAGS)
LDFLAGS += $(CFLAGS) -fno-exceptions -fno-rtti
ifneq ($(LDSCRIPT),)
LDFLAGS += -T $(LDSCRIPT)
endif
# basic gnu tools
CC = propeller-elf-gcc
CXX = propeller-elf-g++
LD = propeller-elf-ld
AS = propeller-elf-as
AR = propeller-elf-ar
OBJCOPY = propeller-elf-objcopy
LOADER = propeller-load
LOADER2 = p2load
# BSTC program
BSTC=bstc
SPINDIR=.
ifneq ($(NAME),)
$(NAME).elf: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
endif
ifneq ($(LIBNAME),)
lib$(LIBNAME).a: $(OBJS)
$(AR) rs $@ $(OBJS)
endif
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
%.o: %.cpp
$(CC) $(CXXFLAGS) -o $@ -c $<
%.o: %.s
$(CC) -o $@ -c $<
#
# a .cog program is an object file that contains code intended to
# run in a COG separate from the main program; i.e., it's a COG
# driver that the linker will place in the .text section.
#
%.cog: %.c
$(CC) $(CFLAGS_NO_MODEL) -mcog -r -o $@ $<
$(OBJCOPY) --localize-text --rename-section .text=$@ $@
%.cog: %.cogc
$(CC) $(CFLAGS_NO_MODEL) -mcog -xc -r -o $@ $<
$(OBJCOPY) --localize-text --rename-section .text=$@ $@
#
# a .ecog program is an object file that contains code intended to
# run in a COG separate from the main program; i.e., it's a COG
# driver that the linker will place in the .drivers section which
# gets loaded to high EEPROM space above 0x8000.
#
%.ecog: %.c
$(CC) $(CFLAGS_NO_MODEL) -mcog -r -o $@ $<
$(OBJCOPY) --localize-text --rename-section .text=$@ $@
%.ecog: %.ecogc
$(CC) $(CFLAGS_NO_MODEL) -mcog -xc -r -o $@ $<
$(OBJCOPY) --localize-text --rename-section .text=$@ $@
%.binary: %.elf
$(LOADER) -s $<
%.dat: $(SPINDIR)/%.spin
$(BSTC) -Ox -c -o $(basename $@) $<
%_firmware.o: %.dat
$(OBJCOPY) -I binary -B propeller -O $(CC) $< $@
clean:
rm -f *.o *.elf *.a *.cog *.ecog *.binary
#
# how to run
run: $(NAME).elf
$(LOADER) $(BOARDFLAG) $(NAME).elf -r -t
run2: $(NAME).elf
$(LOADER2) $(NAME).elf -t
#

56
cdemos/dry/Makefile Normal file
View File

@ -0,0 +1,56 @@
# #########################################################
# This makefile builds the dhrystone program
#
# At the moment only the LMM model works.
#
# To build with LMM model, enter $ make clean; make
# To build with XMM model, enter $ make clean; make MODEL=xmm
# To build with XMMC model, enter $ make clean; make MODEL=xmmc
#
# Copyright (c) 2011 Parallax, Inc.
# All rights MIT licensed
# #########################################################
# Common make
COMMON = ../common
ifndef OPT
OPT=-O0
endif
ifndef PASSES
PASSES=3000
endif
#
# objects for this program
#
NAME = dry
OBJS = dry1.o dry2.o spinix.o
# default build target
all: $(NAME).elf
# flags to use
# MSC_CLOCK selects the clock() function for timing
# printf=__simple_printf makes sure we use the small printf
# -DINTEGER_ONLY removes floating point
DEFINES = -Dprintf=__simple_printf -DMSC_CLOCK -DINTEGER_ONLY -DFIXED_NUMBER_OF_PASSES=$(PASSES)
CFLAGS = $(OPT) $(DEFINES)
#
# include the fragment that defines most of everything
#
include $(COMMON)/common.mk
dry1.o: dry.c
$(CC) $(CFLAGS) -o $@ -c $<
dry2.o: dry.c
$(CC) $(CFLAGS) -DPASS2 -o $@ -c $<
spinix.o: spinix.c
$(CC) $(CFLAGS) -o $@ -c $<

2
cdemos/dry/buildit Normal file
View File

@ -0,0 +1,2 @@
make
propeller-load -s -D clkfreq=1347436867 -D clkmode=98 dry.elf

1053
cdemos/dry/dry.c Normal file

File diff suppressed because it is too large Load Diff

45
cdemos/dry/spinix.c Normal file
View File

@ -0,0 +1,45 @@
#include <propeller.h>
#include "spinix.h"
static int run_prog[] = {
0xa0bc65f0, 0x08bc6e32, 0x80fc6404, 0x08bc7032, 0x80fc6404, 0x08bc6032,
0x80fc6404, 0x08bc6232, 0x80fc63ff, 0x28fc6209, 0x08fc6600, 0x00fc6804,
0x083c6029, 0x083c5c2a, 0x083c582b, 0x08bc642b, 0x863c642c, 0x5c68000f,
0x80fc6001, 0x80fc5d00, 0x80fc5d00, 0xe4fc620c, 0x087c6600, 0x007c6804,
0x04fc6a08, 0x04fc6c0a, 0xa0bc6236, 0x84bc6235, 0x28fc6202, 0x083c5a35,
0x80fc6a04, 0xe4fc621d, 0x083c5a36, 0x80fc6c04, 0x083c6e36, 0x80fc6c04,
0x083c7036, 0x0cfc6401, 0x60fc6407, 0x68bc5e32, 0x0c7c5e02, 0x00007fd8,
0x00007fdc, 0x00007fd4, 0x00000072, 0x00000000, 0x00000000, 0x0007c010};
static int arg_list[] = {0, 0, 0, 0};
void spinix_enter(int argc, char **argv)
{
}
void spinix_exit(int retval)
{
int i;
int cogspi = (*(int *)spinix_spi_engine_cog) - 1;
arg_list[2] = *(int *)spinix_shell_sector;
arg_list[3] = *(int *)spinix_shell_size;
*(int *)spinix_return_value = retval;
// Stop all the cogs except this one and the SD SPI cog
for (i = 0; i < 8; i++)
{
if (i != cogid() && i != cogspi)
cogstop(i);
}
// Clear and return all the locks
for (i = 0; i < 8; i++)
{
lockclr(i);
lockret(i);
}
// Start run_prog in this cog
coginit(cogid(), run_prog, arg_list);
}

45
cdemos/dry/spinix.h Normal file
View File

@ -0,0 +1,45 @@
#define spinix_start 0x7c00 // Extra space for the stand-alone loader
#define spinix_rendezvous 0x7e50
#define spinix_environ_vars 0x7e50
#define spinix_environ_vars_end 0x7ed3
#define spinix_argv_parms 0x7ed4
#define spinix_return_value 0x7f94
#define spinix_vga_cog 0x7f98
#define spinix_vga_handle 0x7f9c
#define spinix_sd_pins 0x7fa0
#define spinix_config 0x7fa4
#define spinix_shell_sector 0x7fa8
#define spinix_unixtime 0x7fac
#define spinix_cycle0 0x7fb0
#define spinix_timezone 0x7fb4
#define spinix_scriptline 0x7fb8
#define spinix_ifflag 0x7fbc
#define spinix_whileflag 0x7fc0
#define spinix_shell_size 0x7fc4
#define spinix_shell_level 0x7fc8
#define spinix_bootflag 0x7fcc
#define spinix_spi_engine_cog 0x7fd0
#define spinix_spi_command 0x7fd4
#define spinix_spi_block_index 0x7fd8
#define spinix_spi_buffer_address 0x7fdc
#define spinix_serial 0x7fe0
#define spinix_stdio 0x7fe4
#define spinix_stdin 0x7fe8
#define spinix_stdout 0x7fec
#define spinix_memlocknum 0x7ff0
#define spinix_memfreelist 0x7ff4
#define spinix_malloclist 0x7ff8
#define spinix_laststackaddr 0x7ffc
#define spinix_checkword 0xdead1eaf
#define spinix_proc_type_spin 1
#define spinix_proc_type_pasm 2
#define spinix_proc_type_capp 3
#define spinix_proc_type_driver 0x80
#define spinix_run_shell_wait 0x00
#define spinix_run_shell_nowait 0x08
#define spinix_run_kill_caller 0x10
#define spinix_run_at_address0 0x20
#define spinix_run_c_program 0x40
#define spinix_run_spin_program 0x80
#define spinix_run_stand_alone 0x100

22
cdemos/fibo/Makefile Normal file
View File

@ -0,0 +1,22 @@
#
# objects for this program
#
PROPLIB = ../common
NAME = fibo
OBJS = fibo.o spinix.o
# memory model
MODEL = lmm
#
# enable experimental fcache code for this demo
#
#CFLAGS = -Os -mfcache
CFLAGS = -g -Os
#CFLAGS = -g
all: $(NAME).elf
include $(PROPLIB)/common.mk

2
cdemos/fibo/buildit Normal file
View File

@ -0,0 +1,2 @@
propeller-elf-gcc -Os -mlmm -o fibo.elf fibo.c spinix.c
propeller-load -s -D clkfreq=1347436867 -D clkmode=98 fibo.elf

47
cdemos/fibo/fibo.c Normal file
View File

@ -0,0 +1,47 @@
//#include <stdio.h>
//#include <string.h>
//#include <stdlib.h>
#include <stdio.h>
#include <propeller.h>
#include "spinix.h"
//#define CNT _CNT
//#define CLKFREQ _CLKFREQ
unsigned int fibo (unsigned int n)
{
if (n < 2)
{
return (n);
}
else
{
return fibo(n - 1) + fibo(n - 2);
}
}
extern unsigned int clock(void);
int main (int argc, char* argv[])
{
int n;
int result;
unsigned int startTime;
unsigned int endTime;
unsigned int executionTime;
unsigned int rawTime;
printf("hello, world!\r\n");
for (n = 0; n <= 26; n++)
{
printf("fibo(%02d) = ", n);
startTime = clock();
result = fibo(n);
endTime = clock();
rawTime = endTime - startTime;
executionTime = rawTime / (CLKFREQ / 1000);
printf ("%06d (%05ums) (%u ticks)\n", result, executionTime, rawTime);
}
spinix_exit(0);
}

45
cdemos/fibo/spinix.c Normal file
View File

@ -0,0 +1,45 @@
#include <propeller.h>
#include "spinix.h"
static int run_prog[] = {
0xa0bc65f0, 0x08bc6e32, 0x80fc6404, 0x08bc7032, 0x80fc6404, 0x08bc6032,
0x80fc6404, 0x08bc6232, 0x80fc63ff, 0x28fc6209, 0x08fc6600, 0x00fc6804,
0x083c6029, 0x083c5c2a, 0x083c582b, 0x08bc642b, 0x863c642c, 0x5c68000f,
0x80fc6001, 0x80fc5d00, 0x80fc5d00, 0xe4fc620c, 0x087c6600, 0x007c6804,
0x04fc6a08, 0x04fc6c0a, 0xa0bc6236, 0x84bc6235, 0x28fc6202, 0x083c5a35,
0x80fc6a04, 0xe4fc621d, 0x083c5a36, 0x80fc6c04, 0x083c6e36, 0x80fc6c04,
0x083c7036, 0x0cfc6401, 0x60fc6407, 0x68bc5e32, 0x0c7c5e02, 0x00007fd8,
0x00007fdc, 0x00007fd4, 0x00000072, 0x00000000, 0x00000000, 0x0007c010};
static int arg_list[] = {0, 0, 0, 0};
void spinix_enter(int argc, char **argv)
{
}
void spinix_exit(int retval)
{
int i;
int cogspi = (*(int *)spinix_spi_engine_cog) - 1;
arg_list[2] = *(int *)spinix_shell_sector;
arg_list[3] = *(int *)spinix_shell_size;
*(int *)spinix_return_value = retval;
// Stop all the cogs except this one and the SD SPI cog
for (i = 0; i < 8; i++)
{
if (i != cogid() && i != cogspi)
cogstop(i);
}
// Clear and return all the locks
for (i = 0; i < 8; i++)
{
lockclr(i);
lockret(i);
}
// Start run_prog in this cog
coginit(cogid(), run_prog, arg_list);
}

45
cdemos/fibo/spinix.h Normal file
View File

@ -0,0 +1,45 @@
#define spinix_start 0x7c00 // Extra space for the stand-alone loader
#define spinix_rendezvous 0x7e50
#define spinix_environ_vars 0x7e50
#define spinix_environ_vars_end 0x7ed3
#define spinix_argv_parms 0x7ed4
#define spinix_return_value 0x7f94
#define spinix_vga_cog 0x7f98
#define spinix_vga_handle 0x7f9c
#define spinix_sd_pins 0x7fa0
#define spinix_config 0x7fa4
#define spinix_shell_sector 0x7fa8
#define spinix_unixtime 0x7fac
#define spinix_cycle0 0x7fb0
#define spinix_timezone 0x7fb4
#define spinix_scriptline 0x7fb8
#define spinix_ifflag 0x7fbc
#define spinix_whileflag 0x7fc0
#define spinix_shell_size 0x7fc4
#define spinix_shell_level 0x7fc8
#define spinix_bootflag 0x7fcc
#define spinix_spi_engine_cog 0x7fd0
#define spinix_spi_command 0x7fd4
#define spinix_spi_block_index 0x7fd8
#define spinix_spi_buffer_address 0x7fdc
#define spinix_serial 0x7fe0
#define spinix_stdio 0x7fe4
#define spinix_stdin 0x7fe8
#define spinix_stdout 0x7fec
#define spinix_memlocknum 0x7ff0
#define spinix_memfreelist 0x7ff4
#define spinix_malloclist 0x7ff8
#define spinix_laststackaddr 0x7ffc
#define spinix_checkword 0xdead1eaf
#define spinix_proc_type_spin 1
#define spinix_proc_type_pasm 2
#define spinix_proc_type_capp 3
#define spinix_proc_type_driver 0x80
#define spinix_run_shell_wait 0x00
#define spinix_run_shell_nowait 0x08
#define spinix_run_kill_caller 0x10
#define spinix_run_at_address0 0x20
#define spinix_run_c_program 0x40
#define spinix_run_spin_program 0x80
#define spinix_run_stand_alone 0x100

22
cdemos/hello/Makefile Normal file
View File

@ -0,0 +1,22 @@
#
# objects for this program
#
PROPLIB = ../common
NAME = hello
OBJS = hello.o spinix.o
# memory model
MODEL = lmm
#
# enable experimental fcache code for this demo
#
#CFLAGS = -Os -mfcache
CFLAGS = -g -Os
#CFLAGS = -g
all: $(NAME).elf
include $(PROPLIB)/common.mk

2
cdemos/hello/buildit Normal file
View File

@ -0,0 +1,2 @@
propeller-elf-gcc -Os -mlmm -o hello.elf hello.c spinix.c
propeller-load -s -D clkfreq=1347436867 -D clkmode=98 hello.elf

9
cdemos/hello/hello.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdio.h>
#include "spinix.h"
int main (int argc, char **argv)
{
spinix_enter();
printf("Hello World!\n");
spinix_exit(0);
}

45
cdemos/hello/spinix.c Normal file
View File

@ -0,0 +1,45 @@
#include <propeller.h>
#include "spinix.h"
static int run_prog[] = {
0xa0bc65f0, 0x08bc6e32, 0x80fc6404, 0x08bc7032, 0x80fc6404, 0x08bc6032,
0x80fc6404, 0x08bc6232, 0x80fc63ff, 0x28fc6209, 0x08fc6600, 0x00fc6804,
0x083c6029, 0x083c5c2a, 0x083c582b, 0x08bc642b, 0x863c642c, 0x5c68000f,
0x80fc6001, 0x80fc5d00, 0x80fc5d00, 0xe4fc620c, 0x087c6600, 0x007c6804,
0x04fc6a08, 0x04fc6c0a, 0xa0bc6236, 0x84bc6235, 0x28fc6202, 0x083c5a35,
0x80fc6a04, 0xe4fc621d, 0x083c5a36, 0x80fc6c04, 0x083c6e36, 0x80fc6c04,
0x083c7036, 0x0cfc6401, 0x60fc6407, 0x68bc5e32, 0x0c7c5e02, 0x00007fd8,
0x00007fdc, 0x00007fd4, 0x00000072, 0x00000000, 0x00000000, 0x0007c010};
static int arg_list[] = {0, 0, 0, 0};
void spinix_enter(int argc, char **argv)
{
}
void spinix_exit(int retval)
{
int i;
int cogspi = (*(int *)spinix_spi_engine_cog) - 1;
arg_list[2] = *(int *)spinix_shell_sector;
arg_list[3] = *(int *)spinix_shell_size;
*(int *)spinix_return_value = retval;
// Stop all the cogs except this one and the SD SPI cog
for (i = 0; i < 8; i++)
{
if (i != cogid() && i != cogspi)
cogstop(i);
}
// Clear and return all the locks
for (i = 0; i < 8; i++)
{
lockclr(i);
lockret(i);
}
// Start run_prog in this cog
coginit(cogid(), run_prog, arg_list);
}

45
cdemos/hello/spinix.h Normal file
View File

@ -0,0 +1,45 @@
#define spinix_start 0x7c00 // Extra space for the stand-alone loader
#define spinix_rendezvous 0x7e50
#define spinix_environ_vars 0x7e50
#define spinix_environ_vars_end 0x7ed3
#define spinix_argv_parms 0x7ed4
#define spinix_return_value 0x7f94
#define spinix_vga_cog 0x7f98
#define spinix_vga_handle 0x7f9c
#define spinix_sd_pins 0x7fa0
#define spinix_config 0x7fa4
#define spinix_shell_sector 0x7fa8
#define spinix_unixtime 0x7fac
#define spinix_cycle0 0x7fb0
#define spinix_timezone 0x7fb4
#define spinix_scriptline 0x7fb8
#define spinix_ifflag 0x7fbc
#define spinix_whileflag 0x7fc0
#define spinix_shell_size 0x7fc4
#define spinix_shell_level 0x7fc8
#define spinix_bootflag 0x7fcc
#define spinix_spi_engine_cog 0x7fd0
#define spinix_spi_command 0x7fd4
#define spinix_spi_block_index 0x7fd8
#define spinix_spi_buffer_address 0x7fdc
#define spinix_serial 0x7fe0
#define spinix_stdio 0x7fe4
#define spinix_stdin 0x7fe8
#define spinix_stdout 0x7fec
#define spinix_memlocknum 0x7ff0
#define spinix_memfreelist 0x7ff4
#define spinix_malloclist 0x7ff8
#define spinix_laststackaddr 0x7ffc
#define spinix_checkword 0xdead1eaf
#define spinix_proc_type_spin 1
#define spinix_proc_type_pasm 2
#define spinix_proc_type_capp 3
#define spinix_proc_type_driver 0x80
#define spinix_run_shell_wait 0x00
#define spinix_run_shell_nowait 0x08
#define spinix_run_kill_caller 0x10
#define spinix_run_at_address0 0x20
#define spinix_run_c_program 0x40
#define spinix_run_spin_program 0x80
#define spinix_run_stand_alone 0x100

2
chess/buildit Normal file
View File

@ -0,0 +1,2 @@
propeller-elf-gcc -o chess.elf -Os -mlmm -fno-exceptions chess.c -ltiny -lpthread
propeller-load -s chess.elf

1412
chess/chess.c Normal file

File diff suppressed because it is too large Load Diff

8
chess/chess.side Normal file
View File

@ -0,0 +1,8 @@
chess.c
>compiler=C
>memtype=lmm main ram
>optimize=-Os
>-fno-exceptions
>-ltiny
>-lpthread
>BOARD::C3F

31
devel/fibo.spn Normal file
View File

@ -0,0 +1,31 @@
con
_clkmode = $62
_clkfreq = $4E495053 ' SPIN
obj
c : "clibsd"
pub main(argc, argv) | n, startTime, endTime, executionTime, rawTime
c.enter(argc, argv)
c.printf0(string("hello, world!\n"))
n := 0
repeat while n =< 26
c.printf1(string("fibo(%d) = "), n)
startTime := clock
result := fibo(n)
endTime := clock
rawTime := endTime - startTime
executionTime := rawTime / (CLKFREQ / 1000)
c.printf3(string("%d (%dms) (%d ticks)\n"), result, executionTime, rawTime)
n++
c.exit(0)
pub clock
result := cnt
pub fibo(n)
if n < 2
return n
else
return fibo(n - 1) + fibo(n - 2)

11
devel/hello.spn Normal file
View File

@ -0,0 +1,11 @@
con
_clkmode = $62
_clkfreq = $4E495053 ' SPIN
obj
c : "clibsd"
pub main(argc, argv)
c.enter(argc, argv)
c.printf0(string("Hello World\n"))
c.exit(0)

7
devel/makepong Normal file
View File

@ -0,0 +1,7 @@
#shell
echo spinit pong
spinit pong
echo spasm pong
spasm pong
echo splink pong.bin pongclib.bin pong
splink pong.bin pongclib.bin pong

13
devel/makepong.all Normal file
View File

@ -0,0 +1,13 @@
#shell
echo spinit pongsubs
spinit pongsubs
echo spasm pongsubs
spasm pongsubs
echo splink pongsubs.bin clibsd.bin pongclib.bin
splink pongsubs.bin clibsd.bin pongclib.bin
echo spinit pong
spinit pong
echo spasm pong
spasm pong
echo splink pong.bin pongclib.bin pong
splink pong.bin pongclib.bin pong

7
devel/makepong.sub Normal file
View File

@ -0,0 +1,7 @@
#shell
echo spinit pongsubs
spinit pongsubs
echo spasm pongsubs
spasm pongsubs
echo splink pongsubs.bin clibsd.bin pongclib.bin
splink pongsubs.bin clibsd.bin pongclib.bin

174
devel/pong.spn Normal file
View File

@ -0,0 +1,174 @@
CON
_clkmode = $62
_clkfreq = $4E495053 ' SPIN
height = 3
xmax = 78
xmin = 1
ymax = 23
ymin = 1
OBJ
p : "pongsubs"
c : "clibsd"
DAT
left long 0
right long 0
config long 0
x long 0
y long 0
xvel long 0
yvel long 0
score0 long 0
score1 long 0
center long 0
xold long 1
yold long 1
pub main(argc, argv) | time, deltat
c.enter(argc, argv)
p.splash
initialize
deltat := clkfreq/20
time := cnt
repeat
check_input
update_position
check_score
p.plotit(xold, yold, p.getval(xold, yold))
p.plotit(x, y, "@")
xold := x
yold := y
time += deltat
repeat while (cnt - time) < deltat
c.setconfig(config)
c.putchar(13)
c.exit(0)
pub initialize | i
c.putchar(0)
config := c.getconfig
c.setconfig(1)
center := (xmin + xmax)/2
p.updatevars(ymin, center, score0, score1)
x := 1
y := 10
xvel := 1
yvel := 1
left := (ymin + ymax)/2
right := left
p.moveto(xmin-1, ymin-1)
i := xmin-1
repeat while i++ =< xmax + 1
c.putchar("#")
p.moveto(xmin-1, ymax+1)
i := xmin-1
repeat while i++ =< xmax + 1
c.putchar("#")
i := ymin
repeat while i =< ymax
p.moveto(center, i)
c.putchar(".")
i++
p.plotpaddle(xmin-1, left, height)
p.plotpaddle(xmax+1, right, height)
p.putnum(center-8, ymin+1, 0)
p.putnum(center+3, ymin+1, 0)
p.moveto(xmin+1, ymin)
pub update_position
x += xvel
y += yvel
if y < ymin
y := ymin - y
yvel := 0 - yvel
c.putchar(7)
elseif y > ymax
y := 2 * ymax - y
yvel := 0 - yvel
c.putchar(7)
pub check_score
if x < xmin
if y =< left + height and y => left - height
x := xmin - x
xvel := 0 - xvel
c.putchar(7)
else
scoreit(1)
elseif x > xmax
if y =< right + height and y => right - height
x := 2 * xmax - x
xvel := 0 - xvel
c.putchar(7)
else
scoreit(0)
if y =< left + height and y => left - height
pub check_input | val
repeat while p.kbhit
val := c.getchar
if val == "x"
c.putchar(0)
c.setconfig(config)
c.exit(0)
if val == "q"
move_left_up
move_left_up
if val == "a"
move_left_down
move_left_down
if val == "p"
move_right_up
move_right_up
if val == "l"
move_right_down
move_right_down
pub move_left_up
if left > ymin + height
p.plotit(xmin-1, left + height, " ")
left--
p.plotit(xmin-1, left - height, "#")
pub move_left_down
if left < ymax - height
p.plotit(xmin-1, left - height, " ")
left++
p.plotit(xmin-1, left + height, "#")
pub move_right_up
if right > ymin + height
p.plotit(xmax+1, right + height, " ")
right--
p.plotit(xmax+1, right - height, "#")
pub move_right_down
if right < ymax - height
p.plotit(xmax+1, right - height, " ")
right++
p.plotit(xmax+1, right + height, "#")
pub scoreit(player)
if player
score1++
p.putnum(center+3, ymin+1, score1)
if right > (ymin+ymax)/2
y := right - height - 3
else
y := right + height + 3
x := xmax + 1
xvel := 0 - 1
else
score0++
p.putnum(center-8, ymin+1, score0)
if left > (ymin+ymax)/2
y := left - height - 3
else
y := left + height + 3
x := xmin - 1
xvel := 1
yvel := 1
p.updatevars(ymin, center, score0, score1)

97
devel/pongsubs.spn Normal file
View File

@ -0,0 +1,97 @@
OBJ
c : "clibsd"
dat
score0 long 0
score1 long 0
ymin long 0
center long 0
pub splash
c.putchar(0)
c.printf0(string("PONG\n"))
c.printf0(string("----\n"))
c.printf0(string("Press 'q' and 'a' to move the"))
c.printf0(string(" left paddle up and down\n"))
c.printf0(string("Press 'p' and 'l' to move the"))
c.printf0(string(" right paddle up and down\n"))
c.printf0(string("Press 'x' to exit\n"))
c.printf0(string("Press any key to start\n"))
c.getchar
pub updatevars(p_ymin, p_center, p_score0, p_score1)
ymin := p_ymin
center := p_center
score0 := p_score0
score1 := p_score1
pub plotit(xpos, ypos, val)
moveto(xpos, ypos)
c.putchar(val)
pub moveto(xpos, ypos)
c.putchar(2)
c.putchar(xpos)
c.putchar(ypos)
pub kbhit | stream, handle, rxhead, rxtail
stream := c.getstdin
handle := long[stream][1]
rxhead := word[handle][6]
rxtail := word[handle][7]
return rxhead <> rxtail
dat
digit
byte %111111, %110011, %110011, %110011, %111111
byte %001100, %011100, %001100, %001100, %011110
byte %111111, %000011, %111111, %110000, %111111
byte %111111, %000011, %001111, %000011, %111111
byte %110011, %110011, %111111, %000011, %000011
byte %111111, %110000, %111111, %000011, %111111
byte %111111, %110000, %111111, %110011, %111111
byte %111111, %000011, %000110, %000110, %000110
byte %111111, %110011, %111111, %110011, %111111
byte %111111, %110011, %111111, %000011, %000011
pub getval(xpos, ypos) | ptr, val
if xpos == center
return "."
if ypos < ymin + 1 or ypos > ymin + 5
return " "
if xpos < center - 8 or xpos > center + 8
return " "
if xpos > center - 3 and xpos < center + 3
return " "
if xpos < center
val := score0
xpos -= center - 8
else
val := score1
xpos -= center + 3
val := byte[@digit][val*5 + ypos - ymin - 1]
if val & ($20 >> xpos)
result := "#"
else
result := " "
pub putnum(xpos, ypos, num) | ptr, temp, i, j
i := 5
ptr := @digit + (num//10)*5
repeat while i--
j := 6
temp := byte[ptr++]
moveto(xpos, ypos++)
repeat while j--
if temp & $20
c.putchar("#")
else
c.putchar(" ")
temp <<= 1
pub plotpaddle(xpos, ypos, height) | i
i := ypos - height
repeat while i =< ypos + height
plotit(xpos, i, "#")
i++

62
devel/prime.spn Normal file
View File

@ -0,0 +1,62 @@
con
_clkmode = $62
_clkfreq = $4E495053 ' SPIN
obj
c : "clibsd"
dat
primes long $00020001, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
last long 0
pub main(argc, argv) | i, j, n, num, maxnum, count, prime
c.enter(argc, argv)
if argc <> 2
c.printf0(string("usage: prime max_number\n"))
c.exit(1)
maxnum := 0
i := long[argv][1]
repeat while byte[i]
maxnum := (maxnum * 10) + byte[i++] - "0"
c.printf1(string("%d "), 1)
c.printf1(string("%d "), 2)
num := (@last - @primes)/2
n := 2
i := 3
count := 2
repeat while i < maxnum
j := 2
repeat while j < n
prime := word[@primes][j]
if prime * prime > i
j := n
quit
if i / prime * prime == i
quit
j++
if j == n
if n < num
word[@primes][n++] := i
if n == num and i * i < maxnum
maxnum := i * i
c.printf1(string("%d "), i)
if ++count => 10
count := 0
c.printf0(string("\n"))
i += 2
if count
c.printf0(string("\n"))
c.exit(0)

47
devel/readme.txt Normal file
View File

@ -0,0 +1,47 @@
This directory contains sample Spin programs that can be compiled by the Spin
development tools. These tools consist of spinit, spasm, splink and spc.
spinit is a Spin compiler that produces Spin assmebly (spasm) code. It is
executed as follows:
spinit hello.spn
This will generate the Spasm source file, hello.spa. The Spasm assmebler
is executed as follows:
spasm hello.spa
This will assemble the hello.spa Spasm source file, and generate the
output file hello.bin. The hello programs uses the clibsd object. An
executable file can be created by linking hello.bin with clibsd.bin using
the Spin linke, splink. This is done as follows:
splink hello.bin clibsd.bin hello
You can then run hello as a normal Spinix program.
An assembly listing can be produced by using the -l option, as follows:
spasm -l hello.spa
When running spinit and spasm, the file extensions are optional, and are
assumed to be .spn and .spa if not specified.
A Spin program can be compiled into an executable with one command by using
the spc command. The hello pragram can be built by typing
spc hello
The will run spinit, spasm and splink.
This directory contains the following sample programs:
hello - Hello World Program
fibo - A Spin version of the PropGCC fibo program
prime - A program that prints prime numbers
pong - A simple pong program developed entirely under spinix
pongsubs - Object used by pong
The pong program can be built using the script makepong.all. The pongsubs
object can be built and linked to clibsd using makepong.sub. makepong will
compile pong and link it to the combined pongsubs/clibsd object.

20
filetest/Makefile Normal file
View File

@ -0,0 +1,20 @@
CC=propeller-elf-gcc
MODEL=lmm
CFLAGS=-Os -m$(MODEL)
LDFLAGS=-m$(MODEL)
OBJDIR=./
SRCDIR=./
OBJS = filetest.o printf.o spinix.o file_io.o
HDRS =
filetest.elf: $(OBJS)
@$(CC) $(LDFLAGS) $(OBJS) -o $@ -s
binary:
propeller-load -s -D clkfreq=1347436867 -D clkmode=98 filetest.elf
clean:
rm -f *.o *.elf *.binary
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(HDRS)
@$(CC) $(CFLAGS) -c $< -o $@

394
filetest/dosfs.h Normal file
View File

@ -0,0 +1,394 @@
/*
DOSFS Embedded FAT-Compatible Filesystem
(C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com)
11/5/2011 Added PROPGCC_MODS and DFS_DIRECTORY - Dave Hein
*/
#ifndef _DOSFS_H
#define _DOSFS_H
#include <stdint.h>
#define PROPGCC_MODS /* This flag is used to enable changes for PropGCC */
//===================================================================
// User-supplied functions
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count);
//===================================================================
// Configurable items
#define MAX_PATH 64 // Maximum path length (increasing this will
// GREATLY increase stack requirements!)
#define DIR_SEPARATOR '/' // character separating directory components
// End of configurable items
//===================================================================
//===================================================================
// 32-bit error codes
#define DFS_OK 0 // no error
#define DFS_EOF 1 // end of file (not an error)
#define DFS_WRITEPROT 2 // volume is write protected
#define DFS_NOTFOUND 3 // path or file not found
#define DFS_PATHLEN 4 // path too long
#define DFS_ALLOCNEW 5 // must allocate new directory cluster
#define DFS_IOERR 6 // i/o error
#define DFS_INVAL 7 // invalid argument
#define DFS_ERRMISC 0xffffffff // generic error
//===================================================================
// File access modes
#define DFS_READ 1 // read-only
#define DFS_WRITE 2 // write-only
#ifdef PROPGCC_MODS
#define DFS_DIRECTORY 0x10 // directory-mode
#endif
//===================================================================
// Miscellaneous constants
#define SECTOR_SIZE 512 // sector size in bytes
//===================================================================
// Internal subformat identifiers
#define FAT12 0
#define FAT16 1
#define FAT32 2
//===================================================================
// DOS attribute bits
#define ATTR_READ_ONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUME_ID 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)
/*
Directory entry structure
note: if name[0] == 0xe5, this is a free dir entry
if name[0] == 0x00, this is a free entry and all subsequent entries are free
if name[0] == 0x05, the first character of the name is 0xe5 [a kanji nicety]
Date format: bit 0-4 = day of month (1-31)
bit 5-8 = month, 1=Jan..12=Dec
bit 9-15 = count of years since 1980 (0-127)
Time format: bit 0-4 = 2-second count, (0-29)
bit 5-10 = minutes (0-59)
bit 11-15= hours (0-23)
*/
typedef struct _tagDIRENT {
uint8_t name[11]; // filename
uint8_t attr; // attributes (see ATTR_* constant definitions)
uint8_t reserved; // reserved, must be 0
uint8_t crttimetenth; // create time, 10ths of a second (0-199 are valid)
uint8_t crttime_l; // creation time low byte
uint8_t crttime_h; // creation time high byte
uint8_t crtdate_l; // creation date low byte
uint8_t crtdate_h; // creation date high byte
uint8_t lstaccdate_l; // last access date low byte
uint8_t lstaccdate_h; // last access date high byte
uint8_t startclus_h_l; // high word of first cluster, low byte (FAT32)
uint8_t startclus_h_h; // high word of first cluster, high byte (FAT32)
uint8_t wrttime_l; // last write time low byte
uint8_t wrttime_h; // last write time high byte
uint8_t wrtdate_l; // last write date low byte
uint8_t wrtdate_h; // last write date high byte
uint8_t startclus_l_l; // low word of first cluster, low byte
uint8_t startclus_l_h; // low word of first cluster, high byte
uint8_t filesize_0; // file size, low byte
uint8_t filesize_1; //
uint8_t filesize_2; //
uint8_t filesize_3; // file size, high byte
} DIRENT, *PDIRENT;
/*
Partition table entry structure
*/
typedef struct _tagPTINFO {
uint8_t active; // 0x80 if partition active
uint8_t start_h; // starting head
uint8_t start_cs_l; // starting cylinder and sector (low byte)
uint8_t start_cs_h; // starting cylinder and sector (high byte)
uint8_t type; // type ID byte
uint8_t end_h; // ending head
uint8_t end_cs_l; // ending cylinder and sector (low byte)
uint8_t end_cs_h; // ending cylinder and sector (high byte)
uint8_t start_0; // starting sector# (low byte)
uint8_t start_1; //
uint8_t start_2; //
uint8_t start_3; // starting sector# (high byte)
uint8_t size_0; // size of partition (low byte)
uint8_t size_1; //
uint8_t size_2; //
uint8_t size_3; // size of partition (high byte)
} PTINFO, *PPTINFO;
/*
Master Boot Record structure
*/
typedef struct _tagMBR {
uint8_t bootcode[0x1be]; // boot sector
PTINFO ptable[4]; // four partition table structures
uint8_t sig_55; // 0x55 signature byte
uint8_t sig_aa; // 0xaa signature byte
} MBR, *PMBR;
/*
BIOS Parameter Block structure (FAT12/16)
*/
typedef struct _tagBPB {
uint8_t bytepersec_l; // bytes per sector low byte (0x00)
uint8_t bytepersec_h; // bytes per sector high byte (0x02)
uint8_t secperclus; // sectors per cluster (1,2,4,8,16,32,64,128 are valid)
uint8_t reserved_l; // reserved sectors low byte
uint8_t reserved_h; // reserved sectors high byte
uint8_t numfats; // number of FAT copies (2)
uint8_t rootentries_l; // number of root dir entries low byte (0x00 normally)
uint8_t rootentries_h; // number of root dir entries high byte (0x02 normally)
uint8_t sectors_s_l; // small num sectors low byte
uint8_t sectors_s_h; // small num sectors high byte
uint8_t mediatype; // media descriptor byte
uint8_t secperfat_l; // sectors per FAT low byte
uint8_t secperfat_h; // sectors per FAT high byte
uint8_t secpertrk_l; // sectors per track low byte
uint8_t secpertrk_h; // sectors per track high byte
uint8_t heads_l; // heads low byte
uint8_t heads_h; // heads high byte
uint8_t hidden_0; // hidden sectors low byte
uint8_t hidden_1; // (note - this is the number of MEDIA sectors before
uint8_t hidden_2; // first sector of VOLUME - we rely on the MBR instead)
uint8_t hidden_3; // hidden sectors high byte
uint8_t sectors_l_0; // large num sectors low byte
uint8_t sectors_l_1; //
uint8_t sectors_l_2; //
uint8_t sectors_l_3; // large num sectors high byte
} BPB, *PBPB;
/*
Extended BIOS Parameter Block structure (FAT12/16)
*/
typedef struct _tagEBPB {
uint8_t unit; // int 13h drive#
uint8_t head; // archaic, used by Windows NT-class OSes for flags
uint8_t signature; // 0x28 or 0x29
uint8_t serial_0; // serial#
uint8_t serial_1; // serial#
uint8_t serial_2; // serial#
uint8_t serial_3; // serial#
uint8_t label[11]; // volume label
uint8_t system[8]; // filesystem ID
} EBPB, *PEBPB;
/*
Extended BIOS Parameter Block structure (FAT32)
*/
typedef struct _tagEBPB32 {
uint8_t fatsize_0; // big FAT size in sectors low byte
uint8_t fatsize_1; //
uint8_t fatsize_2; //
uint8_t fatsize_3; // big FAT size in sectors high byte
uint8_t extflags_l; // extended flags low byte
uint8_t extflags_h; // extended flags high byte
uint8_t fsver_l; // filesystem version (0x00) low byte
uint8_t fsver_h; // filesystem version (0x00) high byte
uint8_t root_0; // cluster of root dir, low byte
uint8_t root_1; //
uint8_t root_2; //
uint8_t root_3; // cluster of root dir, high byte
uint8_t fsinfo_l; // sector pointer to FSINFO within reserved area, low byte (2)
uint8_t fsinfo_h; // sector pointer to FSINFO within reserved area, high byte (0)
uint8_t bkboot_l; // sector pointer to backup boot sector within reserved area, low byte (6)
uint8_t bkboot_h; // sector pointer to backup boot sector within reserved area, high byte (0)
uint8_t reserved[12]; // reserved, should be 0
uint8_t unit; // int 13h drive#
uint8_t head; // archaic, used by Windows NT-class OSes for flags
uint8_t signature; // 0x28 or 0x29
uint8_t serial_0; // serial#
uint8_t serial_1; // serial#
uint8_t serial_2; // serial#
uint8_t serial_3; // serial#
uint8_t label[11]; // volume label
uint8_t system[8]; // filesystem ID
} EBPB32, *PEBPB32;
/*
Logical Boot Record structure (volume boot sector)
*/
typedef struct _tagLBR {
uint8_t jump[3]; // JMP instruction
uint8_t oemid[8]; // OEM ID, space-padded
BPB bpb; // BIOS Parameter Block
union {
EBPB ebpb; // FAT12/16 Extended BIOS Parameter Block
EBPB32 ebpb32; // FAT32 Extended BIOS Parameter Block
} ebpb;
uint8_t code[420]; // boot sector code
uint8_t sig_55; // 0x55 signature byte
uint8_t sig_aa; // 0xaa signature byte
} LBR, *PLBR;
/*
Volume information structure (Internal to DOSFS)
*/
typedef struct _tagVOLINFO {
uint8_t unit; // unit on which this volume resides
uint8_t filesystem; // formatted filesystem
// These two fields aren't very useful, so support for them has been commented out to
// save memory. (Note that the "system" tag is not actually used by DOS to determine
// filesystem type - that decision is made entirely on the basis of how many clusters
// the drive contains. DOSFS works the same way).
// See tag: OEMID in dosfs.c
// uint8_t oemid[9]; // OEM ID ASCIIZ
// uint8_t system[9]; // system ID ASCIIZ
uint8_t label[12]; // volume label ASCIIZ
uint32_t startsector; // starting sector of filesystem
uint8_t secperclus; // sectors per cluster
uint16_t reservedsecs; // reserved sectors
uint32_t numsecs; // number of sectors in volume
uint32_t secperfat; // sectors per FAT
uint16_t rootentries; // number of root dir entries
uint32_t numclusters; // number of clusters on drive
// The fields below are PHYSICAL SECTOR NUMBERS.
uint32_t fat1; // starting sector# of FAT copy 1
uint32_t rootdir; // starting sector# of root directory (FAT12/FAT16) or cluster (FAT32)
uint32_t dataarea; // starting sector# of data area (cluster #2)
} VOLINFO, *PVOLINFO;
/*
Flags in DIRINFO.flags
*/
#define DFS_DI_BLANKENT 0x01 // Searching for blank entry
/*
Directory search structure (Internal to DOSFS)
*/
typedef struct _tagDIRINFO {
uint32_t startcluster; // first cluster in dir
uint32_t currentcluster; // current cluster in dir
uint8_t currentsector; // current sector in cluster
uint8_t currententry; // current dir entry in sector
uint8_t *scratch; // ptr to user-supplied scratch buffer (one sector)
uint8_t flags; // internal DOSFS flags
} DIRINFO, *PDIRINFO;
/*
File handle structure (Internal to DOSFS)
*/
typedef struct _tagFILEINFO {
PVOLINFO volinfo; // VOLINFO used to open this file
uint32_t dirsector; // physical sector containing dir entry of this file
uint8_t diroffset; // # of this entry within the dir sector
uint8_t mode; // mode in which this file was opened
uint32_t firstcluster; // first cluster of file
uint32_t filelen; // byte length of file
uint32_t cluster; // current cluster
uint32_t pointer; // current (BYTE) pointer
uint32_t parentcluster; // first cluster of parent dir
} FILEINFO, *PFILEINFO;
/*
Set the Date and Time in a DIRENT to the Default Date and Time.
*/
void DFS_SetDirEntDateTime(PDIRENT pde);
/*
Set the Cluster in a DIRENT
*/
void DFS_SetStartCluster(PDIRENT pde, uint32_t cluster);
/*
Get starting sector# of specified partition on drive #unit
NOTE: This code ASSUMES an MBR on the disk.
scratchsector should point to a SECTOR_SIZE scratch area
Returns 0xffffffff for any error.
If pactive is non-NULL, this function also returns the partition active flag.
If pptype is non-NULL, this function also returns the partition type.
If psize is non-NULL, this function also returns the partition size.
*/
uint32_t DFS_GetPtnStart(uint8_t unit, uint8_t *scratchsector, uint8_t pnum, uint8_t *pactive, uint8_t *pptype, uint32_t *psize);
/*
Retrieve volume info from BPB and store it in a VOLINFO structure
You must provide the unit and starting sector of the filesystem, and
a pointer to a sector buffer for scratch
Attempts to read BPB and glean information about the FS from that.
Returns 0 OK, nonzero for any error.
*/
uint32_t DFS_GetVolInfo(uint8_t unit, uint8_t *scratchsector, uint32_t startsector, PVOLINFO volinfo);
/*
Open a directory for enumeration by DFS_GetNextDirEnt
You must supply a populated VOLINFO (see DFS_GetVolInfo)
The empty string or a string containing only the directory separator are
considered to be the root directory.
Returns 0 OK, nonzero for any error.
*/
uint32_t DFS_OpenDir(PVOLINFO volinfo, uint8_t *dirname, PDIRINFO dirinfo);
/*
Get next entry in opened directory structure. Copies fields into the dirent
structure, updates dirinfo. Note that it is the _caller's_ responsibility to
handle the '.' and '..' entries.
A deleted file will be returned as a NULL entry (first char of filename=0)
by this code. Filenames beginning with 0x05 will be translated to 0xE5
automatically. Long file name entries will be returned as NULL.
returns DFS_EOF if there are no more entries, DFS_OK if this entry is valid,
or DFS_ERRMISC for a media error
*/
uint32_t DFS_GetNext(PVOLINFO volinfo, PDIRINFO dirinfo, PDIRENT dirent);
/*
Open a file for reading or writing. You supply populated VOLINFO, a path to the file,
mode (DFS_READ or DFS_WRITE) and an empty fileinfo structure. You also need to
provide a pointer to a sector-sized scratch buffer.
Returns various DFS_* error states. If the result is DFS_OK, fileinfo can be used
to access the file from this point on.
*/
uint32_t DFS_OpenFile(PVOLINFO volinfo, uint8_t *path, uint8_t mode, uint8_t *scratch, PFILEINFO fileinfo);
/*
Read an open file
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
pointer to a SECTOR_SIZE scratch buffer.
Note that returning DFS_EOF is not an error condition. This function updates the
successcount field with the number of bytes actually read.
*/
uint32_t DFS_ReadFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
/*
Write an open file
You must supply a prepopulated FILEINFO as provided by DFS_OpenFile, and a
pointer to a SECTOR_SIZE scratch buffer.
This function updates the successcount field with the number of bytes actually written.
*/
uint32_t DFS_WriteFile(PFILEINFO fileinfo, uint8_t *scratch, uint8_t *buffer, uint32_t *successcount, uint32_t len);
/*
Seek file pointer to a given position
This function does not return status - refer to the fileinfo->pointer value
to see where the pointer wound up.
Requires a SECTOR_SIZE scratch buffer
*/
void DFS_Seek(PFILEINFO fileinfo, uint32_t offset, uint8_t *scratch);
/*
Delete a file
scratch must point to a sector-sized buffer
*/
uint32_t DFS_UnlinkFile(PVOLINFO volinfo, uint8_t *path, uint8_t *scratch);
// If we are building a host-emulation version, include host support
#ifdef HOSTVER
#include "hostemu.h"
#endif
#endif // _DOSFS_H

87
filetest/enter.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include <string.h>
#include "spinix.h"
#include "varsubs.h"
static char retvalstr[16];
void sprintdec(char *str, int val)
{
int scale;
int zeroflag = 0;
if (val < 0)
{
*str++ = '-';
val = -val;
}
for (scale = 1000000000; scale > 1; scale /= 10)
{
if (val >= scale)
{
*str++ = '0' + val/scale;
val %= scale;
zeroflag = 1;
}
else if (zeroflag)
*str++ = '0';
}
*str++ = '0' + val;
*str = 0;
}
char *varsubs_FindVar(char *str)
{
char *ptr = (char *)spinix_environ_vars;
while (*ptr)
{
if (!strcmp(str, ptr + 1))
{
if (*ptr != varsubs_ALIAS_FLAG)
{
return ptr;
}
}
ptr += strlen(ptr) + 1;
ptr += strlen(ptr) + 1;
}
return 0;
}
char *varsubs_GetVarVal(char *name)
{
char *ptr;
if (!strcmp(name, "?"))
{
sprintdec(retvalstr, *(int *)spinix_return_value);
return retvalstr;
}
if ((ptr = varsubs_FindVar(name)))
{
return ptr + strlen(ptr) + 1;
}
return "";
}
void enter(void)
{
char *mode;
char *ptr = varsubs_GetVarVal("PWD");
if (ptr) chdir(ptr);
ptr = varsubs_GetVarVal("<");
if (*ptr)
printf("stdin = %s\n", ptr);
ptr = varsubs_GetVarVal(">");
if (*ptr)
mode = ">";
else
{
ptr = varsubs_GetVarVal(">>");
if (*ptr)
mode = ">>";
}
printf("stdout = %s %s\n", mode, ptr);
}

180
filetest/file_io.c Normal file
View File

@ -0,0 +1,180 @@
/*
# #########################################################
# This file contains the SD driver code for the C3
# Propeller board. It contains the low-level three file
# system routines, which are DFS_InitFileIO, DFS_ReadSector
# and DFS_WriteSector.
#
# Written by Dave Hein with contributions from other GCC
# development team members.
# Copyright (c) 2011 Parallax, Inc.
# MIT Licensed
# #########################################################
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/driver.h>
#include <compiler.h>
#include <errno.h>
#include <propeller.h>
#include "sd_internal.h"
#define SD_INIT_CMD 0x0d
#define SD_READ_CMD 0x11
#define SD_WRITE_CMD 0x15
#define BUS_LOCK_CMD 0x1D
static volatile uint32_t __attribute__((section(".hub"))) sd_lock = -1;
static volatile uint32_t __attribute__((section(".hub"))) *sd_mbox;
#if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
#define USE_XMM_MBOX
extern uint16_t _xmm_mbox_p;
#endif
uint32_t *_sd_mbox_p = 0;
// This routine sends a command to the driver cog and returns the result
// It must be loaded in HUB RAM so we don't generate a cache miss
static uint32_t __attribute__((section(".hubtext"))) do_cmd(uint32_t *params)
{
//printf("%x %x %x %x\n", sd_mbox, params[0], params[1], params[2]);
sd_mbox[1] = params[1];
sd_mbox[2] = params[2];
sd_mbox[0] = params[0];
while (sd_mbox[0] == params[0]);
return sd_mbox[0];
}
// This routine passes a bus lock to the low-level driver
void dfs_use_lock(uint32_t lockId)
{
#if 0
if (sd_mbox)
do_cmd(BUS_LOCK_CMD | (lockId << 8));
else
#endif
sd_lock = lockId;
}
// This routine initializes the low-level driver
int DFS_InitFileIO(void)
{
#if 0
int retries = 5;
#if !defined(USE_XMM_MBOX)
sd_mbox = _sd_mbox_p;
if (!_sd_mbox_p)
return DFS_INVAL;
#else
if (_sd_mbox_p)
sd_mbox = _sd_mbox_p;
else
{
sd_mbox = (uint32_t *)(uint32_t)_xmm_mbox_p;
retries = -1; // We're using the SD Cache driver - it's already initialized!
}
#endif
// Handle the case where we were given the lock before dfs_mount() was called.
if (sd_lock != -1)
dfs_use_lock(sd_lock);
while (retries-- > 0)
{
if (do_cmd(SD_INIT_CMD) == 0)
return DFS_OK;
}
return DFS_IOERR;
#else
sd_mbox = (uint32_t *)0x7fd4;
return DFS_OK;
#endif
}
// This routine reads 512-byte sectors into a buffer. If the buffer is
// not located in hub memory it reads the sectors into the scratch buffer,
// and then copies it to to the buffer.
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
{
uint32_t params[3], result;
while (count > 0) {
if (((uint32_t)buffer) & 0xffff0000)
params[2] = (uint32_t)dfs_scratch;
else
params[2] = (uint32_t)buffer;
params[0] = 'r';
params[1] = sector;
result = do_cmd(params);
if (result != 0) {
return DFS_IOERR;
}
if (((uint32_t)buffer) & 0xffff0000)
memcpy(buffer, dfs_scratch, SECTOR_SIZE);
buffer += SECTOR_SIZE;
++sector;
--count;
}
return DFS_OK;
}
// This routine writes 512-byte sectors from a buffer. If the buffer is
// not located in hub memory the data is first copied to the scratch buffer,
// and then written from the scratch buffer.
uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count)
{
uint32_t params[3], result;
while (count > 0) {
if (((uint32_t)buffer) & 0xffff0000)
{
memcpy(dfs_scratch, buffer, SECTOR_SIZE);
params[2] = (uint32_t)dfs_scratch;
}
else
params[2] = (uint32_t)buffer;
params[0] = 'w';
params[1] = sector;
result = do_cmd(params);
if (result != 0) {
return DFS_IOERR;
}
buffer += SECTOR_SIZE;
++sector;
--count;
}
return DFS_OK;
}
void LoadSDDriver(uint32_t configwords[2])
{
}
/*
+--------------------------------------------------------------------
| TERMS OF USE: MIT License
+--------------------------------------------------------------------
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------
*/

505
filetest/filetest.c Normal file
View File

@ -0,0 +1,505 @@
/*
############################################################################
# This program is used to test the basic functions of the SD file system.
# It implements simple versions of the cat, rm, ls, echo, cd, pwd, mkdir and
# rmdir commands plus the <, > and >> file redirection operators.
# The program starts up the file driver and then prompts for a command.
#
# Written by Dave Hein
# Copyright (c) 2011 Parallax, Inc.
# MIT Licensed
############################################################################
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cog.h>
#include <propeller.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include "spinix.h"
extern _Driver _SimpleSerialDriver;
extern _Driver _FileDriver;
/* This is a list of all drivers we can use in the
* program. The default _InitIO function opens stdin,
* stdout, and stderr based on the first driver in
* the list (the serial driver, for us)
*/
_Driver *_driverlist[] = {
&_SimpleSerialDriver,
&_FileDriver,
NULL
};
char *FindChar(char *ptr, int val);
FILE *stdinfile;
FILE *stdoutfile;
/* Print help information */
void Help()
{
printf("Commands are help, cat, rm, ls, ll, echo, cd, pwd and exit\n");
}
void Cd(int argc, char **argv)
{
if (argc < 2) return;
if (chdir(argv[1]))
perror(argv[1]);
}
void Pwd(int argc, char **argv)
{
uint8_t buffer[64];
char *ptr = getcwd(buffer, 64);
if (!ptr)
perror(0);
else
fprintf(stdoutfile, "%s\n", ptr);
}
#if 0
void Mkdir(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if (mkdir(argv[i], 0))
perror(argv[i]);
}
}
void Rmdir(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if (rmdir(argv[i]))
perror(argv[i]);
}
}
#endif
/* This routine implements the file cat function */
void Cat(int argc, char **argv)
{
int i;
int num;
void *infile;
uint8_t buffer[40];
for (i = 0; i < argc; i++)
{
if (i == 0)
{
if (argc == 1 || stdinfile != stdin)
infile = stdinfile;
else
continue;
}
else
{
infile = fopen(argv[i], "r");
if (infile == 0)
{
perror(argv[i]);
continue;
}
}
if (infile == stdin)
{
while (gets(buffer))
{
if (buffer[0] == 4) break;
fprintf(stdoutfile, "%s\n", buffer);
}
}
else
{
while ((num = fread(buffer, 1, 40, infile)))
fwrite(buffer, 1, num, stdoutfile);
}
if (i)
fclose(infile);
}
fflush(stdout);
}
/* This routine deletes the files specified by the command line arguments */
void Remove(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if (remove(argv[i]))
perror(argv[i]);
}
}
/* This routine echos the command line arguments */
void Echo(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if (i != argc - 1)
fprintf(stdoutfile, "%s ", argv[i]);
else
fprintf(stdoutfile, "%s\n", argv[i]);
}
}
/* This routine lists the root directory or any subdirectories specified
in the command line arguments. If the "-l" option is specified, it
will print the file attributes and size. Otherwise, it will just
print the file names. */
void List(int argc, char **argv)
{
int i, j;
char *ptr;
char fname[13];
int32_t count = 0;
uint32_t filesize;
uint32_t longflag = 0;
char *path;
char drwx[5];
int column;
int prevlen;
DIR *dirp;
struct dirent *entry;
// Check flags
for (j = 1; j < argc; j++)
{
if (argv[j][0] == '-')
{
if (!strcmp(argv[j], "-l"))
longflag = 1;
else
printf("Unknown option \"%s\"\n", argv[j]);
}
else
count++;
}
// List directories
for (j = 1; j < argc || count == 0; j++)
{
if (count == 0)
{
count--;
path = "./";
}
else if (argv[j][0] == '-')
continue;
else
path = argv[j];
if (count >= 2)
fprintf(stdoutfile, "\n%s:\n", path);
dirp = opendir(path);
if (!dirp)
{
perror(path);
continue;
}
column = 0;
prevlen = 14;
while (entry = readdir(dirp))
{
if (entry->name[0] == '.') continue;
ptr = fname;
for (i = 0; i < 8; i++)
{
if (entry->name[i] == ' ') break;
*ptr++ = tolower(entry->name[i]);
}
if (entry->name[8] != ' ')
{
*ptr++ = '.';
for (i = 8; i < 11; i++)
{
if (entry->name[i] == ' ') break;
*ptr++ = tolower(entry->name[i]);
}
}
*ptr = 0;
filesize = entry->filesize_3;
filesize = (filesize << 8) | entry->filesize_2;
filesize = (filesize << 8) | entry->filesize_1;
filesize = (filesize << 8) | entry->filesize_0;
strcpy(drwx, "-rw-");
if (entry->attr & ATTR_READ_ONLY)
drwx[2] = '-';
if (entry->attr & ATTR_ARCHIVE)
drwx[3] = 'x';
if (entry->attr & ATTR_DIRECTORY)
{
drwx[0] = 'd';
drwx[3] = 'x';
}
if (longflag)
fprintf(stdoutfile, "%s %8d %s\n", drwx, filesize, fname);
else if (++column == 5)
{
for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " ");
fprintf(stdoutfile, "%s\n", fname);
column = 0;
prevlen = 14;
}
else
{
for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " ");
prevlen = strlen(fname);
fprintf(stdoutfile, "%s", fname);
}
}
closedir(dirp);
if (!longflag && column)
fprintf(stdoutfile, "\n");
}
}
/* This routine returns a pointer to the first character that doesn't
match val. */
char *SkipChar(char *ptr, int val)
{
while (*ptr)
{
if (*ptr != val) break;
ptr++;
}
return ptr;
}
/* This routine returns a pointer to the first character that matches val. */
char *FindChar(char *ptr, int val)
{
while (*ptr)
{
if (*ptr == val) break;
ptr++;
}
return ptr;
}
/* This routine extracts tokens from a string that are separated by one or
more spaces. It returns the number of tokens found. */
int tokenize(char *ptr, char *tokens[])
{
int num = 0;
while (*ptr)
{
ptr = SkipChar(ptr, ' ');
if (*ptr == 0) break;
if (ptr[0] == '>')
{
ptr++;
if (ptr[0] == '>')
{
tokens[num++] = ">>";
ptr++;
}
else
tokens[num++] = ">";
continue;
}
if (ptr[0] == '<')
{
ptr++;
tokens[num++] = "<";
continue;
}
tokens[num++] = ptr;
ptr = FindChar(ptr, ' ');
if (*ptr) *ptr++ = 0;
}
return num;
}
/* This routine searches the list of tokens for the redirection operators
and opens the files for input, output or append depending on the
operator. */
int CheckRedirection(char **tokens, int num)
{
int i, j;
for (i = 0; i < num-1; i++)
{
if (!strcmp(tokens[i], ">"))
{
stdoutfile = fopen(tokens[i+1], "w");
if (!stdoutfile)
{
perror(tokens[i+1]);
stdoutfile = stdout;
return 0;
}
}
else if (!strcmp(tokens[i], ">>"))
{
stdoutfile = fopen(tokens[i+1], "a");
if (!stdoutfile)
{
perror(tokens[i+1]);
stdoutfile = stdout;
return 0;
}
}
else if (!strcmp(tokens[i], "<"))
{
stdinfile = fopen(tokens[i+1], "r");
if (!stdinfile)
{
perror(tokens[i+1]);
stdinfile = stdin;
return 0;
}
}
else
continue;
for (j = i + 2; j < num; j++) tokens[j-2] = tokens[j];
i--;
num -= 2;
}
return num;
}
/* This routine closes files that were open for redirection */
void CloseRedirection()
{
if (stdinfile != stdin)
{
fclose(stdinfile);
stdinfile = stdin;
}
if (stdoutfile != stdout)
{
fclose(stdoutfile);
stdoutfile = stdout;
}
}
int getdec(char *ptr)
{
int val = 0;
while (*ptr) val = (val * 10) + *ptr++ - '0';
return val;
}
static char pins[4];
static char *CWD;
#if 0
void GetConfig(int argc, char **argv)
{
unsigned int *lptr;
char *ptr = argv[argc-1];
ptr += strlen(ptr) + 1;
ptr = (char *)(((((int)ptr) + 3) >> 2) << 2);
lptr = (unsigned int *)ptr;
//printf("%8.8x, %8.8x, %s\n", lptr[0], lptr[1], ptr + 8);
memcpy(pins, &lptr[1], 4);
CWD = ptr + 8;
}
#endif
/* The program starts the file system. It then loops reading commands
and calling the appropriate routine to process it. */
int main(int argc, char **argv)
{
int num;
char *tokens[20];
uint8_t buffer[80];
stdinfile = stdin;
stdoutfile = stdout;
spinix_enter();
printf("\n");
Help();
while (1)
{
printf("\n> ");
fflush(stdout);
gets(buffer);
num = tokenize(buffer, tokens);
num = CheckRedirection(tokens, num);
if (num == 0) continue;
if (!strcmp(tokens[0], "help"))
Help();
else if (!strcmp(tokens[0], "cat"))
Cat(num, tokens);
else if (!strcmp(tokens[0], "ls"))
List(num, tokens);
else if (!strcmp(tokens[0], "ll"))
{
tokens[num++] = "-l";
List(num, tokens);
}
else if (!strcmp(tokens[0], "rm"))
Remove(num, tokens);
else if (!strcmp(tokens[0], "echo"))
Echo(num, tokens);
else if (!strcmp(tokens[0], "cd"))
Cd(num, tokens);
else if (!strcmp(tokens[0], "pwd"))
Pwd(num, tokens);
#if 0
else if (!strcmp(tokens[0], "mkdir"))
Mkdir(num, tokens);
else if (!strcmp(tokens[0], "rmdir"))
Rmdir(num, tokens);
#endif
else if (!strcmp(tokens[0], "exit"))
spinix_exit(0);
else
{
printf("Invalid command\n");
Help();
}
CloseRedirection();
}
spinix_exit(0);
}
/*
+--------------------------------------------------------------------
| TERMS OF USE: MIT License
+--------------------------------------------------------------------
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------
*/

37
filetest/mount.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/sd.h>
void mount(int MISO, int CLK, int MOSI, int CS)
{
#if 0
uint32_t mountErr;
_SD_Params params;
if (MISO == 10 && CLK == 11 && MOSI == 9 && CS == 25)
{
params.AttachmentType = _SDA_SerialDeMUX;
params.pins.SerialDeMUX.MISO = MISO;
params.pins.SerialDeMUX.CLK = CLK;
params.pins.SerialDeMUX.MOSI = MOSI;
params.pins.SerialDeMUX.CLR = CS;
params.pins.SerialDeMUX.INC = 8;
params.pins.SerialDeMUX.ADDR = 5;
}
else
{
params.AttachmentType = _SDA_SingleSPI;
params.pins.SingleSPI.MISO = MISO;
params.pins.SingleSPI.CLK = CLK;
params.pins.SingleSPI.MOSI = MOSI;
params.pins.SingleSPI.CS = CS;
}
if ((mountErr = dfs_mount(&params)))
{
printf("Mount error: %d\n", mountErr);
exit(1);
}
#endif
}

97
filetest/printf.c Normal file
View File

@ -0,0 +1,97 @@
#include <stdio.h>
#include <stdarg.h>
void printdec(FILE *fp, int val)
{
int scale;
int zeroflag = 0;
if (val < 0)
{
fputc('-', fp);
val = -val;
}
for (scale = 1000000000; scale > 1; scale /= 10)
{
if (val >= scale)
{
fputc('0' + val/scale, fp);
val %= scale;
zeroflag = 1;
}
else if (zeroflag)
fputc('0', fp);
else
fputc(' ', fp);
}
fputc('0'+val, fp);
}
void printhex(FILE *fp, int val)
{
int i;
static char hexdigits[] = "0123456789abcdef";
for (i = 0; i < 8; i++)
{
fputc(hexdigits[(val >> 28)&15], fp);
val <<= 4;
}
}
void _doprint(FILE *fp, const char *fmt, va_list args )
{
int val;
int state = 0;
while (*fmt)
{
val = *fmt++;
if (state)
{
if (val == 's')
{
state = 0;
val = va_arg(args, int);
fputs((char *)val, fp);
}
else if (val == 'd')
{
state = 0;
val = va_arg(args, int);
printdec(fp, val);
}
else if (val == 'x')
{
state = 0;
val = va_arg(args, int);
printhex(fp, val);
}
}
else
{
if (val == '%') state = 1;
else fputc(val, fp);
}
}
}
int printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
_doprint(stdout, fmt, args);
va_end(args);
return 0;
}
int fprintf(FILE *fp, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
_doprint(fp, fmt, args);
va_end(args);
return 0;
}

11
filetest/sd_internal.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _SD_INTERNAL_H
#define _SD_INTERNAL_H
#include "dosfs.h"
extern int dfs_mountflag;
extern VOLINFO dfs_volinfo;
extern char dfs_currdir[MAX_PATH];
extern __attribute__((section(".hub"))) uint8_t dfs_scratch[512];
#endif

45
filetest/spinix.c Normal file
View File

@ -0,0 +1,45 @@
#include <propeller.h>
#include "spinix.h"
static int run_prog[] = {
0xa0bc65f0, 0x08bc6e32, 0x80fc6404, 0x08bc7032, 0x80fc6404, 0x08bc6032,
0x80fc6404, 0x08bc6232, 0x80fc63ff, 0x28fc6209, 0x08fc6600, 0x00fc6804,
0x083c6029, 0x083c5c2a, 0x083c582b, 0x08bc642b, 0x863c642c, 0x5c68000f,
0x80fc6001, 0x80fc5d00, 0x80fc5d00, 0xe4fc620c, 0x087c6600, 0x007c6804,
0x04fc6a08, 0x04fc6c0a, 0xa0bc6236, 0x84bc6235, 0x28fc6202, 0x083c5a35,
0x80fc6a04, 0xe4fc621d, 0x083c5a36, 0x80fc6c04, 0x083c6e36, 0x80fc6c04,
0x083c7036, 0x0cfc6401, 0x60fc6407, 0x68bc5e32, 0x0c7c5e02, 0x00007fd8,
0x00007fdc, 0x00007fd4, 0x00000072, 0x00000000, 0x00000000, 0x0007c010};
static int arg_list[] = {0, 0, 0, 0};
void spinix_enter(int argc, char **argv)
{
}
void spinix_exit(int retval)
{
int i;
int cogspi = (*(int *)spinix_spi_engine_cog) - 1;
arg_list[2] = *(int *)spinix_shell_sector;
arg_list[3] = *(int *)spinix_shell_size;
*(int *)spinix_return_value = retval;
// Stop all the cogs except this one and the SD SPI cog
for (i = 0; i < 8; i++)
{
if (i != cogid() && i != cogspi)
cogstop(i);
}
// Clear and return all the locks
for (i = 0; i < 8; i++)
{
lockclr(i);
lockret(i);
}
// Start run_prog in this cog
coginit(cogid(), run_prog, arg_list);
}

45
filetest/spinix.h Normal file
View File

@ -0,0 +1,45 @@
#define spinix_start 0x7c00 // Extra space for the stand-alone loader
#define spinix_rendezvous 0x7e50
#define spinix_environ_vars 0x7e50
#define spinix_environ_vars_end 0x7ed3
#define spinix_argv_parms 0x7ed4
#define spinix_return_value 0x7f94
#define spinix_vga_cog 0x7f98
#define spinix_vga_handle 0x7f9c
#define spinix_sd_pins 0x7fa0
#define spinix_config 0x7fa4
#define spinix_shell_sector 0x7fa8
#define spinix_unixtime 0x7fac
#define spinix_cycle0 0x7fb0
#define spinix_timezone 0x7fb4
#define spinix_scriptline 0x7fb8
#define spinix_ifflag 0x7fbc
#define spinix_whileflag 0x7fc0
#define spinix_shell_size 0x7fc4
#define spinix_shell_level 0x7fc8
#define spinix_bootflag 0x7fcc
#define spinix_spi_engine_cog 0x7fd0
#define spinix_spi_command 0x7fd4
#define spinix_spi_block_index 0x7fd8
#define spinix_spi_buffer_address 0x7fdc
#define spinix_serial 0x7fe0
#define spinix_stdio 0x7fe4
#define spinix_stdin 0x7fe8
#define spinix_stdout 0x7fec
#define spinix_memlocknum 0x7ff0
#define spinix_memfreelist 0x7ff4
#define spinix_malloclist 0x7ff8
#define spinix_laststackaddr 0x7ffc
#define spinix_checkword 0xdead1eaf
#define spinix_proc_type_spin 1
#define spinix_proc_type_pasm 2
#define spinix_proc_type_capp 3
#define spinix_proc_type_driver 0x80
#define spinix_run_shell_wait 0x00
#define spinix_run_shell_nowait 0x08
#define spinix_run_kill_caller 0x10
#define spinix_run_at_address0 0x20
#define spinix_run_c_program 0x40
#define spinix_run_spin_program 0x80
#define spinix_run_stand_alone 0x100

193
filetest/varsubs.c Normal file
View File

@ -0,0 +1,193 @@
#include <stdio.h>
#include <string.h>
#include "spinix.h"
#include "varsubs.h"
static char retvalstr[16];
//******************************************************************************
// Copyright (c) 2013 Dave Hein
// See end of file for terms of use.
//******************************************************************************
char *varsubs_FindVar(char *str)
{
char *ptr = (char *)spinix_environ_vars;
while (*ptr)
{
if (!strcmp(str, ptr + 1))
{
if (*ptr != varsubs_ALIAS_FLAG)
{
return ptr;
}
}
ptr += strlen(ptr) + 1;
ptr += strlen(ptr) + 1;
}
return 0;
}
char *varsubs_FindAlias(char *str)
{
char *ptr = (char *)spinix_environ_vars;
while (*ptr)
{
if (!strcmp(str, ptr + 1))
{
if (*ptr == varsubs_ALIAS_FLAG)
{
return ptr;
}
}
ptr += strlen(ptr) + 1;
ptr += strlen(ptr) + 1;
}
return 0;
}
char *varsubs_FindEnd(void)
{
char *ptr = (char *)spinix_environ_vars;
while (*ptr)
{
ptr += strlen(ptr) + 1;
ptr += strlen(ptr) + 1;
}
return ptr;
}
char *varsubs_RemoveEntry(char *ptr1)
{
int i, len;
char *ptr2 = ptr1 + strlen(ptr1) + 1;
ptr2 += strlen(ptr2) + 1;
while (*ptr2)
{
for (i = 0; i < 2; i++)
{
len = strlen(ptr2) + 1;
memmove (ptr1, ptr2, len);
ptr1 += len;
ptr2 += len;
}
}
*ptr1 = 0;
return ptr1;
}
void varsubs_RemoveVar(char *name)
{
char *ptr;
if ((ptr = varsubs_FindVar(name)))
{
ptr = varsubs_RemoveEntry(ptr);
}
}
void varsubs_SaveVar(char *name, char *value, int type)
{
char *ptr;
int space, len1, len2;
// Check if variable already exists
if ((ptr = varsubs_FindVar(name)))
{
type = *ptr;
ptr = varsubs_RemoveEntry(ptr);
}
else
{
ptr = varsubs_FindEnd();
}
// Check if space is available
space = spinix_environ_vars_end - (int)ptr + 1;
len1 = strlen(name) + 1;
len2 = strlen(value) + 1;
if ((space < len1 + len2 + 2))
{
printf("Not enough variable space\n");
return;
}
else if ((space < len1 + len2 + 82))
{
printf("space = %d, need = %d\n", space, len1 + len2 + 2);
}
// Add variable
*ptr++ = type;
memmove (ptr, name, len1);
ptr += len1;
memmove (ptr, value, len2);
ptr += len2;
*ptr = 0;
}
char *varsubs_GetVarVal(char *name)
{
char *ptr;
if (!strcmp(name, "?"))
{
sprintf(retvalstr, "%d", *(int *)spinix_return_value);
return retvalstr;
}
if ((ptr = varsubs_FindVar(name)))
{
return ptr + strlen(ptr) + 1;
}
return "";
}
char *varsubs_Val(char *ptr)
{
if (*ptr != '$') return ptr;
return varsubs_GetVarVal(ptr + 1);
}
int varsubs_NumVal(char *ptr)
{
if (*ptr == '$')
{
if (!strcmp(ptr, "$?"))
{
return *(int *)spinix_return_value;
}
ptr = varsubs_GetVarVal(ptr + 1);
}
return atol(ptr);
}
#if 0
char *varsubs_FindChar(char *str, int val)
{
while (*str && *str != val) str++;
return str;
}
char *varsubs_SkipChar(char *str, int val)
{
while (*str && *str == val) str++;
return str;
}
#endif
/*
+-----------------------------------------------------------------------------+
| TERMS OF USE: MIT License |
+-----------------------------------------------------------------------------+
|Permission is hereby granted, free of charge, to any person obtaining a copy |
|of this software and associated documentation files (the "Software"), to deal|
|in the Software without restriction, including without limitation the rights |
|to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|copies of the Software, and to permit persons to whom the Software is |
|furnished to do so, subject to the following conditions: |
| |
|The above copyright notice and this permission notice shall be included in |
|all copies or substantial portions of the Software. |
| |
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,|
|OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE|
|SOFTWARE. |
+-----------------------------------------------------------------------------+
*/

17
filetest/varsubs.h Normal file
View File

@ -0,0 +1,17 @@
// CONSTANTS
#define varsubs_GLOBAL_FLAG 'G'
#define varsubs_LOCAL_FLAG 'L'
#define varsubs_PARM_FLAG 'P'
#define varsubs_ALIAS_FLAG 'A'
char *varsubs_FindVar(char *str);
char *varsubs_FindAlias(char *str);
char *varsubs_FindEnd(void);
char *varsubs_RemoveEntry(char *ptr1);
void varsubs_RemoveVar(char *name);
void varsubs_SaveVar(char *name, char *value, int type);
char *varsubs_GetVarVal(char *name);
char *varsubs_Val(char *ptr);
int varsubs_NumVal(char *ptr);
char *varsubs_FindChar(char *str, int val);
char *varsubs_SkipChar(char *str, int val);

315
lerner/cfloatstr.spin Normal file
View File

@ -0,0 +1,315 @@
'******************************************************************************
' Floating Point I/O Routines
' Author: Dave Hein
' Copyright (c) 2010
' See end of file for terms of use.
'******************************************************************************
'******************************************************************************
' Revison History
' v1.0 - 4/2/2010 First official release
'******************************************************************************
{
These routines are used by the C library to perform formatted floating point
I/O. The two output routines, putfloate and putfloatf write to string.
Input formatting is performed by the strtofloat routine. It uses a pointer
to a string pointer and returns the resulting floating point value.
If floating point I/O is not required for an application this file can be
removed by deleting the references to the object and the three routines in
clib.spin.
}
'******************************************************************************
' Floating Point Routines
'******************************************************************************
PUB putfloate(str, x, width, digits) | man, exp10, signbit
{{
Convert the floating point value in x to a string of characters in scientific
notation in str. digits determines the number of fractional digits used and
width determines the minimum length of the output string. Leading blanks are
added to achieve the minimum width.
}}
if (digits < 0)
digits := 6
signbit := tofloat10(x, @man, @exp10)
exp10 += round10(digits + 1, @man) + digits
width -= 5 + signbit - (digits <> 0)
repeat while (width-- > digits)
byte[str++] := " "
if (signbit)
byte[str++] := "-"
str := utoa10(man, str, 1)
byte[str++] := "e"
if (exp10 => 0)
byte[str++] := "+"
else
byte[str++] := "-"
exp10 := 0-exp10
if (exp10 < 10)
byte[str++] := "0"
str := utoa10(exp10, str, -1)
byte[str] := 0
return str
PUB putfloatf(str, x, width, digits) | lead0, trail0, man, exp10, signbit, digits0
{{
Convert the floating point value in x to a string of character in standard
notation in str. digits determines the number of fractional digits used and
width determines the minimum length of the output string. Leading blanks are
added to achieve the minimum width.
}}
if (digits < 0)
digits := 6
signbit := tofloat10(x, @man, @exp10)
digits0 := numdigits(man, @lead0) + exp10
if (digits0 > 0)
width -= digits0
digits0 += digits
if (digits0 > 8)
digits0 := 8
exp10 += round10(digits0, @man) + digits0 - 1
if (digits0 < 0)
digits0 := 0
elseif (digits0 == 0 and man == 1 and digits > 0)
digits0 := 1
lead0 := digits - digits0
trail0 := digits - digits0 + exp10 + 1
width -= signbit + digits - (lead0 => 0) + 1
repeat while (width-- > 0)
byte[str++] := " "
if (signbit)
byte[str++] := "-"
if (lead0 => 0)
byte[str++] := "0"
if (lead0 > 0)
byte[str++] := "."
repeat while (lead0-- > 0)
byte[str++] := "0"
if (digits0 > 0)
str := utoa10(man, str, exp10 + 1)
exp10 -= digits0 - 1
repeat while (trail0-- > 0)
if (exp10-- == 0)
byte[str++] := "."
byte[str++] := "0"
byte[str] := 0
return str
PUB strtofloat(pstr) | value, exp10, exp10a, signbit, mode, char, esignbit, str
{{
Convert the string of characters pointer to by "pstr" into a floating point
value. The input can be in either standard or scientific notation. Leading
blanks are ignored. The string pointed to by "pstr" is updated to the last
character postioned that caused processing to be completed.
}}
str := long[pstr]
esignbit := 0
mode := 0
value := 0
exp10 := 0
exp10a := 0
signbit := 0
repeat
char := byte[str++]
if (char == 0)
quit
case mode
0:
case char
"0".."9": value := char - "0"
"-" : signbit := 1
" " : next
"+": mode := 1
other:quit
mode := 1
1 :
case char
"0".."9":
if (value =< 200_000_000)
value := (value * 10) + char - "0"
else
exp10++
".": mode := 2
"e", "E": mode := 3
other: quit
2:
case char
"0".."9":
if (value =< 200_000_000)
value := (value * 10) + char - "0"
exp10--
"e", "E": mode := 3
other: quit
3:
case char
"0".."9": exp10a := char - "0"
"-" : esignbit := 1
"+": mode := 4
other:quit
mode := 4
4:
case char
"0".."9":exp10a := (exp10a * 10) + char - "0"
other: quit
if (esignbit)
exp10 -= exp10a
else
exp10 += exp10a
long[pstr] := str
return fromfloat10(value, exp10, signbit)
DAT
{{
________________________
These tables of scalers are used to scale a floating point number by a ratio of a
power of 10 versus a power of 2.
}}
''SCALE1 10/16 100/128 1000/1024 10^6/2^20 10^12/2^40 10^24/2^80
scale1 long 1342177280, 1677721600, 2097152000, 2048000000, 1953125000, 1776356839
''SCALE2 8/10 64/100 512/1000 2^19/10^6 2^39/10^12 2^79/10^24
scale2 long 1717986918, 1374389535, 1099511628, 1125899907, 1180591621, 1298074215
nbits1 byte 4, 7, 10, 20, 40, 80
nbits2 byte 3, 6, 9, 19, 39, 79
ndecs byte 1, 2, 3, 6, 12, 24
PRI floatloop(man, pexp0, pexp1, step0, step1, scale, pexp2, step2) | i
{{
This private routine reduces the value of exp0 toward 0 while increasing the value
of exp1. This is done in a successive approximation method using the scaling
table passed in "scale". This routine is used here to convert between a mantissa
times a power of 2 or 10 to a mantissa times a power of 10 or 2.
}}
repeat i from 5 to 0
if (long[pexp0] => byte[step0][i])
man := (man ** long[scale][i]) << 1
long[pexp0] -= byte[step0][i]
long[pexp1] += byte[step1][i]
if ((man & $40000000) == 0)
man <<= 1
long[pexp2] -= step2
return man
PRI tofloat10(value, pman, pexp10) | exp2, exp10, man
{{
This private routine converts from a mantissa times a power of 2 to a mantissa
times a power of 10.
}}
result := value >> 31
exp2 := ((value >> 23) & 255) - 157
man := ((value & $007fffff) | $00800000) << 7
exp10 := 0
if (exp2 =< 0)
exp2 := -exp2
man := floatloop(man, @exp2, @exp10, @nbits1, @ndecs, @scale1, @exp2, -1)
man >>= exp2
exp10 := -exp10
else
exp2 += 2
man := floatloop(man, @exp2, @exp10, @nbits2, @ndecs, @scale2, @exp2, 1)
man >>= 2 - exp2
long[pman] := man
long[pexp10] := exp10
PRI fromfloat10(man, exp10, signbit) | exp2
{{
This private routine converts from a mantissa times a power of 10 to a mantissa
times a power of two.
}}
if (man == 0)
return 0
exp2 := 0
repeat while(man & $40000000) == 0
man <<= 1
exp2--
if (exp10 =< 0)
exp10 := -exp10
exp2 := -exp2
man := floatloop(man, @exp10, @exp2, @ndecs, @nbits2, @scale2, @exp2, -1)
exp2 := -exp2
else
man := floatloop(man, @exp10, @exp2, @ndecs, @nbits1, @scale1, @exp2, 1)
repeat while(man & $ff000000)
man >>= 1
exp2++
return (signbit << 31) | ((exp2 + 150) << 23) | (man & $007fffff)
PRI numdigits(man, pdiv) : numdig | divisor
{{
This routine determines the number of decimal digits in the number in man.
}}
numdig := 10
divisor := 1000000000
repeat while (divisor > man)
numdig--
divisor /= 10
long[pdiv] := divisor
PRI round10(digits, pman) : exp10 | numdig, divisor, rounder, man
{{
This routine round the number poiinted to by pman to the number of decimal
digits specified by "digits".
}}
man := long[pman]
exp10 := numdigits(man, @divisor) - digits
if (digits < 0)
man := 0
elseif (digits == 0)
if (man / divisor => 5)
man := 1
exp10++
elseif (exp10 > 0)
rounder := 1
repeat exp10
rounder *= 10
man :=(man + (rounder >> 1)) / rounder
divisor /= rounder
if (man / divisor > 9)
man /= 10
exp10++
elseif (exp10 < 0)
repeat 0-exp10
man *= 10
long[pman] := man
PRI utoa10(number, str, point) | divisor, temp
{{
This routine converts the value in "number" to a string of decimal characters
in "str". A decimal point is added after the character position specified by
the value in "point".
}}
if (number == 0)
byte[str++] := "0"
byte[str] := 0
return str
divisor := 1_000_000_000
repeat while (divisor > number)
divisor /= 10
repeat while (divisor > 0)
if (point-- == 0)
byte[str++] := "."
temp := number / divisor
byte[str++] := temp + "0"
number -= temp * divisor
divisor /= 10
byte[str] := 0
return str
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

1015
lerner/clib.spin Normal file

File diff suppressed because it is too large Load Diff

208
lerner/cmalloc.spin Normal file
View File

@ -0,0 +1,208 @@
'******************************************************************************
' C malloc written in Spin
' Author: Dave Hein
' Copyright (c) 2010
' See end of file for terms of use.
'******************************************************************************
'******************************************************************************
' Revison History
' v1.0 - 4/2/2010 First official release
'******************************************************************************
{
This object contains the malloc, free and calloc routines used by clib.
}
OBJ
sys : "sysdefs"
CON
NEXT_BLK = 0
BLK_SIZE = 1
HDR_SIZE = 4
'RAM_SIZE = $8000
RAM_SIZE = sys#rendezvous
CHECKWORD = $dead1eaf
DAT
locknum long 0
memfreelist long 0
malloclist long 0
laststackaddr long 0
PUB CheckStackSpace | addr
repeat addr from laststackaddr to 0 step 4
if long[addr] <> CHECKWORD
quit
result++
PUB GetMallocList
return malloclist
PUB GetFreeList
return memfreelist
PUB mallocinit(stacksize) | currblk, addr
'' Initialize the malloc heap "stacksize" longs after the current stack pointer
'' Allocate a lock and return the lock number plus one if successful, or zero if not
locknum := locknew + 1
currblk := @stacksize + (stacksize << 2)
'Fill stack with checkword
laststackaddr := currblk - 4
longfill(@stacksize + 40, CHECKWORD, stacksize - 10)
memfreelist := currblk
malloclist := 0
word[currblk]{NEXT_BLK} := 0
word[currblk][BLK_SIZE] := RAM_SIZE - currblk
return locknum
PUB malloc(size) | prevblk, currblk, nextblk, prevblk0, currblk0, size0
'' Allocate a memory block of "size" bytes. Return a pointer to the clock if
'' successful, or zero if a large enough memory block could not be found
'ser.dbprintf1(string("malloc: %d\n"), size)
prevblk := 0
prevblk0 := 0
currblk0 := 0
if (size =< 0)
return 0
repeat until not lockset(locknum - 1)
currblk := memfreelist
' Adjust size to nearest long plus the header size
size := ((size + 3) & (!3)) + HDR_SIZE
' Search for a block of memory
repeat while (currblk)
if (word[currblk][BLK_SIZE] => size)
prevblk0 := prevblk
currblk0 := currblk
prevblk := currblk
currblk := word[currblk]{NEXT_BLK}
currblk := currblk0
prevblk := prevblk0
' Return null if block not found
if (currblk == 0)
lockclr(locknum - 1)
return 0
' Split block if larger than needed
size0 := word[currblk][BLK_SIZE] - size
if (size0 => HDR_SIZE + 4)
word[currblk][BLK_SIZE] := size0
currblk += size0
word[currblk][BLK_SIZE] := size
' Otherwise, use space without splitting and remove from memfreelist
else
nextblk := word[currblk]{NEXT_BLK}
if (prevblk)
word[prevblk]{NEXT_BLK} := nextblk
else
memfreelist := nextblk
' Add to the beginning of the malloc list
word[currblk]{NEXT_BLK} := malloclist
malloclist := currblk
lockclr(locknum - 1)
return currblk + HDR_SIZE
PUB freeraw(ptr, size)
repeat until not lockset(locknum - 1)
word[ptr][BLK_SIZE] := size
meminsert(ptr)
lockclr(locknum - 1)
return 1
PUB free(ptr) | prevblk, currblk, nextblk
'' Return the memory block at "ptr" to the free list. Return a value of one
'' if successful, or zero if the memory block was not on the allocate list.
prevblk := 0
repeat until not lockset(locknum - 1)
nextblk := malloclist
currblk := ptr - HDR_SIZE
' Search the malloclist for the currblk pointer
repeat while (nextblk)
if (currblk == nextblk)
' Remove from the malloc list
if (prevblk)
word[prevblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
else
malloclist := word[nextblk]{NEXT_BLK}
' Add to the free list
meminsert(nextblk)
lockclr(locknum - 1)
return 1
prevblk := nextblk
nextblk := word[nextblk]{NEXT_BLK}
' Return a NULL value if not found
lockclr(locknum - 1)
return 0
PRI meminsert(currblk) | prevblk, nextblk
'' Insert a memory block back into the free list. Merge blocks together if
'' the memory block is contiguous with other blocks on the list.
prevblk := 0
nextblk := memfreelist
' Find Insertion Point
repeat while (nextblk)
if ((currblk => prevblk) and (currblk =< nextblk))
quit
prevblk := nextblk
nextblk := word[nextblk]{NEXT_BLK}
' Merge with the previous block if contiguous
if (prevblk and (prevblk + word[prevblk][BLK_SIZE] == currblk))
word[prevblk][BLK_SIZE] += word[currblk][BLK_SIZE]
' Also merge with next block if contiguous
if (prevblk + word[prevblk][BLK_SIZE] == nextblk)
word[prevblk][BLK_SIZE] += word[nextblk][BLK_SIZE]
word[prevblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
' Merge with the next block if contiguous
elseif (nextblk and (currblk + word[currblk][BLK_SIZE] == nextblk))
word[currblk][BLK_SIZE] += word[nextblk][BLK_SIZE]
word[currblk]{NEXT_BLK} := word[nextblk]{NEXT_BLK}
if (prevblk)
word[prevblk]{NEXT_BLK} := currblk
else
memfreelist := currblk
' Insert in the middle of the free list if not contiguous
elseif (prevblk)
word[prevblk]{NEXT_BLK} := currblk
word[currblk]{NEXT_BLK} := nextblk
' Otherwise, insert at beginning of the free list
else
memfreelist := currblk
word[currblk]{NEXT_BLK} := nextblk
PUB calloc(size) | ptr
'' Allocate a memory block of "size" bytes and initialize to zero. Return
'' a pointer to the memory block if successful, or zero if a large enough
'' memory block could not be found.
ptr := malloc(size)
if (ptr)
longfill(ptr, 0, (size + 3) >> 2)
return ptr
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

584
lerner/cserial.spin Normal file
View File

@ -0,0 +1,584 @@
'******************************************************************************
' Serial Driver for the C Function Library in Spin
' Author: Dave Hein
' Copyright (c) 2010
' See end of file for terms of use.
'******************************************************************************
'******************************************************************************
' Revison History
' v1.0 - 4/2/2010 First official release
'******************************************************************************
{{
This is a modified version of Ghip Gracey's Full-Duplex Serial Driver. This
serial driver has the following new features:
- Multiple serial ports may be started from any object or cog
- Any serial port is accessable from any object or cog using a device handle
- Transmit and receiver buffers can be different sizes
- Buffer sizes are defined by calling parameters
- Mode bit 4 enables the use of a lock to make the transmit multi-cog safe
The original FullDuplexSerial routines are retained for compatibility. A
handle is maintained locally so that the caller does not have to provide the
buffers or handle for the first serial port.
The enhanced methods use a handle, which is a pointer to a memory buffer that
contains the serial port's state information and transmit and receive buffers.
The size of the memory buffer is equal to header_size + rxsize + txsize in
bytes. The buffer must be long aligned. The transmit and receive buffer
sizes must be a power of 2. They can range anywhere from a value of 2 up to
the size of the available memory.
}}
CON
' Data structure byte offsets
' long variables
tm_seconds = 0
tm_clkticks = 4
bit_ticks = 8
' word variables
rx_head = 12
rx_tail = 14
tx_head = 16
tx_tail = 18
rx_buffer = 20
tx_buffer = 22
rx_mask = 24
tx_mask = 26
' byte variables
cog = 28
lock = 29
rx_pin = 30
tx_pin = 31
rxtx_mode = 32
header_size = 36
' Data structure storage for the default serial port
DAT
handle1 long 0
data_struct long 0[(header_size+16+16)/4]
''
''*****************************************************************************
''Original FullDuplexSerial routines for compatibility
''*****************************************************************************
PUB rxflush
'' Flush receive buffer
rxflush1(handle1)
PUB rxcheck
'' Check if byte received (never waits)
'' returns -1 if no byte received, $00..$FF if byte
return rxcheck1(handle1)
PUB rxtime(ms)
'' Wait ms milliseconds for a byte to be received
'' returns -1 if no byte received, $00..$FF if byte
return rxtime1(handle1, ms)
PUB rx
'' Receive byte (may wait for byte)
'' returns $00..$FF
return rx1(handle1)
PUB tx(txbyte)
'' Send byte (may wait for room in buffer)
tx1(handle1, txbyte)
PUB str(stringptr)
'' Send string
str1(handle1, stringptr)
PUB dec(value)
'' Print a decimal number
dec1(handle1, value)
PUB hex(value, digits)
'' Print a hexadecimal number
hex1(handle1, value, digits)
PUB bin(value, digits)
'' Print a binary number
bin1(handle1, value, digits)
''
''*****************************************************************************
''Enhanced routines
''*****************************************************************************
PUB kbhit
return kbhit1(handle1)
PUB kbhit1(handle)
return word[handle+rx_tail] <> word[handle+rx_head]
PUB rxflush1(handle)
'' Flush receive buffer
word[handle+rx_tail] := word[handle+rx_head]
PUB rxcheck1(handle) : rxbyte | rx_tail1, rx_buffer1
'' Check if byte received (never waits)
'' returns -1 if no byte received, $00..$FF if byte
rxbyte--
rx_tail1 := word[handle+rx_tail]
if rx_tail1 <> word[handle+rx_head]
rx_buffer1 := word[handle+rx_buffer]
rxbyte := byte[rx_buffer1+rx_tail1]
word[handle+rx_tail] := (rx_tail1 + 1) & word[handle+rx_mask]
PUB rxtime1(handle, ms) : rxbyte | t
'' Wait ms milliseconds for a byte to be received
'' returns -1 if no byte received, $00..$FF if byte
t := cnt
repeat until (rxbyte := rxcheck1(handle)) => 0 or (cnt - t) / (clkfreq / 1000) > ms
PUB rx1(handle) : rxbyte
'' Receive byte (may wait for byte)
'' returns $00..$FF
repeat while (rxbyte := rxcheck1(handle)) < 0
PRI txchar(handle, txbyte) | tx_mask1, tx_buffer1, tx_head1, tx_head2
'' Send byte (may wait for room in buffer)
tx_mask1 := word[handle+tx_mask]
tx_buffer1 := word[handle+tx_buffer]
tx_head1 := word[handle+tx_head]
tx_head2 := (tx_head1 + 1) & tx_mask1
repeat until (word[handle+tx_tail] <> tx_head2)
{
if (byte[handle+rxtx_mode] & %100000) and (txbyte == 10)
txbyte := 13
}
byte[tx_buffer1+tx_head1] := txbyte
word[handle+tx_head] := tx_head2
if byte[handle+rxtx_mode] & %1000
rx1(handle)
PUB tx1(handle, txbyte) | uselock, locknum
'' Send byte - Use lock if mode bit 4 is set
uselock := byte[handle+rxtx_mode] & %10000
if (uselock)
locknum := byte[handle+lock] - 1
repeat until not lockset(locknum)
txchar(handle, txbyte)
if (uselock)
lockclr(locknum)
PUB str1(handle, stringptr) | uselock, locknum, value
'' Send string - Use lock if mode bit 4 is set
uselock := byte[handle+rxtx_mode] & %10000
if (uselock)
locknum := byte[handle+lock] - 1
repeat until not lockset(locknum)
repeat strsize(stringptr)
txchar(handle, byte[stringptr++])
if (uselock)
lockclr(locknum)
PUB dec1(handle, value) | i
'' Print a decimal number
if (value < 0)
tx1(handle, "-")
if (value == NEGX)
tx1(handle, "2")
value += 2_000_000_000
value := -value
i := 1_000_000_000
repeat while (i > value and i > 1)
i /= 10
repeat while (i > 0)
tx1(handle, value/i + "0")
value //= i
i /= 10
PUB hex1(handle, value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin1(handle, value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
tx((value <-= 1) & 1 + "0")
PUB gethandle1
'' Get the local handle
return handle1
PUB dbprintf0(fmtstr)
dbprintf(fmtstr, @fmtstr)
PUB dbprintf1(fmtstr, arg1)
dbprintf(fmtstr, @arg1)
PUB dbprintf2(fmtstr, arg1, arg2)
dbprintf(fmtstr, @arg1)
PUB dbprintf3(fmtstr, arg1, arg2, arg3)
dbprintf(fmtstr, @arg1)
PUB dbprintf4(fmtstr, arg1, arg2, arg3, arg4)
dbprintf(fmtstr, @arg1)
PUB dbprintf5(fmtstr, arg1, arg2, arg3, arg4, arg5)
dbprintf(fmtstr, @arg1)
PUB dbprintf6(fmtstr, arg1, arg2, arg3, arg4, arg5, arg6)
dbprintf(fmtstr, @arg1)
PUB dbprintf(fmtstr, arglist) | arg, val, digits
arg := long[arglist]
arglist += 4
repeat while (val := byte[fmtstr++])
if (val == "%")
digits := 0
repeat
case (val := byte[fmtstr++])
"d" : dec(arg)
"x" :
ifnot digits
digits := 8
hex(arg, digits)
"b" :
ifnot digits
digits := 32
bin(arg, digits)
"s" : str(arg)
"0".."9":
digits := (digits * 10) + val - "0"
next
0 : return
other: tx(val)
quit
arg := long[arglist]
arglist += 4
elseif (val == "\")
case (val := byte[fmtstr++])
"n" : tx(13)
"r" : tx(10)
0 : return
other: tx(val)
else
tx(val)
PUB settime(seconds, clkticks) | handle
handle := handle1
long[handle + tm_seconds] := seconds
long[handle + tm_clkticks] := clkticks | $80000000
repeat while long[handle + tm_clkticks] & $c0000000
PUB gettime(pclkticks) | handle
handle := handle1
long[handle + tm_clkticks] := $40000000
repeat while long[handle + tm_clkticks] & $c0000000
long[pclkticks] := long[handle + tm_clkticks]
return long[handle + tm_seconds]
''
''*****************************************************************************
''Original FullDuplexSerial routines for compatibility
''*****************************************************************************
PUB start(rxpin, txpin, mode, baudrate)
'' Start serial driver - starts a cog
'' returns false if no cog available
''
'' mode bit 0 = invert rx
'' mode bit 1 = invert tx
'' mode bit 2 = open-drain/source tx
'' mode bit 3 = ignore tx echo on rx
'' mode bit 4 = use lock
'' mode bit 5 = convert LF to CR on tx
return start1(@data_struct, rxpin, txpin, mode, baudrate, 256, 16)
''
''*****************************************************************************
''Enhanced routines
''*****************************************************************************
PUB start1(handle, rxpin, txpin, mode, baudrate, rxsize, txsize) : okay
'' Start serial driver - starts a cog
'' returns false if no cog available
''
'' mode bit 0 = invert rx
'' mode bit 1 = invert tx
'' mode bit 2 = open-drain/source tx
'' mode bit 3 = ignore tx echo on rx
'' mode bit 4 = use lock
'' mode bit 5 = convert LF to CR on tx
if (handle1)
if (handle1 == handle)
stop1(handle)
else
handle1 := handle
wordfill(handle+rx_head, 0, 4)
long[handle+tm_clkticks] := clkfreq + cnt
long[handle+tm_seconds] := 0
byte[handle+rx_pin] := rxpin
byte[handle+tx_pin] := txpin
byte[handle+rxtx_mode] := mode
long[handle+bit_ticks] := clkfreq / baudrate
word[handle+rx_buffer] := handle + header_size
word[handle+tx_buffer] := handle + header_size + rxsize
word[handle+rx_mask] := rxsize - 1
word[handle+tx_mask] := txsize - 1
if (mode & %10000)
okay := byte[handle+lock] := locknew + 1
if (okay == 0)
return 0
okay := byte[handle+cog] := cognew(@entry, handle) + 1
PUB stop1(handle) | cog1
'' Stop serial driver - frees a cog
cog1 := byte[handle+cog]
if cog1
cogstop(cog1 - 1)
longfill(handle, 0, header_size >> 2)
DAT
'***********************************
'* Assembly language serial driver *
'***********************************
org
'
'
' Entry
'
entry mov t1, par
add t1, #rx_pin
rdbyte t2,t1 'get rx_pin
mov rxbitmask,#1
shl rxbitmask,t2
add t1,#1 'get tx_pin
rdbyte t2,t1
mov txbitmask,#1
shl txbitmask,t2
add t1,#1 'get rxtx_mode
rdbyte rxtxmode,t1
mov t1, par
add t1, #bit_ticks 'get bit_ticks
rdlong bitticks,t1
mov t1, par
add t1, #tm_seconds 'get tmseconds
rdlong tmseconds,t1
mov t1, par
add t1, #tm_clkticks 'get tmclkticks
rdlong tmclkticks, #0 'get clkfreq
rdlong tmclkticks,t1
mov t1, par
add t1, #rx_buffer 'get rx_buffer ptr
rdword rxbuff,t1
add t1,#2 'get tx_buffer ptr
rdword txbuff,t1
add t1,#2 'get rx_mask
rdword rxmask,t1
add t1,#2 'get tx_mask
rdword txmask,t1
test rxtxmode,#%100 wz 'init tx pin according to mode
test rxtxmode,#%010 wc
if_z_ne_c or outa,txbitmask
if_z or dira,txbitmask
mov txcode,#transmit 'initialize multitasking addresses
mov clcode,#clock
'
'
' Receive
'
receive jmpret rxcode,txcode 'run a chunk of transmit code, then return
test rxtxmode,#%001 wz 'wait for start bit on rx pin
test rxbitmask,ina wc
if_z_eq_c jmp #receive
mov rxbits,#9 'ready to receive byte
mov rxcnt,bitticks
shr rxcnt,#1
add rxcnt,cnt
:bit add rxcnt,bitticks 'ready next bit period
:wait jmpret rxcode,txcode 'run a chuck of transmit code, then return
mov t1,rxcnt 'check if bit receive period done
sub t1,cnt
cmps t1,#0 wc
if_nc jmp #:wait
test rxbitmask,ina wc 'receive bit on rx pin
rcr rxdata,#1
djnz rxbits,#:bit
shr rxdata,#32-9 'justify and trim received byte
and rxdata,#$FF
test rxtxmode,#%001 wz 'if rx inverted, invert byte
if_nz xor rxdata,#$FF
mov t1, par
add t1, #rx_head
rdword t2, t1 'save received byte and inc head
add t2,rxbuff
wrbyte rxdata,t2
sub t2,rxbuff
add t2,#1
and t2,rxmask
wrword t2,t1
jmp #receive 'byte done, receive next byte
'
'
' Transmit
'
transmit jmpret txcode,clcode 'run a chunk of clock code, then return
mov t1,par 'check for head <> tail
add t1,#tx_head
rdword t2,t1
add t1,#2
rdword t3,t1
cmp t2,t3 wz
if_z jmp #transmit
add t3,txbuff 'get byte and inc tail
rdbyte txdata,t3
sub t3,txbuff
add t3,#1
and t3,txmask
wrword t3,t1
or txdata,#$100 'ready byte to transmit
shl txdata,#2
or txdata,#1
mov txbits,#11
mov txcnt,cnt
:bit test rxtxmode,#%100 wz 'output bit on tx pin according to mode
test rxtxmode,#%010 wc
if_z_and_c xor txdata,#1
shr txdata,#1 wc
if_z muxc outa,txbitmask
if_nz muxnc dira,txbitmask
add txcnt,bitticks 'ready next cnt
:wait jmpret txcode,clcode 'run a chunk of clock code, then return
mov t1,txcnt 'check if bit transmit period done
sub t1,cnt
cmps t1,#0 wc
if_nc jmp #:wait
djnz txbits,#:bit 'another bit to transmit?
jmp #transmit 'byte done, transmit next byte
clock jmpret clcode,rxcode 'run the receive task
mov t2, par
add t2, #tm_clkticks
rdlong t1, t2
shl t1, #1 wc
if_c jmp #setclock
shl t1, #1 wc
if_c jmp #getclock
mov t1, cnt
sub t1, tmclkticks
shl t1, #1 wc
if_c jmp #clock
add tmseconds, #1
rdlong t1, #0
add tmclkticks, t1
jmp #clock
setclock shl t1, #3
shr t1, #4
rdlong tmclkticks, #0
add tmclkticks, cnt
sub tmclkticks, t1
mov t2, par
add t2, #tm_seconds
rdlong tmseconds, t2
mov t2, par
add t2, #tm_clkticks
wrlong t1, t2
jmp #clock
getclock rdlong t1, #0
mov t2, cnt
add t2, t1
sub t2, tmclkticks
mov t3, par
add t3, #tm_seconds
wrlong tmseconds, t3
mov t3, par
add t3, #tm_clkticks
wrlong t2, t3
jmp #clock
'
'
' Uninitialized data
'
t1 res 1
t2 res 1
t3 res 1
rxtxmode res 1
bitticks res 1
rxbitmask res 1
rxbuff res 1
rxdata res 1
rxbits res 1
rxcnt res 1
rxcode res 1
rxmask res 1
txbitmask res 1
txbuff res 1
txdata res 1
txbits res 1
txcnt res 1
txcode res 1
txmask res 1
tmclkticks res 1
tmseconds res 1
clcode res 1
fit $100
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

34
lerner/exit.spin Normal file
View File

@ -0,0 +1,34 @@
obj
sys : "sysdefs"
dat
run_prog
long $a0bc65f0, $08bc6e32, $80fc6404, $08bc7032, $80fc6404, $08bc6032
long $80fc6404, $08bc6232, $80fc63ff, $28fc6209, $08fc6600, $00fc6804
long $083c6029, $083c5c2a, $083c582b, $08bc642b, $863c642c, $5c68000f
long $80fc6001, $80fc5d00, $80fc5d00, $e4fc620c, $087c6600, $007c6804
long $04fc6a08, $04fc6c0a, $a0bc6236, $84bc6235, $28fc6202, $083c5a35
long $80fc6a04, $e4fc621d, $083c5a36, $80fc6c04, $083c6e36, $80fc6c04
long $083c7036, $0cfc6401, $60fc6407, $68bc5e32, $0c7c5e02, $00007fd8
long $00007fdc, $00007fd4, $00000072, $00000000, $00000000, $0007c010
arg_list long 0[4]
pub exit(retval) | i, cogspi
cogspi := long[sys#SPI_engine_cog] - 1
arg_list[2] := long[sys#shell_sector]
arg_list[3] := long[sys#shell_size]
long[sys#return_value] := retval
' Stop all the cogs except this one and the SD SPI cog
repeat i from 0 to 7
if (i <> cogid and i <> cogspi)
cogstop(i)
' Clear and return all the locks
repeat i from 0 to 7
lockclr(i)
lockret(i)
' Start run_prog in this cog
coginit(cogid, @run_prog, @arg_list)

1541
lerner/lerner.spin Normal file

File diff suppressed because it is too large Load Diff

112
lerner/sysdefs.spin Normal file
View File

@ -0,0 +1,112 @@
'******************************************************************************
' Copyright (c) 2011, 2012, Dave Hein
' See end of file for terms of use.
'******************************************************************************
CON
'start = $7e50 ' Extra space for the stand-alone loader
start = $7c00 ' Extra space for the stand-alone loader
' SD CLIB data
rendezvous = $7e50
' Exported variables
environ_vars = $7e50
environ_vars_end = $7ed3
' Argv parameter area
argv_parms = $7ed4
' Additional system parameters
return_value = $7f94
vga_cog = $7f98
vga_handle = $7f9c
sd_pins = $7fa0
config = $7fa4
shell_sector = $7fa8
' System time
unixtime = $7fac
cycle0 = $7fb0
timezone = $7fb4
{
' I2C Driver
i2c_cog = $7fb8
i2c_cmd = $7fbc
i2c_parm = $7fc0
' Kernel data
filelock = $7fc4
filecmd = $7fc8
fileparm = $7fcc
}
'Shell variables
scriptline = $7fb8
ifflag = $7fbc
whileflag = $7fc0
shell_size = $7fc4
shell_level = $7fc8
bootflag = $7fcc
'File I/O
spi_engine_cog = $7fd0
spi_command = $7fd4
spi_block_index = $7fd8
spi_buffer_address = $7fdc
' Basic CLIB data
' Serial data
serial = $7fe0
stdio = $7fe4
stdin = $7fe8
stdout = $7fec
' Malloc data
memlocknum = $7ff0
memfreelist = $7ff4
malloclist = $7ff8
laststackaddr = $7ffc
' Stack check word
checkword = $dead1eaf
' Process types
proc_type_spin = 1
proc_type_pasm = 2
proc_type_capp = 3
proc_type_driver = $80
' Run modes
run_shell_wait = $00
run_shell_nowait = $08
run_kill_caller = $10
run_at_address0 = $20
run_c_program = $40
run_spin_program = $80
run_stand_alone = $100
PUB main
return
{{
+-----------------------------------------------------------------------------+
| TERMS OF USE: MIT License |
+-----------------------------------------------------------------------------+
|Permission is hereby granted, free of charge, to any person obtaining a copy |
|of this software and associated documentation files (the "Software"), to deal|
|in the Software without restriction, including without limitation the rights |
|to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|copies of the Software, and to permit persons to whom the Software is |
|furnished to do so, subject to the following conditions: |
| |
|The above copyright notice and this permission notice shall be included in |
|all copies or substantial portions of the Software. |
| |
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,|
|OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE|
|SOFTWARE. |
+-----------------------------------------------------------------------------+
}}

26
license.txt Normal file
View File

@ -0,0 +1,26 @@
+-----------------------------------------------------------------------------+
|The spinix software is distributed under the terms of the MIT license as |
|shown below. |
| |
|Copyright (c) 2011, 2012, 2013, Dave Hein |
+-----------------------------------------------------------------------------+
| TERMS OF USE: MIT License |
+-----------------------------------------------------------------------------+
|Permission is hereby granted, free of charge, to any person obtaining a copy |
|of this software and associated documentation files (the "Software"), to deal|
|in the Software without restriction, including without limitation the rights |
|to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|copies of the Software, and to permit persons to whom the Software is |
|furnished to do so, subject to the following conditions: |
| |
|The above copyright notice and this permission notice shall be included in |
|all copies or substantial portions of the Software. |
| |
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,|
|OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE|
|SOFTWARE. |
+-----------------------------------------------------------------------------+

24
manpages/alias.txt Normal file
View File

@ -0,0 +1,24 @@
ALIAS(1) User Commands ALIAS(1)
NAME
alias - create an alias
SYNOPSIS
alias [name=value]
DESCRIPTION
The alias command will create an alias symbol that will be used
generate a shell command. If not parameters are specified the list
of aliases will be printed.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013 Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility October 2013 ALIAS(1)

34
manpages/boot.txt Normal file
View File

@ -0,0 +1,34 @@
BOOT(1) Spinix OS BOOT(1)
NAME
boot - spinix boot program
DESCRIPTION
The spinix boot program resides in the Propeller boot EEPROM. When run
for the first time, the boot program prompts the user for the I/O pins
used to interface to the SD card. The pin values are stored back into
EEPROM so that the user does not need to specify them in subsequent
start ups.
The boot program starts up the serial and SD drivers. The serial and
SD drivers and the kernel each run in their own cog.
The boot program reads the file _shell.var, and set the SHELL
environment variable to the contents of this file. It then verifies
that the shell program exists, and starts the shell.
SEE ALSO
For more information see the man pages for spinix and shell.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013 Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX OS September 2013 BOOT(1)

25
manpages/cat.txt Normal file
View File

@ -0,0 +1,25 @@
CAT(1) User Commands CAT(1)
NAME
cat - concatenate files and print on the standard output
SYNOPSIS
cat [FILE]...
DESCRIPTION
Concatenate FILE(s), or standard input to the standard output. When no
files are specified the standard input is used. Input from the standard
input is terminated by typing a ^D.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 CAT(1)

24
manpages/cd.txt Normal file
View File

@ -0,0 +1,24 @@
CD(1) User Commands CD(1)
NAME
cd - change the working directory
SYNOPSIS
cd [directory]
DESCRIPTION
The cd utility changes the working directory in the current shell if
the directory path exists. Otherwise, the current working directory
will remain the same.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 CD(1)

24
manpages/chmod.txt Normal file
View File

@ -0,0 +1,24 @@
CHMOD(1) User Commands CHMOD(1)
NAME
chmod - change file mode bits
SYNOPSIS
chmod [MODE] [FILE]
DESCRIPTION
Changes the mode bits of a FILE based on the MODE string. MODE is
either an octal number or contains the characters +-drwx. If an octal
number is specified, the bits map to the drwx field.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 CHMOD(1)

49
manpages/config.txt Normal file
View File

@ -0,0 +1,49 @@
CONFIG(1) User Commands CONFIG(1)
NAME
config - configure the system
SYNOPSIS
config [PARM]
DESCRIPTION
The config utility is used to control how information is displayed on
the console terminal. The config utility writes the value of PARM to
the config location in Spinix. PARM is expressed as a hexadecimal
number.
The config value indicates the number of display lines, the terminal
type and whether a newline sends the line-feed and carriage-return
characters to the console. The format of PARM is "NNTL", where "NN" is
a 2-digit hex number indicating the number of display lines, "T" is a
single hex digit with a value of 0, 1 or 2 for TTY, PST or ANSI
terminal mode. "L" is a single hex digit with the following values:
0 - Do not send any characters
1 - Send a LF character
2 - Send a CR character
3 - Send a CR character followed by a LF
The "linefeed" command may also be used to enable/disable whether a
line-feed character is sent by a newline.
EXAMPLES
The following shows various examples of terminal configurations:
config 2 - TTY terminal with no line specification
config 12 - PST terminal with no line specification
config 23 - ANSI terminal with no line specification
config 1823 - 24-line ANSI terminal with CR and LF
config 2812 - 40-line PST terminal with CR
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 CONFIG(1)

22
manpages/cp.txt Normal file
View File

@ -0,0 +1,22 @@
CP(1) User Commands CP(1)
NAME
cp - copy files
SYNOPSIS
cp [FILE1] [FILE2]
DESCRIPTION
Copy FILE1 to FILE2
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 CP(1)

30
manpages/date.txt Normal file
View File

@ -0,0 +1,30 @@
DATE(1) User Commands DATE(1)
NAME
date - display or set the system date and time
SYNOPSIS
date [-s [yyyy/mm/dd] [hh:mm[:ss]]]
DESCRIPTION
If no parameters are specified the date and time will be displayed
in the yyyy/mm/dd hh:mm:ss format. If the -s option is specified
without any additional parameters the unix epoch time will be printed,
which is the number of seconds since the beginning of 1970.
If the -s option is specified with additional parameters the date
and/or time can be set by specifying either the date, time or both.
The date and time can be specified in either order, and the seconds
parameter is optional when specifying the time.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility September 2013 DATE(1)

31
manpages/declare.txt Normal file
View File

@ -0,0 +1,31 @@
DECLARE(1) User Commands DECLARE(1)
NAME
declare - declare one or more environment variables
SYNOPSIS
declare [-p] [-x] [name[=[value]]...]
DESCRIPTION
If no parameters are specified, export will print all of the
environment variables. If only the -p option is provided the variables
will be printed preceed by "declare -F ", where F will be x for
exported variables, and - for non-exported variables. If -x is
specified only the exported variables will be printed.
If one or more names is provided the variables will be declared. If
the name is followed by the "=" character the following value will be
assigned to the variable. If the -x option is specified before the
list of names the variables will be exported.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2013 DECLARE(1)

36
manpages/diag.txt Normal file
View File

@ -0,0 +1,36 @@
DIAG(1) User Commands DIAG(1)
NAME
diag - perform diagnostics
SYNOPSIS
diag
DESCRIPTION
diag implements the following commands:
help - Print commands
exit - Exit diag
stack - Print the amount of unused stack space
malloc - Print the malloc and free lists
peek address - Print value at address in EEPROM
poke address num - Write value at address in EEPROM
dump address num - Print num values statring at address in EEPROM
peekm address - Print value at address in memory
pokem address num - Write value at address in memory
dumpm address num - Print num values statring at address in memory
filename - Execute an application file
LIMITATIONS
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility November 2013 DIAG(1)

11
manpages/diaghelp.txt Normal file
View File

@ -0,0 +1,11 @@
help - Print commands
exit - Exit diag
stack - Print the amount of unused stack space
malloc - Print the malloc and free lists
peek address - Print value at address in EEPROM
poke address num - Write value at address in EEPROM
dump address num - Print num values statring at address in EEPROM
peekm address - Print value at address in memory
pokem address num - Write value at address in memory
dumpm address num - Print num values statring at address in memory
filename - Execute an application file

23
manpages/diff.txt Normal file
View File

@ -0,0 +1,23 @@
DIFF(1) User Commands DIFF(1)
NAME
diff - compare files line by line
SYNOPSIS
diff [FILE1] [FILE2]
DESCRIPTION
Compares FILE1 with FILE2 line by line, and prints the differences to
the standard output.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 DIFF(1)

26
manpages/dos2unix.txt Normal file
View File

@ -0,0 +1,26 @@
DOS2UNIX(1) User Commands DOS2UNIX(1)
NAME
dos2unix - convert from from dos to unix format
SYNOPSIS
dos2unix [FILE]
DESCRIPTION
The dos2unix utility converts a text file from the DOS format to the
Unix format. A line in a DOS text file is terminated by the carriage-
return and line-feed characters. A Unix file is terminated only by
the line-feed character.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 DOS2UNIX(1)

22
manpages/echo.txt Normal file
View File

@ -0,0 +1,22 @@
ECHO(1) User Commands ECHO(1)
NAME
echo - display a line of text
SYNOPSIS
echo [STRING]...
DESCRIPTION
Echo the STRING(s) to standard output.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 ECHO(1)

313
manpages/ed.txt Normal file
View File

@ -0,0 +1,313 @@
ED(1) User Commands ED(1)
NAME
ed - text editor
SYNOPSIS
ed [file]
DESCRIPTION
ed is a line-oriented text editor. It is used to create, display,
modify and otherwise manipulate text files. This version of ed
implements most of the commands in the standard ed utility. It does
not allow wildcard or escape characters in the search or replacement
strings, and it cannot execute shell commands. It also does not
implement the undo command, and it only allows one command per line.
There are two non-standard commands supported that provide assistance
in using ed. The 'h' command will print help information that
summarizes the commands available in ed. A 'V' command was added to
provide an enhanced visualization mode, which prints the text around the
current line after executing a command.
If invoked with a file argument, a copy of file is read into the
editor's buffer. Changes are made to this copy and not directly to file
itself. Upon quitting ed, any changes not explicitly saved with a 'w'
command are lost.
Editing is done in two distinct modes: command and input. When first
invoked, ed is in command mode. In this mode commands are read from the
standard input and executed to manipulate the contents of the editor
buffer. A typical command might look like:
,s/old/new/g
which replaces all occurrences of the string old with new.
When an input command, such as 'a' (append), 'i' (insert) or 'c'
(change), is given, ed enters input mode. This is the primary means of
adding text to a file. In this mode, no commands are available;
instead, the standard input is written directly to the editor buffer.
Lines consist of text up to and including a newline character. Input
mode is terminated by entering a single period (.) on a line.
All ed commands operate on whole lines or ranges of lines; e.g., the 'd'
command deletes lines; the 'm' command moves lines, and so on. It is
possible to modify only a portion of a line by means of replacement, as
in the example above. However even here, the 's' command is applied to
whole lines at a time.
In general, ed commands consist of zero or more line addresses, followed
by a single character command and possibly additional parameters; i.e.,
commands have the structure:
[address [,address]]command[parameters]
The address(es) indicate the line or range of lines to be affected by
the command. If fewer addresses are given than the command accepts,
then default addresses are supplied.
OPTIONS
file Specifies the name of a file to read. The default filename is
set to the specified file.
LINE ADDRESSING
An address represents the number of a line in the buffer. ed maintains
a current address which is typically supplied to commands as the default
address when none is specified. When a file is first read, the
current address is set to the last line of the file. In general, the
current address is set to the last line affected by a command.
A line address is constructed from one of the bases in the list below,
optionally followed by a numeric offset. The offset may include any
combination of digits, operators (i.e. + and -). Addresses are read
from left to right, and their values are computed relative to the
current address.
One exception to the rule that addresses represent line numbers is the
address 0 (zero). This means "before the first line," and is legal
wherever it makes sense.
An address range is two addresses separated either by a comma or
semicolon. The value of the first address in a range cannot exceed the
value of the second. If only one address is given in a range, then the
second address is set to the given address. If only one address is
expected, then the last address is used.
Each address in a comma-delimited range is interpreted relative to the
current address. In a semicolon-delimited range, the first address is
used to set the current address, and the second address is
interpreted relative to the first.
The following address symbols are recognized.
. The current line (address) in the buffer.
$ The last line in the buffer.
n The nth, line in the buffer where n is a number in the range
[0,$].
- The previous line. This is equivalent to -1.
-n The nth previous line, where n is a non-negative number.
+ The next line. This is equivalent to +1.
+n The nth next line, where n is a non-negative number.
, The first through last lines in the buffer. This is equivalent
to the address range 1,$.
; The current through last lines in the buffer. This is
equivalent to the address range .,$.
/re/ The next line containing the regular expression re. The search
wraps to the beginning of the buffer and continues down to the
current line, if necessary. // repeats the last search.
?re? The previous line containing the regular expression re. The
search wraps to the end of the buffer and continues up to the
current line, if necessary. ?? repeats the last search.
REGULAR EXPRESSIONS
Regular expressions are patterns used in selecting text. For example,
the ed command
g/string/
prints all lines containing string. Regular expressions are also used
by the 's' command for selecting old text to be replaced with new. This
version of ed does not use any wildcard or escape characters.
COMMANDS
All ed commands are single characters, though some require additional
parameters. ed commands must fit in a single line, and cannot be
continued to another line.
In general, only one command is allowed per line. The only exceptions
are the 'g' and 'v' commands, which can be followed by an 's', 'p', 'l'
or 'n' command.
ed recognizes the following commands. The commands are shown together
with the default address or address range supplied if none is specified
(in parenthesis).
(.)a Appends text to the buffer after the addressed line, which may
be the address 0 (zero). Text is entered in input mode. The
current address is set to last line entered.
(.,.)c Changes lines in the buffer. The addressed lines are deleted
from the buffer, and text is appended in their place. Text is
entered in input mode. The current address is set to last line
entered.
(.,.)d Deletes the addressed lines from the buffer. If there is a line
after the deleted range, then the current address is set to this
line. Otherwise the current address is set to the line before
the deleted range.
e file Edits file, and sets the default filename. If file is not
specified, then the default filename is used. Any lines in the
buffer are deleted before the new file is read. The current
address is set to the last line read.
E file Edits file unconditionally. This is similar to the e command,
except that unwritten changes are discarded without warning.
The current address is set to the last line read.
f file Sets the default filename to file. If file is not specified,
then the default filename is printed.
(1,$)g/re/command
Applies command to each of the addressed lines matching a
regular expression re. The current address is set to the line
currently matched before command is executed. At the end of the
'g' command, the current address is set to the last line
affected by command. The allowable commands are 's', 'p', 'l'
and 'n'. The 'p' command is used if command is not specified.
h Print help information, which summarizes the commands available.
Note that this is different than the standard usage for 'h',
which prints an explanation of the last error.
(.)i Inserts text in the buffer before the current line. Text is
entered in input mode. The current address is set to the last
line entered.
(.,.+1)j
Joins the addressed lines. The addressed lines are deleted from
the buffer and replaced by a single line containing their joined
text. The current address is set to the resultant line.
(.,.)l Prints the addressed lines unambiguously. The current address
is set to the last line printed.
(.,.)m(.)
Moves lines in the buffer. The addressed lines are moved to
after the right-hand destination address, which may be the
address 0 (zero). The current address is set to the new address
of the last line moved.
(.,.)n Prints the addressed lines along with their line numbers. The
current address is set to the last line printed.
(.,.)p Prints the addressed lines. The current address is set to the
last line printed.
P Toggles the command prompt on and off. The command prompt is by
default turned off.
q Quits ed.
Q Quits ed unconditionally. This is similar to the q command,
except that unwritten changes are discarded without warning.
($)r file
Reads file to after the addressed line. If file is not
specified, then the default filename is used. If there was no
default filename prior to the command, then the default filename
is set to file. Otherwise, the default filename is unchanged.
The current address is set to the last line read.
(.,.)s/re/replacement/
(.,.)s/re/replacement/g
Replaces text in the addressed lines matching a regular
expression re with replacement. By default, only the first
match in each line is replaced. If the 'g' (global) suffix is
given, then every match to be replaced. It is an error if no
substitutions are performed on any of the addressed lines. The
current address is set to the last line affected.
(.,.)t(.)
Copies (i.e., transfers) the addressed lines to after the right-
hand destination address, which may be the address 0 (zero).
The current address is set to the last line copied.
(1,$)v/re/command-list
Applies command-list to each of the addressed lines not matching
a regular expression re. This is similar to the 'g' command.
Vn If n is specified, the visualization mode is enabled and the
number of lines printed is set to n. Otherwise, the
visualization mode it toggled on or off. The visualization mode
is a non-standard feature that prints the text in the edit
buffer before and after the current line.
(1,$)w file
Writes the addressed lines to file. Any previous contents of
file is lost without warning. If there is no default filename,
then the default filename is set to file, otherwise it is
unchanged. If no filename is specified, then the default
filename is used. The current address is unchanged.
(.)x Copies (puts) the contents of the cut buffer to after the
addressed line. The current address is set to the last line
copied.
(.,.)y Copies (yanks) the addressed lines to the cut buffer. The cut
buffer is overwritten by subsequent 'y', 'j', 'd', or 'c'
commands. The current address is unchanged.
(.+1)zn Scrolls n lines at a time starting at addressed line. If n is
not specified, then the current window size is used. The
current address is set to the last line printed.
($)= Prints the line number of the addressed line.
(.+1)newline
Prints the addressed line, and sets the current address to that
line.
SEE ALSO
B. W. Kernighan and P. J. Plauger, Software Tools in Pascal , Addison-
Wesley, 1981.
LIMITATIONS
ed is limited to 200 characters per line. If an input line is greater
than 200 characters it will be broken up into multiple lines. The input
file must terminate lines with a newline (LF) character. Files will be
written using the UNIX LF line termination. The size of the file is
limited by the amount of buffer memory available to ed. If ed
encounters an error in a command line it will print '?' and return to
command mode. Attempting to quit ed or edit another file before writing
a modified buffer results in an error. If the command is entered a
second time, it succeeds, but any changes to the buffer are lost.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 ED(1)

44
manpages/edhelp.txt Normal file
View File

@ -0,0 +1,44 @@
ED Commands
Line Addresses
n - nth line
. - current line
$ - last line
- - previous line
-n - nth previous line
+ - next line
+n - nth next line
n,m - lines n through m
, - first through last lines
; - current through last lines
/str/ - next line containing str
?str? - previous line containing str
Editing Commands
(.)a - append text after the addressed line
(.,.)c - replace the addressed lines with text
(.,.)d - delete the addressed lines
e file - discard all lines and edit the specified file
E file - unconditionally discard all lines and edit specified file
f file - set the current file name and print the name
(1,$)g/str/cmd - execute a command on lines containing str
h - print help information
(.)i - insert text before the addressed line
(.,.+1)j - join the addressed lines
(.,.)l - print the addressed lines unambiguously
(.,.)m(.) - move the addressed lines to after the right-hand address
(.,.)n - print the addresses lines with line numbers
(.,.)p - print the addresses lines
P - toggle the prompt mode
q - quit
($)r file - read the specified file after the addressed line
(.,.)s/st1/st2/g - substitute occurances of st1 with st2
(.,.)t(.) - copy the addressed lines to after the right-hand address
(1,$)v/str/cmd - execute a command on lines not containing str
Vn - set visualization mode to n lines or toggle on/off if no n
(1,$)w file - write the addressed lines to the specified file
(.)x - insert lines from the cut buffer after the addressed line
(.,.)y - yank the addressed lines to the cut buffer
(.+1)zn - scroll and print n lines from the addressed line
($)= - print the line number of the addressed line
(.+1) - print the addressed line

29
manpages/export.txt Normal file
View File

@ -0,0 +1,29 @@
EXPORT(1) User Commands EXPORT(1)
NAME
export - export one or more environment variables
SYNOPSIS
export [name[=[value]]...]
DESCRIPTION
If no parameters are specified, export will print all of the exported
environment variables. If one or more varible are supplied they will
become exported variables. If the variable had been previously
declared as a non-exported variable it will be exported with its
current value unless the "=" character is included. If a value is
specified after the "=" character it will become the new value of the
variable. If no value follows the "=" character the variable will be
assigned a NULL value.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2013 EXPORT(1)

22
manpages/getmod.txt Normal file
View File

@ -0,0 +1,22 @@
GETMOD(1) User Commands GETMOD(1)
NAME
getmod - print the mode of a file
SYNOPSIS
getmode [FILE]
DESCRIPTION
Print the mode of FILE.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 GETMOD(1)

23
manpages/halt.txt Normal file
View File

@ -0,0 +1,23 @@
HALT(1) User Commands HALT(1)
NAME
halt - halt the system
SYNOPSIS
halt
DESCRIPTION
All of the precesses are stopped, and the processor is put in an idle
state.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 HALT(1)

26
manpages/head.txt Normal file
View File

@ -0,0 +1,26 @@
HEAD(1) User Commands HEAD(1)
NAME
head - print the beginning lines of a file
SYNOPSIS
head [OPTION] [FILE]
DESCRIPTION
The first 10 lines of FILE are printed to the standard output if OPTION
is not present. A different number of lines can be specified with a
"-n" OPTION, where n is the postivie number. The standard input is used
if FILE is not specified. In the case of the standard input, head will
terminate after reading "n" lines.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 HEAD(1)

25
manpages/history.txt Normal file
View File

@ -0,0 +1,25 @@
HISTORY(1) User Commands HISTORY(1)
NAME
history - print the shell command history
SYNOPSIS
history [-c] [n]
DESCRIPTION
If no parameters are specified, the history file containing the
previous shell commands will be printed out. If a number is specified
only the last "n" lines will be printed. If the -c option is specified
the history file will be deleted.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013 Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility October 2013 HISTORY(1)

53
manpages/lerner.txt Normal file
View File

@ -0,0 +1,53 @@
LERNER(1) User Commands LERNER(1)
NAME
lerner - conversational program that learns
SYNOPSIS
lerner
DESCRIPTION
Lerner is a stand-alone conversational program that can learn by
building a vocabulary. It supports a simple grammatical syntax
containing a subject, verb and predicate. The predicate can contain
an optional adjective. The syntax is as follows:
[article] subject verb [article] [adjective] predicate
Each field must consist of a single word. The articles, "a", "an" and
"the" are optional. Statements can be made questions by adding a "?"
at the end. Questions can also start with the words "who", "what",
"does", "do", "is" and "are". The question mark is optional when
starting a question with these words.
Words must be spelled with the same capitalization as they were
defined. One exception is at the beginning of a sentence where the
first letter can be capitalized even if the word was defined in
lower-case.
Lerner supports the following commands:
vocab [word] - Print the words I know
dump - Print the words as hex codes
forget - Remove a word from memory
save - Save the words to EEPROM
reset - Reset the word table
basic - Reset the word table to a basic list
history - Print the short term memory
goodbye - Exit the program
help - Print this list of commands
Lerner normally saves its vocabulary to the EEPROM. However, the save
function has been disabled in this version.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX Program March 2012 LERNER(1)

42
manpages/let.txt Normal file
View File

@ -0,0 +1,42 @@
LET(1) User Commands LET(1)
NAME
let - print a manual entry
SYNOPSIS
let name=val1[op1val2...]
DESCRIPTION
Sets the value of the named shell variable to the value of an
arithmetic expression. The arithmetic expression is evaluated from
left to right. The allowable operators are as follows:
>= - Greater than or equal
<= - Less than or equal
== - Equal
!= - Not equal
&& - Logical and
|| - Logical or
>> - Arithmetic shift right
<< - Shift left
+ - Add
- - Subtract
* - Multiply
/ - Divide
& - Bitwise and
| - Bitwise or
< - Less than
> - Greater than
% - Modulus
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2013 LET(1)

26
manpages/linefeed.txt Normal file
View File

@ -0,0 +1,26 @@
LINEFEED(1) User Commands LINEFEED(1)
NAME
linefeed - enable or disable linefeeds
SYNOPSIS
linefeed [PARM]
DESCRIPTION
The linefeed utility is used to enable or disable line-feeds when
printing the newline character. PARM can be either "on" or "off" to
enable or disable line-feeds.
The "config" command may also be used to perform a similar function.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 LINEFEED(1)

29
manpages/ls.txt Normal file
View File

@ -0,0 +1,29 @@
LS(1) User Commands LS(1)
NAME
ls - list files
SYNOPSIS
ls [OPTIONS] [DIRECTORIES]
DESCRIPTION
List the files in the DIRECTORIES to the standard output. If no
DIRECTORIES are specified, the current directory is listed. If OPTIONS
is not specified, only the file names will be listed. OPTIONS can be
one or more of the following:
-l - Long list that shows the attributes and lengths
-a - Show all files including hidden files that start with . and _
-e - Show the executable type
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 LS(1)

23
manpages/man.txt Normal file
View File

@ -0,0 +1,23 @@
MAN(1) User Commands MAN(1)
NAME
man - print a manual entry
SYNOPSIS
man [FILE]
DESCRIPTION
Prints the manual entry for a FILE to the standard output. man uses
the same display mode as "more".
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 MAN(1)

22
manpages/mkdir.txt Normal file
View File

@ -0,0 +1,22 @@
MKDIR(1) User Commands MKDIR(1)
NAME
mkdir - make a directory
SYNOPSIS
mkdir [DIRECTORY]
DESCRIPTION
Creates a directory named DIRECTORY.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 MKDIR(1)

26
manpages/more.txt Normal file
View File

@ -0,0 +1,26 @@
MORE(1) User Commands MORE(1)
NAME
more - display a file page by page
SYNOPSIS
more [FILE]
DESCRIPTION
Displays FILE page by page. The following commands are used:
<space> - Display next page
<CR> - Display next line
q - Quit
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 MORE(1)

22
manpages/mv.txt Normal file
View File

@ -0,0 +1,22 @@
ECHO(1) User Commands ECHO(1)
NAME
mv - move a file
SYNOPSIS
mv [OLDNAME] [NEWNAME]
DESCRIPTION
Moves a file from OLDNAME to NEWNAME.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 ECHO(1)

26
manpages/od.txt Normal file
View File

@ -0,0 +1,26 @@
OD(1) User Commands OD(1)
NAME
od - octal dump
SYNOPSIS
od [OPTION] [FILE]
DESCRIPTION
Dumps the contents of FILE to the standard output in octal if OPTION is
not specified, or if OPTION is "-o". If OPTION is "-x" the file will
be dumped in hexadecimal, and if OPTION is "-a" it will be dumped in
ASCII. In ASCII mode, any non-printable characters will be displayed
as escacped characters.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 OD(1)

40
manpages/pfth.txt Normal file
View File

@ -0,0 +1,40 @@
PFTH(1) User Commands PFTH(1)
NAME
pfth - interpret and execute Forth programs
SYNOPSIS
pfth [FILE]...
DESCRIPTION
pfth is a Forth interpreter that can load Forth source files from the
SD card and execute them. One or more Forth files can be specified
on the command, which will be loaded when pfth starts up.
pfth supports up to two simultaneous opened files. This allows one
file to be read while another one is written, or two files can be read
at the same time. This also allows including a file from another file.
Simple versions of the ls, cat, rm and cp commands are supported under
pfth. The Forth source files used by pfth are included in the /forth
directory. It also includes a Forth versin of the ted line editor,
some SD utilities and other sample programs.
The user can exit pfth and return to the Spinix shell by typing the
bye command.
LIMITATIONS
pfth processes a maximum of six command-line parameters. No more than
two files can be opened at the same time.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility August 2013 PFTH(1)

24
manpages/printenv.txt Normal file
View File

@ -0,0 +1,24 @@
PRINTENV(1) User Commands PRINTENV(1)
NAME
printenv - print the exported environment variables
SYNOPSIS
printenv [name...]
DESCRIPTION
If no parameters are specified, printenv will print all of the exported
environment variables. If one or more varible names are supplied only
the values of the listed variables will be printed.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2013 PRINTENV(1)

22
manpages/pwd.txt Normal file
View File

@ -0,0 +1,22 @@
PWD(1) User Commands PWD(1)
NAME
pwd - print working directory
SYNOPSIS
pwd
DESCRIPTION
Prints the current working directory to the standard output.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 PWD(1)

22
manpages/rb.txt Normal file
View File

@ -0,0 +1,22 @@
RB(1) User Commands RB(1)
NAME
rb - receive binary
SYNOPSIS
rb
DESCRIPTION
Receives a binary file from the serial port using the YMODEM protocol.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 RB(1)

22
manpages/reboot.txt Normal file
View File

@ -0,0 +1,22 @@
REBOOT(1) User Commands REBOOT(1)
NAME
reboot
SYNOPSIS
reboot
DESCRIPTION
Immediately reboots the processor.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 REBOOT(1)

22
manpages/rm.txt Normal file
View File

@ -0,0 +1,22 @@
RM(1) User Commands RM(1)
NAME
rm - remove a file
SYNOPSIS
rm [FILE]
DESCRIPTION
Remove FILE.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 RM(1)

22
manpages/sb.txt Normal file
View File

@ -0,0 +1,22 @@
SB(1) User Commands SB(1)
NAME
sb - send binary
SYNOPSIS
sb [FILE]
DESCRIPTION
Send FILE to the serial port using the YMODEM protocol.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 SB(1)

24
manpages/set.txt Normal file
View File

@ -0,0 +1,24 @@
SET(1) User Commands SET(1)
NAME
set - print the environment variables
SYNOPSIS
set
DESCRIPTION
set prints all of the shell variables, which include exported variables
and non-exported variables.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2013 SET(1)

101
manpages/shell.txt Normal file
View File

@ -0,0 +1,101 @@
SHELL(1) User Commands SHELL(1)
NAME
shell - Spinix shell program
SYNOPSIS
shell
DESCRIPTION
Provides the command-line interface for the Spinix operating system.
The shell program can execute the following commands:
pwd - print the current working directory
cd - change working directory
echo - echo the command line parameters
FILE - execute FILE
Executable files can be one of the following:
- Spinix Spin application
- Spinix C application
- Stand-alone C or Spin program
- script file
Spinix examines the first long of a file to determine what type of
executable it is. A Spin app contains "SPIN" and a C app contains
"CAPP". C apps must use the LMM memory model.
A stand-alone C or Spin program is signalled by a clock frequency
between 80 and 120 MHz. Spinix will modify the clock frequency to
match the current clock frequency when the stand-along program is run.
It does not modify any other portion of the program.
C and Spin programs must be less than or equal to 31.5K bytes since the
spinix shared memory is located in the top 512 bytes of memory.
Program files must consist of contiguous sectors, since the loader does
not implement cluster chaining. This can be ensured by using 32K
clusters.
Standard I/O can be redirected by using the ">", "<" and ">>" comand-
line modifiers.
The first line of a script file must start with "#shell". Script file
can call another script file up to 26 levels deep.
Shell script files support the following commands:
if - conditionally execute based on following condition
then - must be on the next line after an "if" line
fi - terminates the body of an if statment
while - begin conditional loop based on following condition
do - must be on the next line after a "while" line
done - terminats the body of a while statement
exit - exit the script file
An if statement may contain an executable file, such as
if spinit file
or
if test $a -ne 0
The if statement will test the return value from the executable file,
which is referenced by $?. A short-hand version of using test is to
use bracket, so that the "if test" statement above can be written as
if [ $a -ne 0 ]
The shell allows defining variables using the "=" operator, such as
a=123
There must be no spaces before or after the equal. Double quotes
can be used to assign a value containing spaces, such as
b="This is a test"
Variables can be accessed by prepending a "$" character to the name.
From the previous examples, a and b can be printed using echo by
typing
echo $a $b
Spinix provides other variables, which are $?, $#, $1, $2, etc.
$? contains the return value from the last program that has been
executed. $# contains the number of command-line parameters, and
$1, $2, etc. contain the values of the command-line parameters.
LIMITATIONS
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 SHELL(1)

351
manpages/spasm.txt Normal file
View File

@ -0,0 +1,351 @@
SPASM(1) User Commands SPASM(1)
NAME
spasm - spin assembler
SYNOPSIS
spasm [-l] [-d] FILE
DESCRIPTION
Spasm assembles the source file given by FILE. The file name may
include the extension, or .spa will be assumed if no extension is
specified. The assembled binary program will written to a file with
the same root name plus a .bin extension. If -l is specified, it will
print an assembly listing. If -d is specified, spasm will print debug
information.
Spasm is an assembly language that defines mnemonics for Spin
bytecodes. Spin bytecodes are executed by the Spin interpreter, which
is loaded at boot time from the internal ROM. The Spin interpreter is
a stack-based virtual machine that uses the stack to store parameters
that are used by operators, such as add, sub, etc. The operators store
their results back onto the stack. There are other operators that
transfer data back and forth between the stack and hub RAM.
The Spin bytecodes are listed below. They are separated into four
major groups -- lower, memory, math and extened operators. The lower
group contains a mix of operators, including those that handle program
flow, lookup, lookdown, case, and several other miscellaneous functions.
The math operators implement the various math and logic functions that
use two arguments.
The memory operators implement load, store, execute and address
functions. A load operation reads data from the hub RAM and pushes it
onto the stack. A store operation pops a value off the stack and
stores it in RAM. The address operator is used to push the absolute
address of a hub RAM location onto the stack.
The execute operation is used to execute an operation directly on a RAM
location. The result can be optionally pushed to the stack. The
operations that can be executed directly on a hub RAM location include
the standard 32 math operations plus a small number of extended
operations. The extended operators include pre and post increment and
decrement, sign extension and the random function.
The format of the memory mnemonics is as follows:
<operation><size><type><mode>
operation = {ld, st, ex, la},
size = {b, w, l},
type = {i, l, o, a, v, s}
mode = {c, x, 0, 1, m1, p}
The operations are load, store, execute and load address as stated
earlier. The size refers to byte, word and long. The types are
immediate, local, object, absolute, variable and stack. The modes
are compact, indexed, zero, one, minus one and packed.
As an example, the instruction ldwi means load-word-immediate. It
will load an immediate value onto the stack. The instruction stba
will store a byte at the absolute address residing in the stack.
There are compact instructions that use a single byte to address
the first 8 long values residing in the method's stack frame or in
an object's variable space. These use the size, type and mode
characters "llc". As an example, the method result value can be
set with the "stllc 0" instruction. The fourth long in the objet's
variable section could be loaded with "ldllc 12".
When an execute memory operation is specified it is followed by one of
the math operators or an extended operator. An execute instruction may
also specify the "load" extended operator to save the result on the
stack. Examples of using execute instructions are as follows:
exlo $8 add ' Add value on stack to the object long at offset $8
exwv $20 preinc ' Increment the VAR word at offset $20
exll $10 postdec load ' Decrement stack location $10 and load
Spasm also includes psuedo-ops, which are shortened versions of the
memory mnenomics. The psuedo-ops are made up only of the operation
and size fields, plus the "x" charater if it is indexed. The
psuedo-ops are mapped to explicit opcodes depending on the context
of the operand. As an example "ldl 1" maps into "ldli1", and
"ldl result" maps into "ldllc 0".
The Spasm opcodes are listed below. The offsets used for the jump
instructions are signed offsets that are relative to the address of the
next instruction. A "jmp 0" instruction will just execute the next
instruction.
Signed offsets are encoded in either one or two bytes depending
on the value of the most significant bit in the first byte. If the
MSB is zero the remaining seven bits are treated as a signed 7-bit
number in the range from -64 to 63. If the MSB is non-zero, the
remaining seven bits are used as the most significant bits of a 15-bit
signed number, and the next byte provides the eight least sigficant
bits. The 15-bit signed offset has a range from -16384 to 16383.
The memory opcodes use an unsigned offset that can also be encoded in
one or two bytes. The MSB is used to determine whether it is one or
two bytes just like for signed offset. However, since it is unsigned,
the range for the one-byte offset is 0 to 128, and for two bytes it is
0 to 32768.
Lower Opcodes
-------------
00 ldfrmr - Load call frame with return value required
01 ldfrm - Load call frame
02 ldfrmar - Load call frame with abort trap & return value
03 ldfrma - Load call frame with abort trap
04 jmp offset - Jump to signed object offset
05 call meth - Call method
06 callobj meth, obj - Call method in object
07 callobjx meth, obj - Call method in object with index
08 tjz offset - Test and jump if zero
09 djnz offset - Decrement and jump if not zero
0a jz offset - Jump if zero
0b jnz offset - Jump if not zero
0c casedone - Case done without a match
0d casevalue - Execute if value matches case value
0e caserange - Execute if case value within range
0f lookdone - Look up/down done without a match
10 lookupval -
11 lookdnval
12 lookuprng
13 lookdnrng
14 pop - Discard N bytes from the stack
15 run - Prepare new spin cog stack for execution
16 strsize - Determine the size of a string
17 strcomp - Compare two strings
18 bytefill - Fill memory with a constant byte value
19 wordfill - Fill memory with a constant word value
1a longfill - Fill memory with a constant long value
1b waitpeq - Wait till pins are equal to a value
1c bytemove - Copy bytes to a new location
1d wordmove - Copy words to a new location
1e longmove - Copy longs to a new location
1f waitpne - Wait till pins are not equal to value
20 clkset - Change the clock frequency and mode
21 cogstop - Stop the specified cog
22 lockret - Return a lock
23 waitcnt - Wait for cnt to equal a specified value
24 ldlsx
25 stlsx
26 exlsx
27 waitvid - Wait on video
28 coginitret - Start a cog and return the cog number
29 locknewret - Allocate a lock and return the lock number
2a locksetret - Set a lock and return the previous value
2b lockclrret - Clear a lock and return the previous value
2c coginit - Start a cog
2d locknew - Allocate a lock with no return value
2e lockset - Set a lock with no return value
2f lockclr - Clear a lock with no return value
30 abort - Perform an abort to the next abort trap
31 abortval - Perform an abort and return a value
32 ret - Return without loading a return value
33 retval - Return and load a return value on the stack
34 ldlim1 - Load a minus 1
35 ldli0 - Load zero
36 ldli1 - Load 1
37 ldlip value - Load a packed-byte constant
38 ldbi value - Load a single-byte constant
39 ldwi value - Load a two-byte constant
3a ldmi value - Load a three-byte constant
3b ldli value - Load a four-byte constant
3c --- - Unused opcode
3d ldregbit - Load a bit from a register
3d stregbit - Store a bit to a register
3e ldregbits - Load bits from a register
3e stregbits - Store bit to a register
3f ldreg - Load a register
3f streg - Store a register
Compact Memory Opcodes
--------------
40 ldlvc offset - Load long variable compact
41 stlvc offset - Store long variable compact
42 exlvc offset - Execute on a long variable compact
43 lalvc offset - Load address of a long variable compact
60 ldllc offset - Load long local compact
61 stllc offset - Store long local compact
62 exllc offset - Execute on a long local compact
63 lallc offset - Load address of a long local compact
Byte Memory Opcodes
--------------
80 ldba - Load byte absolute
81 stba - Store byte absolute
82 exba - Execute on a byte absolute
83 laba - Load address of a byte absolute
84 ldbo offset - Load byte object offset
85 stbo offset
86 exbo offset
87 labo offset
88 ldbv offset - Load byte variable offset
89 stbv offset
8a exbv offset
8b labv offset
8c ldbl offset - Load byte local offset
8d stbl offset
8e exbl offset
8f labl offset
90 ldbax - Load byte absolute with index
91 stbax
92 exbax
93 labax
94 ldbox offset - Load byte object offset with index
95 stbox offset
96 exbox offset
97 labox offset
98 ldbvx offset - Load byte variable offset with index
99 stbvx offset
9a exbvx offset
9b labvx offset
9c ldblx offset - Load byte local offset with index
9d stblx offset
9e exblx offset
9f lablx offset
Word Memory Opcodes
-------------------
a0 ldwa - Load word absolute
a1 stwa
a2 exwa
a3 lawa
a4 ldwo offset
a5 stwo offset
a6 exwo offset
a7 lawo offset
a8 ldwv offset
a9 stwv offset
aa exwv offset
ab lawv offset
ac ldwl offset
ad stwl offset
ae exwl offset
af lawl offset
b0 ldwax - Load word absolute with index
b1 stwax
b2 exwax
b3 lawax
b4 ldwox offset
b5 stwox offset
b6 exwox offset
b7 lawox offset
b8 ldwvx offset
b9 stwvx offset
ba exwvx offset
bb lawvx offset
bc ldwlx offset
bd stwlx offset
be exwlx offset
bf lawlx offset
Long Memory Opcodes
-------------------
c0 ldla - Load long absolute
c1 stla
c2 exla
c3 lala
c4 ldlo offset
c5 stlo offset
c6 exlo offset
c7 lalo offset
c8 ldlv offset
c9 stlv offset
ca exlv offset
cb lalv offset
cc ldll offset
cd stll offset
ce exll offset
cf lall offset
d0 ldlax - Load long absolute with index
d1 stlax
d2 exlax
d3 lalax
d4 ldlox offset
d5 stlox offset
d6 exlox offset
d7 lalox offset
d8 ldlvx offset
d9 stlvx offset
da exlvx offset
db lalvx offset
dc ldllx offset
dd stllx offset
de exllx offset
df lallx offset
Math Opcodes
------------
e0 ror - Rotate right
e1 rol - Rotate left
e2 shr - Shift right
e3 shl - Shift left
e4 min - Maximum
e5 max - Minimum
e6 neg - Negate
e7 com - Compliment
e8 and - Bitwise and
e9 abs - Absolute value
ea or - Bitwise or
eb xor - Bitwise exclusive or
ec add - Add
ed sub - Subtract
ee sar - Shift arithmetic right
ef rev - Bit reverse
f0 andl - Logical and
f1 encode - Shift "1" left
f2 orl - Logical or
f3 decode - Find left-most "1" bit
f4 mul - Multiply
f5 mulh - Multiply high
f6 div - Divide
f7 mod - Modulus
f8 sqrt - Square root
f9 cmplt - Less than
fa cmpgt - Greater than
fb cmpne - Not equal
fc cmpeq - Equal
fd cmple - Less than or equal
fe cmpge - Greater than or equal
ff notl - Logical not
Extended opcodes
----------------
00 load - Load the value
02 repeat - Repeat index from first to last
06 repeats - Repeat index from first to last with step
08 randf - Forward random number
0c randr - Reverse random number
10 sexb - Sign extend byte
14 sexw - Sign extend word
18 postclr - Post clear to zero
1c postset - Post set to all ones
26 preinc - Pre-increment
2e postinc - Post-increment
36 predec - Pre-decrement
3e postdec - Post-decrement
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPASM March 2012 SPASM(1)

26
manpages/spc.txt Normal file
View File

@ -0,0 +1,26 @@
SPC(1) User Commands SPC(1)
NAME
spc - spinix compiler collection
SYNOPSIS
spc FILE
DESCRIPTION
spc is a script file that compiles a Spin program into a spinix
executable by running the spinit, spasm and splink utilities. At each
step, spc will check to see if the step ran correctly before starting
the next one. In the final step, spc will link the compiled program
with the clibsd object to produce a spinix executable.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPC November 2013 SPC(1)

33
manpages/spinit.txt Normal file
View File

@ -0,0 +1,33 @@
SPINIT(1) User Commands SPINIT(1)
NAME
spinit - spin compiler
SYNOPSIS
spinit [-d] FILE
DESCRIPTION
spinit compiles a Spin program, and generates spasm code. spinit
handles a subset of the Spin language. It dese not compile PASM code,
and it does not implement the following Spin keywords:
CASE, LOOKUP, LOOKUPZ, LOOKDOWN, LOOKDOWNZ, VAR, CONSTANT
FROM, TO, STEP, FLOAT, ROUND, TRUNC
spinit also does not allow arrays to be defined.
If the -d option is specified, spinit will print out debug information
as it compiles.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIT November 2013 SPINIT(1)

37
manpages/spinix.txt Normal file
View File

@ -0,0 +1,37 @@
SPINIX(1) Spinix OS SPINIX(1)
NAME
spinix - spinix operating system
DESCRIPTION
Spinix is a linux-like operating system that runs on a Parallax
Propeller processor interfaced to an SD card. It consists of a boot
program, shell and many applications.
The boot program resides in the Propeller boot EEPROM. When run for
the first time, the boot program prompts the user for the I/O pins used
to interface to the SD card. The boot program then starts up the shell
program.
Spinix maintains a rendevous area of memory at the top of memory. The
rendevous area contains mail boxes that are used to talk to the
console and SD driver.
The shell provides a user interface that accepts commands from the
user, and executes programs that are store on the SD card.
SEE ALSO
For more information see the man pages on the boot program and the
shell.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2013 Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX OS September 2013 SPINIX(1)

30
manpages/splink.txt Normal file
View File

@ -0,0 +1,30 @@
SPLINK(1) User Commands SPLINK(1)
NAME
splink - spin linker
SYNOPSIS
splink FILE1 FILE2 FILE3 [-d]
DESCRIPTION
splink links FILE1 with FILE2 and writes the results to FILE3. FILE1
is the top object file, and it must contain only one Spin object. The
second file may contain one or more objects. The objects listed in the
OBJ section of the top object must be in the same order as those in the
second file.
LIMITATIONS
splink does not support VAR sections.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, 2013, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPLINK November 2013 SPLINK(1)

23
manpages/tail.txt Normal file
View File

@ -0,0 +1,23 @@
TAIL(1) User Commands TAIL(1)
NAME
tail - display a file tail
SYNOPSIS
tail [OPTIONS] [FILE]
DESCRIPTION
Display the last 10 lines of a file to the standard output if OPTION is
not specified. An OPTION of "-n" will display the last n lines.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 TAIL(1)

24
manpages/tar.txt Normal file
View File

@ -0,0 +1,24 @@
TAR(1) User Commands TAR(1)
NAME
tar - process a file archive
SYNOPSIS
tar [OPTION] [FILE] [FILELIST]
DESCRIPTION
Create a tar file named FILE if OPTION is "-cf". FILELIST is a list of
files to be added to the tar file. If OPTION is "-xf", files are
extracted from the tar file, FILE. FILELIST is not used in this case.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 TAR(1)

46
manpages/ted.txt Normal file
View File

@ -0,0 +1,46 @@
TED(1) User Commands TED(1)
NAME
ted - tiny text editor
SYNOPSIS
ted - [FILE]
DESCRIPTION
Edits the file named FILE. ted is a subset of the ed text editor It
uses single letter commands that may be prefixed by a line number or a
range of line numbers. The "." character represents the current line,
and the "$" character is the last line number. A range is specifed by
two line numbers seperated by a comma, such as "1,10" or ".,$".
The commands are:
q - quit
w - write edit buffer to FILE
d - delete the current line
i - insert lines after the current line
a - append lines before the current line
p - print lines
n - print lines with line number
j - join the current line with the next line
# - move to line #
. - current line
$ - move to last line
- - move down one line
+ - move up one line
h - print help information
LIMITATIONS
A file name must be specified when starting ted or it will write a
blank file name when using the "w" command.
AUTHOR
Dave Hein
COPYRIGHT
Copyright (c) 2011, 2012, Dave Hein
MIT License (See license.txt in the root directory)
This is free software: you are free to change and redistribute it.
There is no warranty, to the extent permitted by law.
SPINIX utility March 2012 TED(1)

Some files were not shown because too many files have changed in this diff Show More