Administra: add dcf77 and bluetooth

This commit is contained in:
Jörg Deckert 2014-04-28 17:04:21 +02:00
parent a63c3ef313
commit 387e9d8e56
4 changed files with 1026 additions and 128 deletions

View File

@ -80,6 +80,7 @@ COG's : MANAGMENT 1 COG
SIDCog's 2 COG's
DMP/Tracker 1 COG (dynamisch)
NET 2 COG
DCF receiver 1 COG
Defines : __ADM_FAT enable FAT engine (sd card handling)
__ADM_HSS enable HSS synthesizer
@ -89,6 +90,8 @@ Defines : __ADM_FAT enable FAT engine (sd card handling)
__ADM_LAN enable LAN functions
__ADM_RTC enable RTC functions (FAT engine inherits it also)
__ADM_PLX enable plexbus
__ADM_DCF enable DCF77 receiver
__ADM_BLT enable Bluetooth
__ADM_COM enable serial port
__ADM_AYS enable AYS player
@ -159,17 +162,20 @@ Notizen :
CON
''default defines (please anable to compile from GUI)
'#define __ADM_FAT
#define __ADM_FAT
'#define __ADM_HSS
'#define __ADM_HSS_PLAY
'#define __ADM_WAV
'#define __ADM_RTC
#define __ADM_RTC
'#define __ADM_COM
''other defines
'#define __ADM_LAN
'#define __ADM_SID
#define __ADM_SID
'#define __ADM_AYS
#define __ADM_PLX
#define __ADM_DCF
#define __ADM_BLT
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
@ -243,7 +249,19 @@ CHIP_SPEC_AYS = gc#A_AYS
CHIP_SPEC_AYS = 0
#endif
CHIP_SPEC = CHIP_SPEC_FAT|CHIP_SPEC_LDR|CHIP_SPEC_HSS|CHIP_SPEC_WAV|CHIP_SPEC_SID|CHIP_SPEC_LAN|CHIP_SPEC_RTC|CHIP_SPEC_PLX|CHIP_SPEC_COM|CHIP_SPEC_AYS
#ifdef __ADM_DCF
CHIP_SPEC_DCF = gc#A_DCF
#else
CHIP_SPEC_DCF = 0
#endif
#ifdef __ADM_BLT
CHIP_SPEC_BLT = gc#A_BLT
#else
CHIP_SPEC_BLT = 0
#endif
CHIP_SPEC = CHIP_SPEC_FAT|CHIP_SPEC_LDR|CHIP_SPEC_HSS|CHIP_SPEC_WAV|CHIP_SPEC_SID|CHIP_SPEC_LAN|CHIP_SPEC_RTC|CHIP_SPEC_PLX|CHIP_SPEC_COM|CHIP_SPEC_AYS|CHIP_SPEC_DCF|CHIP_SPEC_BLT
'
' hbeat --------+
' clk -------+|
@ -330,6 +348,12 @@ OBJ
sock : "driver_socket" 'LAN
num : "glob-numbers" 'Number Engine
#endif
#ifdef __ADM_PLX
com : "adm-plx" 'PlexBux
#endif
#ifdef __ADM_DCF
dcf : "adm-dcf" 'DCF-77
#endif
gc : "glob-con" 'globale konstanten
@ -339,6 +363,9 @@ VAR
byte tbuf2[20]
byte fl_syssnd '1 = systemtöne an
byte st_sound '0 = aus, 1 = hss, 2 = wav
#ifdef __ADM_DCF
byte dcfon 'DCF-Betriebsmerker
#endif
CON ''------------------------------------------------- ADMINISTRA
@ -350,6 +377,12 @@ PUB main | cmd,err 'chip: kommandointerpret
init_chip 'bus/vga/keyboard/maus initialisieren
repeat
#ifdef __ADM_DCF
if dcfon
if dcf.GetInSync==1
if dcf.GetBitNumber==59 'Zeittelegramm gültig?, dann RTC synchronisieren (jedes gültige Telegramm)
dcf_updateRTC
#endif '__ADM_DCF
cmd := bus_getchar 'kommandocode empfangen
err := 0
case cmd
@ -396,8 +429,15 @@ PUB main | cmd,err 'chip: kommandointerpret
gc#a_comRx: com_rx
#endif '__ADM_COM
' ---------------------------------------------- Bluetooth-FUNKTIONEN
#ifdef __ADM_BLT
gc#a_bltCommand_On: blt_setCommandMode
gc#a_bltCommand_Off: blt_setNormalMode
#endif '__ADM_BLT
' ---------------------------------------------- RTC-FUNKTIONEN
#ifdef __ADM_RTC
gc#a_rtcTest: rtc_test 'Test if RTC Chip is available
gc#a_rtcGetSeconds: rtc_getSeconds 'Returns the current second (0 - 59) from the real time clock.
gc#a_rtcGetMinutes: rtc_getMinutes 'Returns the current minute (0 - 59) from the real time clock.
gc#a_rtcGetHours: rtc_getHours 'Returns the current hour (0 - 23) from the real time clock.
@ -416,9 +456,31 @@ PUB main | cmd,err 'chip: kommandointerpret
gc#a_rtcGetNVSRAM: rtc_getNVSRAM 'Gets the selected NVSRAM value at the index (0 - 55).
gc#a_rtcPauseForSec: rtc_pauseForSeconds 'Pauses execution for a number of seconds. Returns a puesdo random value derived from the current clock frequency and the time when called. Number - Number of seconds to pause for between 0 and 2,147,483,647.
gc#a_rtcPauseForMSec: rtc_pauseForMilliseconds 'Pauses execution for a number of milliseconds. Returns a puesdo random value derived from the current clock frequency and the time when called. Number - Number of milliseconds to pause for between 0 and 2,147,483,647.
gc#a_rtcTest: rtc_test 'Test if RTC Chip is available
gc#a_rtcGetTime: rtc_getTime 'Returns the current hour, minute and second from the real time clock.
#endif '__ADM_RTC
' ---------------------------------------------- DCF77-FUNKTIONEN
#ifdef __ADM_DCF
gc#a_dcfGetInSync: dcf_getInSync 'Sync-Status senden
gc#a_dcfUpdateRTC: dcf_updateRTC 'RTC Synchronisieren
gc#a_dcfGetBitError: dcf_getBitError
gc#a_dcfGetDataCount: dcf_getDataCount
gc#a_dcfGetBitNumber: dcf_getBitNumber
gc#a_dcfGetBitLevel: dcf_getBitLevel
gc#a_dcfGetTimeZone: dcf_getTimeZone
gc#a_dcfGetActiveSet: dcf_getActiveSet
gc#a_dcfStart: dcf_start 'DCF-Empfang starten
gc#a_dcfStop: dcf_stop 'DCF-Empfang stoppen
gc#a_dcfState: dcf_state 'Status des DCF-Empfängers
gc#a_dcfGetSeconds: dcf_getSeconds
gc#a_dcfGetMinutes: dcf_getMinutes
gc#a_dcfGetHours: dcf_getHours
gc#a_dcfGetWeekDay: dcf_getWeekDay
gc#a_dcfGetDay: dcf_getDay
gc#a_dcfGetMonth: dcf_getMonth
gc#a_dcfGetYear: dcf_getYear
#endif '__ADM_DCF
' ---------------------------------------------- LAN-FUNKTIONEN
#ifdef __ADM_LAN
gc#a_lanStart: lan_start 'Start Network
@ -593,7 +655,7 @@ PRI init_chip | err,i,j 'chip: initialisierung d
#ifdef __ADM_COM
'serielle schnittstelle starten
com_baud := 9600
com.start(gc#SER_RX,gc#SER_TX,0,com_baud) ' start the default serial interface
com.start(gc#SER_RX,gc#SER_TX,0,com_baud) 'start the default serial interface
#endif '__ADM_COM
#ifdef __ADM_LAN
@ -601,6 +663,11 @@ PRI init_chip | err,i,j 'chip: initialisierung d
lan_started := false 'LAN noch nicht gestartet
#endif '__ADM_LAN
#ifdef __ADM_DCF
'DCF-77
dcfon:=0
#endif '__ADM_DCF
PRI bus_putchar(zeichen) 'chip: ein byte über bus ausgeben
''funktionsgruppe : chip
''funktion : senderoutine für ein byte zu regnatix über den systembus
@ -1398,6 +1465,22 @@ CON ''------------------------------------------------- End of COM FUNCTIONS
#endif ' __ADM_COM
CON ''------------------------------------------------- Bluetooth FUNCTIONS
#ifdef __ADM_BLT
PRI blt_setCommandMode
dira[gc#A_Bluetooth_Line]:=1
outa[gc#A_Bluetooth_Line]:=1
PRI blt_setNormalMode
outa[gc#A_Bluetooth_Line]:=0
dira[gc#A_Bluetooth_Line]:=0
CON ''------------------------------------------------- End of Bluetooth FUNCTIONS
#endif ' __ADM_BLT
CON ''------------------------------------------------- HSS-FUNKTIONEN
#ifdef __ADM_HSS
@ -2055,10 +2138,108 @@ PRI rtc_test 'rtc: Test if RTC Chip i
'' : Returns TRUE if RTC is available, otherwise FALSE
bus_putchar(probeRTC)
PRI rtc_getTime
sub_putlong(rtc.getHours)
sub_putlong(rtc.getMinutes)
sub_putlong(rtc.getSeconds)
CON ''------------------------------------------------- End of RTC FUNCTIONS
#endif ' __ADM_RTC
CON ''------------------------------------------------- DCF77-FUNKTIONEN
#ifdef __ADM_DCF
VAR
PRI dcf_getInSync 'dcf: Sync-Status senden
bus_putchar(dcf.GetInSync)
PRI dcf_updateRTC 'dcf: RTC Synchronisieren
#ifdef __ADM_RTC
rtc.setHours(dcf.GetHours)
rtc.setMinutes(dcf.GetMinutes)
rtc.setSeconds(dcf.GetSeconds)
rtc.setYear(dcf.GetYear)
rtc.setMonth(dcf.GetMonth)
rtc.setDate(dcf.GetDay)
rtc.setDay(dcf.GetWeekDay)
#endif ' __ADM_RTC
PRI dcf_getBitError
bus_putchar(dcf.GetBitError)
PRI dcf_getDataCount
bus_putchar(dcf.GetDatacount)
PRI dcf_getBitNumber
bus_putchar(dcf.GetBitNumber)
PRI dcf_getBitLevel
bus_putchar(dcf.GetBitLevel)
PRI dcf_getTimeZone
bus_putchar(dcf.GetTimeZone)
PRI dcf_getActiveSet
bus_putchar(dcf.GetActiveSet)
PRI dcf_start 'dcf: DCF-Empfang starten
dcf.start
dcfon:=1
PRI dcf_stop 'dcf: DCF-Empfang stoppen
dcf.stop
dcfon:=0
PRI dcf_state 'dcf: Status des DCF-Empfängers
bus_putchar(dcfon)
PRI dcf_getSeconds
bus_putchar(dcf.GetSeconds)
PRI dcf_getMinutes
bus_putchar(dcf.GetMinutes)
PRI dcf_getHours
bus_putchar(dcf.GetHours)
PRI dcf_getWeekDay
bus_putchar(dcf.GetWeekDay)
PRI dcf_getDay
bus_putchar(dcf.GetDay)
PRI dcf_getMonth
bus_putchar(dcf.GetMonth)
PRI dcf_getYear
sub_putword(dcf.GetYear)
CON ''------------------------------------------------- End of DCF77 FUNCTIONS
#endif ' __ADM_DCF
CON ''------------------------------------------------- LAN-FUNKTIONEN
#ifdef __ADM_LAN

524
lib/adm-dcf.spin Normal file
View File

@ -0,0 +1,524 @@
{{******************************************************************************}
{ FileName............: Dcf77.spin }
{ Project.............: }
{ Author(s)...........: MM }
{ Version.............: 1.00 }
{------------------------------------------------------------------------------}
{ DCF77 (clock) control }
{ }
{ Copyright (C) 2006-2007 M.Majoor }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the }
{ GNU General Public License for more details. }
{ }
{ You should have received a copy of the GNU General Public License }
{ along with this program; if not, write to the Free Software }
{ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. }
{ }
{------------------------------------------------------------------------------}
{ }
{ Version Date Comment }
{ 1.00 20070727 - Initial release }
{******************************************************************************}
{------------------------------------------------------------------------------}
DCF77 is a time signal being transmitted by 'radio'. The time signal being
transmitted is based on an atomic clock.
This code assumes we have a DCF77 receiver with a digital output. This output
is connected to one of the available input pins.
The output pin of the DCF77 receiver changes it output according to the
received radio signal. This radio signal is an amplitude modulated signal.
The amplitude level is converted into a digital signal by the DCF77 receiver.
A typical output signal of a DCF77 receiver is:
┌──┐ ┌──┐ ┌─┐
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
┘ └─────────────────┘ └───────────────────┘ └──────────────────
The spacing of these pulses is 1 second. Every second the amplitude signal is
being lowered for a small duration (0.1 s or 0.2 s). This lowered amplitude
is being output as a pulse here.
The duration of the pulse defines whether it represents a digital '0' or a
digital '1'.
These digital '0' and '1' together form a digital representation of the time.
This digital stream of bits is being transmitted within one minute. The next
minute a new digital stream starts.
For synchronization purposes there will be no pulse when the 59's digital signal
is being transmitted. This is used to indicate the start of the next digital
stream (and the next minute).
The pulse length is converted into a binary signal according to its length:
0.1s --> '0'
0.2s --> '1'
The digital stream format is (with the first received bit at the right):
5 555555555 44444 444 443333 3333332 22222222 211111 11111
Sec 9 876543210 98765 432 109876 5432109 87654321 098765 432109876543210
D P84218421 18421 421 218421 P218421 P4218421 SAZZAR
30000 0 00 200 1000 2211
R = Call bit (irregularities in DCF77 control facilities)
A1 = '1' Imminent change-over of time from CET <-> CEST
Transmitted 1 hour prior to change (refelected in Z1/Z2)
Z1 = Zone time bit 0 '10' = CET ; UTC + 1 hour
Z2 = Zone time bit 1 '01' = CEST; DST ; dayligt saving time, UTC + 2 hours
A2 = '1' Imminent change-over of leap second
Transmitted 1 hour prior to change (January 1/July 1)
S = Startbit coded time information (always '1')
1 = Minute (BCD)
2 = ,,
4 = ,,
8 = ,,
10 = ,,
20 = ,,
40 = ,,
P1 = Parity bit preceeding 7 bits (all bits including parity equals even number)
1 = Hour (BDC)
2 = ,,
4 = ,,
8 = ,,
10 = ,,
20 = ,,
P2 = Parity bit preceeding 6 bits (all bits including parity equals even number)
1 = Calendar day (BCD)
2 = ,,
4 = ,,
8 = ,,
10 = ,,
20 = ,,
1 = Day of the week (BCD) 1 = Monday
2 = ,,
4 = ,,
1 = Month (BCD)
2 = ,,
4 = ,,
8 = ,,
10 = ,,
1 = Year (BCD)
2 = ,,
4 = ,,
8 = ,,
10 = ,,
20 = ,,
40 = ,,
80 = ,,
P3 = Parity bit preceeding 22 bits (all bits including parity equals even number)
D = No pulse here except for leap second ('0' pulse) -> the next (leap) second
then has no pulse.
The pulse following the 'no pulse' indicates start of next minute/data stream.
The DCF device is connected as follows:
3V3
┌────────┐ 
R │ DCF │ 10k
3V3 ──┳──┳──┤ ├─┻── Input
C  │ device │
┌────┻──┻──┤ │
 └────────┘
R = 1kΩ
C = 1uF + 1nF
The resistor here has one major purpose: filtering out any noise from the 3V3
power supply, which is typically connected directly to the Propeller device.
Since the DCF signal itself is a low frequency (77.5 kHz), it falls within
the frequency range of the Propeller chip itself, which can lead to problems.
Without this resistor the DCF device was unable to function properly. The
resistor has very little impact on the voltage available to the DCF device.
Because the DCF device draws very little current, the voltage drop over the
resistor is very low (0.08V here).
{------------------------------------------------------------------------------}}
CON
CDcfIn = 22 ' Input pin for DCF77 _>Hive ADM-Port 1 ->Expansionsbus B17
CDcfOut = 24 ' Output pin for DCF77 signal (debug/visualization) ->Hive-Administra-LED
CDcfLevel = 1 ' Level for '1' signal
CNoSync = 0 ' Not in sync (never sync data received)
CInSync = 1 ' In sync (no error since last sync)
CInSyncWithError = 2 ' Not in sync (error since last sync), but time is up to date
CCest = 1 ' CEST timezone (daylight saving time)
CCet = 2 ' CET timezone
CAm = 0 ' AM
CPm = 1 ' PM
VAR
byte Cog ' Active cog
long Stack[26] ' Stack for cog
byte Bits[8] ' Current detection of pulses (bit access)
long BitLevel ' Current bit level (NOT the signal level!)
long BitError ' Current bit status
byte BitNumber ' Current index of bit (== seconds)
' Time settings
byte DataCount ' Incremented when data below updated
byte TimeIndex ' Indicates the active index for the time settings
' Typically the background writes in one of the registers
' and if they all check out it makes them available by
' changing the TimeIndex.
byte InSync ' Synchronization indication
byte TimeZone[2]
byte Seconds[2]
byte Minutes[2]
byte Hours[2] ' 0..23 hour indication
byte HoursAmPm[2] ' 1..12 hour indication (used with AM/PM)
byte AmPm[2]
byte WeekDay[2]
byte Day[2]
byte Month[2]
word Year[2]
{{------------------------------------------------------------------------------
Params : -
Returns : <Result> TRUE if cog available
Descript: Start DCF acquisition
Notes :
------------------------------------------------------------------------------}}
PUB Start: Success
{
DIRA[dcfstart]~~
outa[dcfstart]:=1
waitcnt((clkfreq * 2)+ cnt)
outa[dcfstart]:=0
}
result := Cog := cognew(DcfReceive, @Stack)
{{------------------------------------------------------------------------------
Params : -
Returns : -
Descript: Stop cog and DCF acquisition
Notes :
------------------------------------------------------------------------------}}
PUB Stop
if Cog == 0 ' Only if cog is active
return
cogstop(Cog) ' Stop the cog
{{------------------------------------------------------------------------------
Params : -
Returns : -
Descript: Interfaces to variables
Notes :
------------------------------------------------------------------------------}}
PUB GetActiveSet: Value
result := TimeIndex
PUB GetInSync: Value
result := InSync
PUB GetTimeZone: Value
result := TimeZone[TimeIndex]
PUB GetSeconds: Value
result := Seconds[TimeIndex]
PUB GetMinutes: Value
result := Minutes[TimeIndex]
PUB GetHours: Value
result := Hours[TimeIndex]
PUB GetWeekDay: Value
result := WeekDay[TimeIndex]
PUB GetDay: Value
result := Day[TimeIndex]
PUB GetMonth: Value
result := Month[TimeIndex]
PUB GetYear: Value
result := Year[TimeIndex]
PUB GetBit(Index): Value
result := Bits[Index]
PUB GetDataCount: Value
result := DataCount
PUB GetBitNumber: Value
result := BitNumber
PUB GetBitLevel: Value
result := BitLevel
PUB GetBitError: Value
result := BitError
{{------------------------------------------------------------------------------
Params : -
Returns : -
Descript: Handle DCF reception
Notes : At fixed intervals the DCF input is polled. Every second the
data is checked and the data updated.
This code does not compensate for a leap second. However, this
is handled by a resynchronization.
We use a state machine so we can divide everything up.
Digital output:
On : In sync (no error)
1 Hz : In sync with DCF77 signal (rising edge is start second)
3 Hz : In sync with DCF77 signal (59th second)
Active in first 0.5 second
10 Hz : Previous bit had error
Active in first 0.5 second
20 Hz : Resyncing (waiting for pulse, max 1 s); followed by bit
error signal
This is the only variable in length (time) signal
The last 100 ms of the 2nd 0.5 second contains a small 40 ms pulse
when a binary '1' has been detected (for a '0' no pulse is generated)
If no signal is being received then the following output is
repeatedly generated: 20 Hz (1s), 10 Hz (0.5s), no signal (0.5s)
------------------------------------------------------------------------------}}
PUB DcfReceive | LLocalTime, LIntervalCounts, LState, LWaitInterval, LBitNumber, LBitError, LLevels, LBitLevel, LIndex, LAccu, LParity, LError, LNewData
DIRA[CDcfIn]~
DIRA[CDcfOut]~~
DataCount := 0
LLocalTime := 0
InSync := CNoSync
LNewData := FALSE
LWaitInterval := CNT ' Get current system counter
LState := 99 ' Last state == initiates new state
LIntervalCounts := (CLKFREQ / (1000 / 10)) #>381 ' Interval counts
TimeIndex := 0
LIndex := 1
repeat
' The state machine consists of 100 equal steps
' Each of these steps have a time span of 10 ms, getting to a total
' of 1 second
waitcnt(LWaitInterval += LIntervalCounts) ' Wait for next interval
' We keep the local time running independent from the received DCF signal
' because that might need synchronization. Only when synchronization has taken place
' the local time is synchronized with the DCF. This only happens every minute, when
' the received data checks out correctly
LLocalTime++
case LLocalTime
001: ' Update local time
' Note: the date is not adjusted
if Seconds[TimeIndex] == 59
Seconds[TimeIndex] := 0
if Minutes[TimeIndex] == 59
Minutes[TimeIndex] := 0
if HoursAmPm[TimeIndex] == 12
HoursAmPm[TimeIndex] := 1
if AmPm[TimeIndex] == CAm
AmPm[TimeIndex] := CPm
else
AmPm[TimeIndex] := CAm
else
HoursAmPm[TimeIndex]++
if Hours[TimeIndex] == 23
Hours[TimeIndex] := 0
if WeekDay[TimeIndex] == 7
WeekDay[TimeIndex] := 1
else
WeekDay[TimeIndex]++
else
Hours[TimeIndex]++
else
Minutes[TimeIndex]++
else
Seconds[TimeIndex]++
100: LLocalTime := 0
' Handling the 0/1 detection
' We allow a 10% margin of error:
' 0 .. 0.3s 0/1 signal detection
' 0.3 .. 0.9s signal must be 0
' 0.9 .. 1 s not checked
' 1 .. 2 s only when resync active
LState++
case LState
01..30 : if INA[CDcfIn] == CDcfLevel
LLevels++ ' We only need to check one level
31..90 : if INA[CDcfIn] == CDcfLevel
LBitError := TRUE ' Any signal here is an error
101..200: if INA[CDcfIn] == CDcfLevel
LState := 0 ' Restart state machine
' We divide the second up into several parts, including handling data of the
' previous second.
' In the last state (100) data from the current second are copied to the data
' which is handled the next second
case LState
091: if (LLevels => 15) ' Decide if we detected a binary '0' or '1'
LBitLevel := TRUE
Bits[LBitNumber / 8] |= (1 << (LBitNumber // 8))
else
LBitLevel := FALSE
Bits[LBitNumber / 8] &= !(1 << (LBitNumber // 8))
092: ' Check for illogical data (this might also be the missing pulse occuring every minute)
if LBitNumber <> 59
LBitError := LBitError | (LLevels =< 5) | (LLevels => 25)
093: ' We can check the received data immediately
' The background operates on the inactive settings
if LBitLevel
LParity++
case LBitNumber
0 : if LNewData ' If new data, switch over to new data set
Seconds[LIndex] := 0 ' Synchronize seconds
' Note: we can not synchronize in the
' 59th seconds because the 'local time'
' state machine adjusts the minutes/hours
' when the seconds reaches '60'
LLocalTime := 0 ' Synchronize the 'local time' state machine
if TimeIndex == 0 ' Switch to different active set
TimeIndex := 1
LIndex := 0
else
TimeIndex := 0
LIndex := 1
InSync := CInSync
OUTA[CDcfOut]~~ ' Output on
LNewData := FALSE
LError := FALSE
15 : ' R = Call bit (irregularities in DCF77 control facilities)
16 : ' A1 = '1' Imminent change-over of time from CET <-> CEST
' Transmitted 1 hour prior to change (refelected in Z1/Z2)
19 : ' A2 = '1' Imminent change-over of leap second
' Transmitted 1 hour prior to change (January 1/July 1)
20 : if !LBitLevel ' S = Startbit coded time information (always '1')
LError := TRUE
17, 42, 45, 50 : if LBitLevel ' Start new data
LAccu := 1
else
LAccu := 0
21, 29, 36 : if LBitLevel ' Start new data and parity controlled data
LAccu := 1
LParity := 1
else
LAccu := 0
LParity := 0
18, 22, 30, 37, 43, 46, 51: if LBitLevel ' 2
LAccu += 2
case LBitNumber
18: TimeZone[LIndex] := LAccu
if (LAccu == %00) or (LAccu == %11)
LError := TRUE
23, 31, 38, 44, 47, 52 : if LBitLevel ' 4
LAccu += 4
case LBitNumber
44: WeekDay[LIndex] := LAccu
24, 32, 39, 48, 53 : if LBitLevel ' 8
LAccu += 8
25, 33, 40, 49, 54 : if LBitLevel ' 10
LAccu += 10
case LBitNumber
49: Month[LIndex] := LAccu
26, 34, 41, 55 : if LBitLevel ' 20
LAccu += 20
case LBitNumber
34: Hours[LIndex] := LAccu
if LAccu > 11 ' 1..12 Hour + AM/PM
AmPm[LIndex] := CPm
else
AmPm[LIndex] := CAm
if LAccu > 12
HoursAmPm[LIndex] := LAccu - 12
else
if LAccu == 0
HoursAmPm[LIndex] := 12
else
HoursAmPm[LIndex] := LAccu
41: Day[LIndex] := LAccu
27, 56 : if LBitLevel ' 40
LAccu += 40
case LBitNumber
27: Minutes[Lindex] := LAccu
57 : if LBitLevel ' 80
LAccu += 80
Year[LIndex] := 2000 + LAccu
28, 35, 58 : if (LParity & %1) <> 0
LError := TRUE
59 : ' D = No pulse here except for leap second ('0' pulse) -> the next (leap) second
' then has no pulse.
' The pulse following the 'no pulse' indicates start of next minute/data stream.
if !LError
LNewData := TRUE
100: ' Copy current second data to data we will be handling the next second
' and (re)set data for next second
if !LBitError ' An error switches to the next state (resync)
LState := 0 ' otherwise restart state machine
BitLevel := LBitLevel
LBitLevel := FALSE
BitError := LBitError
LBitError := FALSE
BitNumber := LBitNumber ' Last to change because foreground might check this one
' to read others
LLevels := 0
if BitError ' A sync error resets the second counter
LBitNumber := 0
if InSync == CInSync
InSync := CInSyncWithError ' 'Out of sync' if we were 'in sync'
else
LBitNumber++ ' Next second
if LBitNumber == 60 ' We could check for leap second here, but ...
LBitNumber := 0
DataCount++ ' Adjust data indicator for foreground
201: LState := 0 ' Resync failed: restart state machine
' Output
' time out biterror sec59 level Note: 'biterror' and 'sec59' never active at same time
' 1 1 1 1 1
' 10 0
' 17 0
' 20 1
' 30 0
' 34 1
' 40 1
' 50 0 0 0 0
' 75 1
' 91 1
' 95 0 0 0 0
' 101 1 1 1 1
' .. t t t t
' 195 0 0 0 0
if InSync <> CInSync ' Only control the output when not in sync
case LState
001 : OUTA[CDcfOut]~~ ' Always on
010, 020, 030, 040: if BitError ' 10 Hz signal (bit error)
!OUTA[CDcfOut]
017, 034, 075 : if !BitError AND (LBitNumber == 59) ' 3 Hz signal (in sync and 59th second)
!OUTA[CDcfOut]
091 : if LBitLevel ' Bit is '1'
!OUTA[CDcfOut] ' Always off
050, 095 : OUTA[CDcfOut]~
101, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 185, 190, 195: !OUTA[CDcfOut]

View File

@ -1,127 +1,268 @@
''*******************************************************************
''* Simple Asynchronous Serial Driver v1.3 *
''* Authors: Chip Gracey, Phil Pilgrim, Jon Williams, Jeff Martin *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''*******************************************************************
''
'' Performs asynchronous serial input/output at low baud rates (~19.2K or lower) using high-level code
'' in a blocking fashion (ie: single-cog (serial-process) rather than multi-cog (parallel-process)).
''
'' To perform asynchronous serial communication as a parallel process, use the FullDuplexSerial object instead.
''
''
'' v1.3 - May 7, 2009 - Updated by Jeff Martin to fix rx method bug, noted by Mike Green and others, where uninitialized
'' variable would mangle received byte.
'' v1.2 - March 26, 2008 - Updated by Jeff Martin to conform to Propeller object initialization standards and compress by 11 longs.
'' v1.1 - April 29, 2006 - Updated by Jon Williams for consistency.
''
''
'' The init method MUST be called before the first use of this object.
'' Optionally call finalize after final use to release transmit pin.
''
'' Tested to 19.2 kbaud with clkfreq of 80 MHz (5 MHz crystal, 16x PLL)
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@gmail.com
System : mental
Name : I2C/PlexBus-Objekt
Chip : Administra
Typ :
Funktion :
COG's :
Logbuch :
Notizen :
}}
OBJ
gc : "m-glob-con"
CON
SCL = gc#adm_scl
SDA = gc#adm_sda
' VNX = gc#adm_int1
' portadressen sepia
'pcf8574 %0100_ABC_0
PORT1 = %0100_000 '$20
PORT2 = %0100_001 '$21
PORT3 = %0100_010 '$22
{
'pcf8574a %0111_ABC_0
PORT1 = %0111_000 '$38
PORT2 = %0111_001 '$39
PORT3 = %0111_010 '$3A
}
' ad/da-wandler-adresse
'pcf8591 %1001_ABC_R
ADDA0 = %1001_000
ADDA0_WR = %1001_000_0
ADDA0_RD = %1001_000_1
'
' +------------- 0
' | +----------- 1 = analog output enable
' | | +-------- 00 - four single endet input
' | | | 01 - three differential inputs
' | | | 10 - single ended and differential mixed
' | | | 11 - two differential inputs
' | | | +------ 0
' | | | | +---- 1 = auto-increment
' | | | | | +- 00 - channel 0
' | | | | | | 01 - channel 1
' | | | | | | 10 - channel 2
' | | | | | | 11 - channel 3
' | | -+ | | -+
ADDA0_INIT = %0_1_00_0_0_00
ADDA0_SCAN = %0_1_00_0_1_00
ADDA0_CH0 = %0_1_00_0_0_00
ADDA0_CH1 = %0_1_00_0_0_01
ADDA0_CH2 = %0_1_00_0_0_10
ADDA0_CH3 = %0_1_00_0_0_11
' index der register
R_PAD0 = 0
R_PAD1 = 1
R_PAD2 = 2
R_PAD3 = 3
R_INP0 = 4
R_INP1 = 5
R_INP2 = 6
' R_VNX = 7
VAR
long sin, sout, inverted, bitTime, rxOkay, txOkay
byte joy0
byte pad0
byte plxreg[16]
long plxstack[16]
long plxcogid
PUB init(rxPin, txPin, baud): Okay
{{Call this method before first use of object to initialize pins and baud rate.
byte plxback
byte plxlock
• For true mode (start bit = 0), use positive baud value. Ex: serial.init(0, 1, 9600)
For inverted mode (start bit = 1), use negative baud value. Ex: serial.init(0, 1, -9600)
• Specify -1 for "unused" rxPin or txPin if only one-way communication desired.
• Specify same value for rxPin and txPin for bi-directional communication on that pin and connect a pull-up/pull-down resistor
to that pin (depending on true/inverted mode) since pin will set it to hi-z (input) at the end of transmission to avoid
electrical conflicts. See "Same-Pin (Bi-Directional)" examples, below.
byte adr_adda 'adresse adda (poller)
byte adr_port 'adresse ports (poller)
EXAMPLES:
PUB init 'plx: io-system initialisieren
Standard Two-Pin Bi-Directional True/Inverted Modes Standard One-Pin Uni-Directional True/Inverted Mode
Ex: serial.init(0, 1, ±9600) Ex: serial.init(0, -1, ±9600) -or- serial.init(-1, 0, ±9600)
┌────────────┐ ┌──────────┐ ┌────────────┐ ┌──────────┐
│Propeller P0├─────────────┤I/O Device│ │Propeller P0├───────────────┤I/O Device│
│ P1├─────────────┤ │ └────────────┘ └──────────┘
└────────────┘ └──────────┘
outa[SCL] := 1 'SCL = 1
dira[SCL] := 1 'SCL = ausgang
dira[SDA] := 0 'SDA = eingang
adr_adda := ADDA0
adr_port := PORT1
'ad/da-wandler initialisieren
ad_init(ADDA0)
Same-Pin (Bi-Directional) True Mode Same-Pin (Bi-Directional) Inverted Mode
Ex: serial.init(0, 0, 9600) Ex: serial.init(0, 0, -9600)
 ┌────────────┐ ┌──────────┐
│ │Propeller P0├─────┳─────┤I/O Device│
 4.7 kΩ └────────────┘ │ └──────────┘
┌────────────┐ │ ┌──────────┐  4.7 kΩ
│Propeller P0├─────┻─────┤I/O Device│ │
└────────────┘ └──────────┘ 
}}
'semaphore anfordern
'plxlock := 2 'mental
plxlock := locknew 'trios
finalize ' clean-up if restart
'pollcog starten
plxcogid := cognew(poller,@plxstack)
pub plxstop
rxOkay := rxPin > -1 ' receiving?
txOkay := txPin > -1 ' transmitting?
if(plxcogid)
cogstop(plxcogid~ - 1)
lockret(-1 + plxlock~)
PRI poller 'plx: pollcog
sin := rxPin & $1F ' set rx pin
sout := txPin & $1F ' set tx pin
repeat
'semaphore setzen
repeat until not lockset(plxlock) 'auf freien bus warten
inverted := baud < 0 ' set inverted flag
bitTime := clkfreq / ||baud ' calculate serial bit time
'analoge eingänge pollen
plxreg[R_PAD0] := ad_ch(adr_adda,0)
plxreg[R_PAD1] := ad_ch(adr_adda,1)
lockclr(plxlock) 'bus freigeben
return rxOkay | TxOkay
repeat until not lockset(plxlock) 'auf freien bus warten
plxreg[R_PAD2] := ad_ch(adr_adda,2)
plxreg[R_PAD3] := ad_ch(adr_adda,3)
lockclr(plxlock) 'bus freigeben
repeat until not lockset(plxlock) 'auf freien bus warten
'digitale eingabeports pollen
plxreg[R_INP0] := in(adr_port )
plxreg[R_INP1] := in(adr_port+1)
plxreg[R_INP2] := in(adr_port+2)
'semaphore freigeben
lockclr(plxlock) 'bus freigeben
PUB finalize
{{Call this method after final use of object to release transmit pin.}}
PUB run 'plx: polling aktivieren
if txOkay ' if tx enabled
dira[sout]~ ' float tx pin
rxOkay := txOkay := false
lockclr(plxlock) 'bus freigeben
PUB halt 'plx: polling stoppen
PUB rx: rxByte | t
{{ Receive a byte; blocks caller until byte received. }}
repeat until not lockset(plxlock) 'auf freien bus warten
if rxOkay
dira[sin]~ ' make rx pin an input
waitpeq(inverted & |< sin, |< sin, 0) ' wait for start bit
t := cnt + bitTime >> 1 ' sync + 1/2 bit
repeat 8
waitcnt(t += bitTime) ' wait for middle of bit
rxByte := ina[sin] << 7 | rxByte >> 1 ' sample bit
waitcnt(t + bitTime) ' allow for stop bit
CON 'Devices: PORTS, AD/DA-WANDLER
rxByte := (rxByte ^ inverted) & $FF ' adjust for mode and strip off high bits
PUB in(adr):data | ack 'plx: port lesen
start
ack := write((adr << 1) + 1)
ifnot ack
data := read(0)
stop
PUB tx(txByte) | t
{{ Transmit a byte; blocks caller until byte transmitted. }}
PUB out(adr,data):ack 'plx: port schreiben
if txOkay
outa[sout] := !inverted ' set idle state
dira[sout]~~ ' make tx pin an output
txByte := ((txByte | $100) << 2) ^ inverted ' add stop bit, set mode
t := cnt ' sync
repeat 10 ' start + eight data bits + stop
waitcnt(t += bitTime) ' wait bit time
outa[sout] := (txByte >>= 1) & 1 ' output bit (true mode)
start
ack := write(adr << 1)
ack := (ack << 1) | write(data)
stop
if sout == sin
dira[sout]~ ' release to pull-up/pull-down
PUB ad_init(adr) 'plx: ad-wandler initialisieren
start
write(adr << 1)
write(ADDA0_INIT)
write(0)
stop
PUB str(strAddr)
{{ Transmit z-string at strAddr; blocks caller until string transmitted. }}
PUB ad_ch(adr,ch): wert 'plx: ad-wandler wert auslesen
if txOkay
repeat strsize(strAddr) ' for each character in string
tx(byte[strAddr++]) ' write the character
start
write(adr << 1)
write(ADDA0_CH0 + ch)
write(0)
stop
repeat 2 'erste messung verwerfen!
start 'da diese das ergebnis
write((adr << 1) + 1) 'der letzten messung
wert := read(1) 'liefert!
stop
PUB getreg(regnr):wert 'plx: register lesen
wert := plxreg[regnr & $0F]
PUB setreg(regnr,wert) 'plx: register schreiben
plxreg[regnr & $0F] := wert
PUB ping(adr):ack 'plx: device anpingen
start
ack := write(adr<<1)
stop
PUB setadr(adradda,adrport)
'halt
adr_adda := adradda
adr_port := adrport
ad_init(adr_adda)
'run
CON 'I2C-FUNKTIONEN
PUB start 'i2c: dialog starten
outa[SCL]~~
dira[SCL]~~
outa[SDA]~~
dira[SDA]~~
outa[SDA]~
outa[SCL]~
PUB stop 'i2c: dialog beenden
outa[SCL]~~
outa[SDA]~~
dira[SCL]~
dira[SDA]~
PUB write(data):ack 'i2c: byte senden
ack := 0
data <<= 24
repeat 8
outa[SDA] := (data <-= 1) & 1
outa[SCL]~~
outa[SCL]~
dira[SDA]~
outa[SCL]~~
ack := ina[SDA]
outa[SCL]~
outa[SDA]~
dira[SDA]~~
PUB read(ack):data 'i2c: byte empfangen
dira[SDA]~
repeat 8
outa[SCL]~~
data := (data << 1) | ina[SDA]
outa[SCL]~
outa[SDA] := ack
dira[SDA]~~
outa[SCL]~~
outa[SCL]~
outa[SDA]~
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
@ -138,3 +279,4 @@ PUB str(strAddr)
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -44,6 +44,7 @@ CON 'Signaldefinitionen --------------------------------------------------------
#8, A_SOUNDL,A_SOUNDR 'sound (stereo 2 pin)
#10, A_SDD0,A_SDCLK,A_SDCMD,A_SDD3 'sd-cardreader (4 pin)
#21, A_Bluetooth_Line 'Key-Line des HC05-Bluetooth-Moduls
#23, A_SELECT 'administra-auswahlsignal
CON 'KEY_CODES -------------------------------------------------------------------------------------
@ -82,16 +83,18 @@ KEY_F12 = 219
CON 'ADMINISTRA-FUNKTIONEN --------------------------------------------------------------------------
' +----------- ays
' |+---------- com
' || +-------- plexbus
' || |+------- rtc
' || ||+------ lan
' || |||+----- sid
' || ||||+---- wav
' || |||||+--- hss
' || ||||||+-- chiploader
' || |||||||+- dateisystem
' +------------- bluetooth
' |+------------ dfc77 receiver
' ||+----------- ays
' |||+---------- com
' |||| +-------- plexbus
' |||| |+------- rtc
' |||| ||+------ lan
' |||| |||+----- sid
' |||| ||||+---- wav
' |||| |||||+--- hss
' |||| ||||||+-- chiploader
' |||| |||||||+- dateisystem
A_FAT = %00000000_00000000_00000000_00000001
A_LDR = %00000000_00000000_00000000_00000010
A_HSS = %00000000_00000000_00000000_00000100
@ -102,6 +105,8 @@ A_RTC = %00000000_00000000_00000000_01000000
A_PLX = %00000000_00000000_00000000_10000000
A_COM = %00000000_00000000_00000001_00000000
A_AYS = %00000000_00000000_00000010_00000000
A_DCF = %00000000_00000000_00000100_00000000
A_BLT = %00000000_00000000_00001000_00000000
' |
' ym
@ -141,10 +146,15 @@ A_AYS = %00000000_00000000_00000010_00000000
' ---------------------------------------------- COM-FUNKTIONEN
#31, a_comInit
a_comTx
a_comRx '33
a_comRx '33
' ---------------------------------------------- Bluetooth-Funktionen
#35, a_bltCommand_On
a_bltCommand_Off '36
' ---------------------------------------------- RTC-FUNKTIONEN
#41, a_rtcGetSeconds 'Returns the current second (0 - 59) from the real time clock.
#40, a_rtcTest 'Test if RTC Chip is available
a_rtcGetSeconds 'Returns the current second (0 - 59) from the real time clock.
a_rtcGetMinutes 'Returns the current minute (0 - 59) from the real time clock.
a_rtcGetHours 'Returns the current hour (0 - 23) from the real time clock.
a_rtcGetDay 'Returns the current day (1 - 7) from the real time clock.
@ -162,10 +172,30 @@ A_AYS = %00000000_00000000_00000010_00000000
a_rtcGetNVSRAM 'Gets the selected NVSRAM value at the index (0 - 55).
a_rtcPauseForSec 'Pauses execution for a number of seconds. Returns a puesdo random value derived from the current clock frequency and the time when called. Number - Number of seconds to pause for between 0 and 2,147,483,647.
a_rtcPauseForMSec 'Pauses execution for a number of milliseconds. Returns a puesdo random value derived from the current clock frequency and the time when called. Number - Number of milliseconds to pause for between 0 and 2,147,483,647.
a_rtcTest '59 'Test if RTC Chip is available
a_rtcGetTime '59 'Returns the current hour, minute and second from the real time clock.
' ---------------------------------------------- DCF77-FUNKTIONEN
#60, a_dcfGetInSync 'Sync-Status senden
a_dcfUpdateRTC 'RTC Synchronisieren
a_dcfGetBitError
a_dcfGetDataCount
a_dcfGetBitNumber
a_dcfGetBitLevel
a_dcfGetTimeZone
a_dcfGetActiveSet
a_dcfStart 'DCF-Empfang starten
a_dcfStop 'DCF-Empfang stoppen
a_dcfState 'Status des DCF-Empfängers
a_dcfGetSeconds
a_dcfGetMinutes
a_dcfGetHours
a_dcfGetWeekDay
a_dcfGetDay
a_dcfGetMonth
a_dcfGetYear '77
' ---------------------------------------------- LAN-FUNKTIONEN
#71, a_lanStart 'Start Network
#81, a_lanStart 'Start Network
a_lanStop 'Stop Network
a_lanConnect 'ausgehende TCP-Verbindung öffnen
a_lanListen 'auf eingehende TCP-Verbindung lauschen
@ -175,7 +205,7 @@ A_AYS = %00000000_00000000_00000010_00000000
a_lanRXData 'Daten aus Empfangspuffer lesen
a_lanTXData 'Daten senden
a_lanRXByte 'wenn vorhanden, Byte aus Empfangspuffer lesen
a_lanIsConnected '81 'TRUE, wenn Socket verbunden, sonst FALSE
a_lanIsConnected '91 'TRUE, wenn Socket verbunden, sonst FALSE
' ---------------------------------------------- CHIP-MANAGMENT
#92, a_mgrSetSound 'soundsubsysteme verwalten
@ -200,6 +230,27 @@ A_AYS = %00000000_00000000_00000010_00000000
a_sfxKeyOff
a_sfxStop '110
' ---------------------------------------------- PLX-Funktionen
#120, a_plxRun 'plx-bus freigeben
a_plxHalt 'plx-bus anfordern
a_plxIn 'port einlesen
a_plxOut 'port ausgeben
a_plxCh 'ad-wandler auslesen
a_plxGetReg 'poller-register lesen
a_plxSetReg 'poller-register setzen
a_plxStart 'i2c-dialog starten
a_plxStop 'i2c-dialog beenden
a_plxWrite 'i2c byte senden
a_plxRead 'i2c byte empfangen
a_plxPing 'abfrage ob device vorhanden ist
a_plxSetAdr 'adressen adda/ports für poller setzen
' ---------------------------------------------- GAMEDEVICES
a_Joy 'Joystick abfragen (1 x 8bit Port)
a_Paddle 'Paddle abfragen (1 x 8bit Port 1 x Analog)
a_Pad 'Pad abfragen (1 x 8bit Port 2 x Analog)
a_SetJoy 'Port für Joystick setzen
a_SetPad '137 'Chan für Pad setzen
' ---------------------------------------------- WAV-FUNKTIONEN
#150, a_sdwStart 'spielt wav-datei direkt von sd-card ab
a_sdwStop 'stopt wav-cog
@ -209,11 +260,6 @@ A_AYS = %00000000_00000000_00000010_00000000
a_sdwPause 'player pause/weiter-modus
a_sdwPosition '156
' ---------------------------------------------- AY-SOUNDFUNKTIONEN
#200, a_ayStart
a_ayStop
a_ayUpdateRegisters
' ---------------------------------------------- SIDCog: DMP-Player-Funktionen (SIDCog2)
#157, a_s_mdmpplay 'dmp-file mono auf sid2 abspielen
a_s_sdmpplay 'dmp-file stereo auf beiden sids abspielen
@ -262,6 +308,11 @@ A_AYS = %00000000_00000000_00000010_00000000
' ---------------------------------------------- Zusatzfunktionen
a_s_dmpreg '196 'soundinformationen senden
' ---------------------------------------------- AY-SOUNDFUNKTIONEN
#200, a_ayStart
a_ayStop
a_ayUpdateRegisters
CON 'BELLATRIX-FUNKTIONEN --------------------------------------------------------------------------
' +----------